Local MCP Server
A registered node can run an MCP server on 127.0.0.1 — its local server. An operator grant starts it, and nobgp mcp install points Claude Desktop or Claude Code at it — so the assistant on that machine gets the machine itself, and the rest of its noBGP network too.
This is the counterpart to the public server at https://mcp.nobgp.com/mcp. The public server speaks for you across every network you belong to; a node's local server speaks for that machine, from inside its network, with no round trip to the router for the things the node already knows.
This page is the guide — how to turn the endpoint on and get Claude talking to it. For the tool-by-tool catalogue — every tool marked with the surfaces that expose it — plus the concepts behind them (tiers, node references, selectors, execution identity) and the error codes, see the MCP Reference.
Why use it
- It works when the router doesn't.
statusandresolveare answered on the box, so they still work while the control channel is down — the first thing to check when the hosted tools start failing. - It reaches machines nothing else can. The other nodes in the network sit behind NAT, CGNAT and firewalls.
ssh,scpandcurlwon't get there; the proxied tools will. - Events arrive by push. Subscribe once and the server tells the client when events land, instead of the client polling. See Waiting without polling.
Connect Claude to a node
The server is grant-driven: an Owner or Admin grants the node a role with node_grant, and the agent starts the local endpoint within seconds of the grant landing. Until then there is nothing on 127.0.0.1 to register — so grant first, install second:
Grant studio-mac observe access over the production network
Then run this on the node, from your own user account:
nobgp mcp install
The install needs root, because the endpoint and token it copies out live in the root-owned profile config. On Linux and macOS it re-executes itself under sudo, so sudo nobgp mcp install works too. On Windows there's no auto-elevation — run it from an Administrator terminal.
Root privileges required, re-executing with sudo...
Installing the noBGP MCP server for user "alice" (profile "default"):
Claude Desktop /Users/alice/Library/Application Support/Claude/claude_desktop_config.json
Claude Code /Users/alice/.claude.json
Continue? [Y/n] y
registered with Claude Desktop (/Users/alice/Library/Application Support/Claude/claude_desktop_config.json)
registered with Claude Code (/Users/alice/.claude.json)
MCP server ready at http://127.0.0.1:51843/mcp
This node holds an operator-granted role — 17 network tools available through the proxy.
Restart Claude to pick this up — it reads its server list only at launch.
Restart Claude and ask it something only that machine knows:
What's the noBGP status of this machine?
Claude's configuration is a per-user file, so getting the account wrong succeeds silently. Under sudo the command resolves your real account (SUDO_USER), writes that account's configuration and hands the file back to you afterwards. Run as root with no SUDO_USER at all — a root login shell, a provisioning script — and it configures root's Claude: it warns and defaults the prompt to no.
Before it registers anything, nobgp mcp install makes sure there is a server to register. It flips no switch — the grant is what starts the server — it just checks and waits:
- Starts the agent service if it isn't running.
- Names the reason an install can never succeed, rather than waiting out the timeout for it:
this node has no MCP role yet — a network operator must grant one first (node_grant, or the app), then retry
- Waits up to 30 seconds for an endpoint that actually answers.
A server that never comes up fails the install rather than registering a port nobody holds.
Once the registrations are written it opens one throwaway session against the live endpoint and counts the router tools the grant actually exposes — the 17 network tools line above. That count tracks the tier: 17 at observe (as granted above), 24 at manage, plus the node's own two local tools either way. A zero count is reported as could not verify right now, not as a missing grant: a serving server already proves the grant is there.
Options:
| Option | Short | Description |
|---|---|---|
--yes | -y | Skip the confirmation prompt (for scripts) |
--profile | Which agent profile to bridge to (default: default) |
What gets written
nobgp mcp install adds one entry to each Claude configuration that already exists on the machine. It never creates a configuration for a Claude that isn't installed, and a file it cannot parse is left untouched and reported rather than replaced.
| Client | Configuration file |
|---|---|
| Claude Desktop (macOS) | ~/Library/Application Support/Claude/claude_desktop_config.json |
| Claude Desktop (Windows) | %APPDATA%\Claude\claude_desktop_config.json |
| Claude Desktop (Linux) | ~/.config/Claude/claude_desktop_config.json |
| Claude Code | ~/.claude.json |
The registration takes one of two shapes, because the clients differ.
Claude Code speaks streamable HTTP itself, so it talks to the agent directly — no bridge process at all:
{
"mcpServers": {
"nobgp": {
"type": "http",
"url": "http://127.0.0.1:51843/mcp",
"headers": { "Authorization": "Bearer <token>" }
}
}
}
Claude Desktop launches STDIO servers only, so it gets nobgp mcp stdio as a bridge, with the same two values in the entry's environment:
{
"mcpServers": {
"nobgp": {
"command": "/usr/bin/nobgp",
"args": ["mcp", "stdio", "--profile", "default"],
"env": {
"NOBGP_MCP_URL": "http://127.0.0.1:51843/mcp",
"NOBGP_MCP_TOKEN": "<token>"
}
}
}
}
Either way the credential lands in the client's own configuration, owned by the account that runs Claude. That's the point of the sudo step: the token reaches an account because a sudoer ran one command for that account, not because a file was left readable — nothing user-land ever opens the agent's config directory.
What is per-account is the distribution, not the credential. mcp-token belongs to the profile, so every account the install was run for holds the same token and the endpoint cannot tell them apart. Two consequences worth planning for:
- There is no way to revoke one account's access on its own. The token changes only when the profile loses it, and that invalidates every registration on the machine — each account then has to re-run
nobgp mcp install.nobgp mcp uninstallremoves registrations, not the token; the switch that takes the endpoint away from every local account at once isnode_revokeat the router. - On a machine with local logins you don't fully trust, install only for accounts that should have the node's MCP reach. What that reach covers is decided by the
node_grantat the router, not by anything on the box.
The cost of freezing those values into a client config is that they have to stay true. The port only moves if something else takes it, and the token only changes if the profile loses it; either way nobgp mcp status reports the endpoint as not responding, and re-running the install repairs it.
There is a single nobgp entry per Claude configuration. Installing a second profile replaces the first — the command says so before it does it, rather than silently unhooking the profile you set up last week.
Check it
nobgp mcp status
server: http://127.0.0.1:51843/mcp (responding, per the Claude Code registration)
Claude Desktop: registered (/Users/alice/Library/Application Support/Claude/claude_desktop_config.json)
Claude Code: registered (/Users/alice/.claude.json)
status needs no root: it reads the endpoint out of the registration — your own Claude configuration — and only falls back to the agent's root-owned state, which is why the line names its source. The server line is a live probe, not a file read, so an endpoint that has moved reports — NOT responding instead of a confident lie. With nothing registered yet and no readable agent state it reports unknown.
For the other half — whether the router has granted this node a role — use nobgp status, whose mcp block reports granted, running and port separately.
Remove it
nobgp mcp uninstall
This removes the nobgp entry from every Claude configuration on the machine, leaving everything else in those files alone. Restart Claude afterwards.
It needs no root, because it touches only your own account's Claude configuration. It deliberately leaves the agent side alone:
- The server keeps running — stopping it is the grant's job (
node_revoke). mcp-portandmcp-tokenare left in place. They are the running server's state, and other accounts on the machine may still be registered against them.
What the node exposes
The local server answers two tools itself. Both are pure reads of on-box state, and both advertise that (readOnlyHint, idempotentHint, closed world), so a client that auto-approves on hints doesn't stop to ask about them:
| Tool | What it does |
|---|---|
status | This node's agent status — identity, network and overlay address, transport, DNS, live sessions. Answered locally, so it works while the router is unreachable. |
resolve | Resolve a peer name to the overlay address this node would use, straight from the directory the router pushed. No round trip. |
Both hand back a node_id beside the address — each targets[] entry in status, and the result of resolve. That is the identifier every proxied tool takes as its target, so a name seen here can be acted on directly, with no round trip to network_directory. The address cannot: overlay addresses are minted per node, so the same peer has a different one on every machine and an address carried elsewhere points at the wrong host. Names and node ids travel; addresses do not.
Their full response fields are in the MCP Reference.
Everything else — commands, files, diagnostics, the event bus on the node's peers — is the router's surface, reached through the node. The tool catalogue lists every one of them with its parameters and the tier it needs.
One control turns all of it on, and it lives at the router: the node_grant an Owner or Admin writes. It both starts the node's local MCP server and scopes what its proxied calls may do to peers. There is no on-device switch — nothing on the machine has to be set, or can be set, to make the endpoint appear or disappear.
An ungranted node serves nothing at all on 127.0.0.1 — not even its own two tools. Grant it a role and the server starts within seconds; revoke the grant and the server stops. A grant does not time out on its own — it stands until it is revoked. The port and token stay in the profile config either way, so a re-grant rebinds the same endpoint and already-registered Claude clients resume without a re-install.
To take the endpoint off a machine, node_revoke it at the router. That reaches the fleet with no on-box action, so a machine whose owner is not its operator is governed the same way as one you run yourself. What the node will actually serve once granted is still the owner's say: the capability keys (allow-tools, allow-roots, allow-admin) refuse work on the box regardless of who asked. Since agent 0.4.33 they cover a published terminal service too, so turning the tools off closes that door as well — plan on-device access before narrowing a node you cannot reach physically.
With a grant in place, tools/list on the local endpoint returns the node's own tools plus the router tools a node context may reach, already filtered to what will actually be allowed. Local names win on a collision, and a proxy failure degrades to the local list rather than failing the session. A grant that changes mid-session pushes notifications/tools/list_changed, so a connected client refetches the list instead of holding a stale one.
A granted node can operate on the machines in its own network. It cannot create, destroy, bill or grant: no provisioning, no network or organization management, no service publishing, and no labelling — which would otherwise let a node widen its own reach over its peers. Nodes in other networks need the public server. Call tools/list for the authoritative inventory, and see the MCP Reference for what each tier holds.
Waiting without polling
This is the reason to prefer a node's local endpoint over the public one for monitoring. Each subscription is exposed as an MCP resource — nobgp://events/<subscription_id> — so a client subscribes once and is told when events land:
- Create a subscription with
fs_subscribe,presence_subscribe, orfs_grep_subscribe— orcommand_subscribe, which a node needs themanagetier of itsnode_grantto call. - Call
resources/subscribeonnobgp://events/<subscription_id>. - The server sends
notifications/resources/updatedas events arrive;resources/readdrains them.
No polling loop, and it keeps working between turns — which is what makes it the right way to wait for a long command to finish or a file to change. Reading still keeps the subscription alive, and event_tail still works as the fallback for a client that doesn't consume notifications.
Event push goes through the router's queue, so it needs the proxy path to be usable. Where it isn't, resources/subscribe is refused with a reason rather than silently never firing.
See Monitoring & Events for the subscription workflow itself, and Events and subscriptions in the reference for the event shape, lifetime rules and the exact resources/read payload.
Configuration
| Config File Key | Description | Default |
|---|---|---|
mcp-port | Loopback port to prefer. The agent binds this port when it's free, otherwise asks the OS for one and writes that back here, so a restart usually lands on the same port | (remembered) |
mcp-token | Bearer token for the server, minted by the agent on first start and written back here. One token per profile, shared by every account it is installed for. Durable on purpose — a token that changed on every restart would invalidate every registration nobgp mcp install wrote | (remembered) |
api-socket-group | Group (name or numeric gid) granted access to the agent's local API socket. Unix only | (unset) |
api-socket-mode | Octal mode for that socket, e.g. "0660". Only meaningful together with api-socket-group | 0600 |
There is deliberately no on/off key for the local surface. The grant is the single control: a node that serves MCP locally and one that forwards to the router are the same intent, the router filters every proxied call against the grant anyway, and a loopback listener is strictly less reach than the operator holding that grant already has. That is what lets an operator provision a fleet from the app with nothing to run on each box.
mcp-port and mcp-token are written by the agent itself, into the root-owned 0600 profile config. You don't set them by hand — nobgp mcp install reads them as root and copies them into the client configuration for you.
The server is loopback-only and enforces that bearer token on every request. Those two config values are the endpoint — there is no discovery file to read or keep in step. (Older agents wrote one at <config-dir>/<profile>-mcp.json; a leftover is deleted at agent start.)
Troubleshooting
"this node's MCP server is not running"
Either the agent isn't up, or the node holds no node_grant — nothing starts the server without one. nobgp status separates the two: its mcp block reports granted and running. nobgp mcp install names a missing grant before it waits, and nobgp service status covers the agent itself.
Claude shows the server but every call fails
Claude Desktop's bridge answers the handshake locally when the agent is unreachable, so a server that appears connected but can't do anything usually means the agent is down or restarting. It recovers on its own once the agent is back — no need to restart Claude.
nobgp mcp status says the endpoint is NOT responding
The registered port or token no longer matches what the agent is serving — the port was taken by something else while the agent was down, or the profile lost its token. Re-run nobgp mcp install to repair the registration, then restart Claude.
Claude doesn't see the new server
Claude reads its server list only at launch — restart it. Verify the entry landed with nobgp mcp status.
Peer tools are missing from tools/list
The node's node_grant decides which router tools appear, and the list is filtered to what a call would actually be allowed to do — a narrower role means a shorter list. Revoking the grant stops the server outright. Grant changes take effect on the node's next call, and a connected client is told to refetch the list; there's no session to restart.
Next Steps
- MCP Reference - The full tool catalogue for both surfaces, with concepts and error codes
- Monitoring & Events - Subscribe to file changes, fleet commands, and node presence
- node_grant - Grant and revoke a node's reach over its peers
- CLI Reference - Full
nobgp mcpcommand reference - Public MCP Server - The other surface, for anything a node cannot reach