Skip to content

MCP Security & Network Access

The MCP server hands each wired-up agent a set of tools that can write to your board. This page is the trust boundary around that: what protects the endpoint, what the tools deliberately refuse, and what you take on if you expose it beyond your own machine.

ControlBehavior
Loopback bindThe server binds 127.0.0.1 on a random port, so it is not reachable from other machines and does not trigger a Windows Defender Firewall prompt. Deliberately not localhost, which can resolve to ::1 on IPv6-preferring systems, and never 0.0.0.0 unless you ask for it
Per-launch tokenEvery launch generates a fresh 32-byte random token, sent as X-Kangentic-Token. Requests without it get 401. The comparison is constant-time, so a local timing oracle cannot recover the token byte by byte
DNS rebinding protectionThe transport enforces a host allowlist (127.0.0.1, localhost, [::1], plus your configured bind address and callback host) on top of the bind
Project routing in the URLThe project ID is a path segment, so a stale config for another project cannot be replayed against the current launch

The guards below are part of the tool surface, not settings, so they hold regardless of how an agent is prompted:

  • A creation cap. Task creation is capped at 500 per app launch, enforced atomically. This is an internal circuit breaker against a looping agent, not a tunable knob, and it resets on restart.
  • Size limits at the protocol level. Titles cap at 200 characters, task descriptions at 50,000, backlog item descriptions at 10,000. An over-cap backlog description is rejected rather than silently truncated.
  • Destructive operations are explicit. Deleting a task, backlog item, column, or attachment, and moving a task, all have to be invoked by name. There is no implicit fallback.
  • Column deletion never touches a task. kangentic_delete_column refuses a column that still holds tasks, and refuses a role column (To Do or Done). Emptying it first is the caller’s separate, deliberate step; there is no force flag.
  • Cross-project relocation is scoped to To Do. Only a To Do task is guaranteed to have no live session or worktree that would be stranded in the source repository.
  • Mutating tools are annotated honestly. They carry readOnlyHint: false, so they still prompt in plan mode even though they are pre-approved in default mode.

One consequence worth stating plainly: creating a task in an auto-spawn column intentionally starts an agent, on the destination board too when relocating across projects. That is the feature, not an oversight, but it means a tool call can begin real work.

Caller identity is honest, not cryptographic

Section titled “Caller identity is honest, not cryptographic”

A spawned task session’s URL carries a third segment naming the calling session, stamped in at spawn. The agent never picks it through a tool parameter, which is what lets kangentic_send_session_message refuse self-sends, track a steer chain, and attribute a message truthfully.

A human-driven client and a Command Terminal session both dial the two-segment URL and are treated as unattributed callers rather than refused, so a message routed through a Command Terminal is indistinguishable from a person’s.

Two advanced keys, both read once at startup, are absent from the Settings UI on purpose. Edit the global config.json by hand and restart:

KeyDefaultPurpose
mcpServer.bindAddress127.0.0.1The interface the server listens on. Widening this is what actually exposes it
mcpServer.callbackHostunsetAllowlisted alongside the bind address for the DNS-rebinding check, so a client naming that host is not rejected

Locally spawned agents always get a 127.0.0.1 URL regardless of what you bind, which keeps them working for the default and for a wildcard bind, since 0.0.0.0 and :: bind loopback along with everything else.

Widening the bind alone is also not enough. A real client’s request carries a Host header naming your machine’s actual LAN or VPN address, not 0.0.0.0, so without a matching callbackHost the request is rejected by DNS-rebinding protection even though the socket accepted it.

To point an external MCP client at Kangentic, read the URL and token it already writes to .kangentic/mcp-config.json for that project and substitute the reachable host for 127.0.0.1. There is no delivery mechanism: Kangentic never pushes this config anywhere, and both the port and the token rotate on every restart, so this is a deliberate one-off rather than a durable setup.

Remote OpenCode sessions are not wired up by this. opencode attach is a stateless client to a server that was started and configured independently and earlier, with no config-push mechanism, so environment variables Kangentic sets on the attach process are never read by the running server. That holds even when the server is on the same machine.

See also:

Kangentic is free and open source. A star helps other people find it.

Star on GitHub