Repository navigation
Releases: cmer/mcp-switchboard
Release list
v1.5.2
Fixed
- SSE servers that retired the legacy transport. Cloudflare's MCP servers (and others moving
off HTTP+SSE) now answer the SSE stream with 410 Gone, which left the server stuck on
"Unreachable · Non-200 status code (410)" and gave no hint about the fix. When an SSE server
refuses the stream (404/405/410), the switchboard now retries Streamable HTTP at the same URL
and switches the server to HTTP once that connects. OAuth servers go to Needs auth as usual.
If HTTP fails too, the error says to change the transport and URL (usually/sse→/mcp).
v1.5.1
Fixed
- Claude connectors behind chained proxies. Behind Cloudflare → Caddy (or any proxy hop that
speaks plain HTTP), the agent OAuth metadata advertisedhttp://URLs, because the inner proxy
reports its own scheme, and Claude refused to sign in. APUBLIC_URLthat ishttps://now
settles the scheme for requests to its own host, so the common one-hostname setup works without
also settingMCP_PUBLIC_URL.
Changed
- Clearer env var docs. The README now splits the variables into the admin UI's and the agent
endpoint's, spells out which OAuth directionPUBLIC_URLandMCP_PUBLIC_URLeach serve, lists
typical setups, and adds a Behind a reverse proxy section with acurlcheck for the metadata
Claude reads. The Claude connector steps now match the current dialog (full/mcp/<slug>URL,
dynamic registration, CIMD unsupported).
v1.5.0
Added
- OAuth for agents — connect Claude Desktop and claude.ai. Custom connectors in Claude Desktop
and claude.ai can't send a staticAuthorizationheader, so they couldn't reach
/mcp/<agent-slug>at all. The switchboard is now its own OAuth 2.1 authorization server for its
agent endpoints (protected-resource and authorization-server metadata, dynamic client
registration, PKCE, refresh-token rotation): paste the agent's endpoint URL into Add custom
connector and approve the connection with a one-time pairing code generated on the Agents
page. Pairing codes keep the agent's long-lived token off a web page anyone can link to. Approved
clients are listed per agent under OAuth connections and can be revoked; static bearer tokens
keep working unchanged. The endpoint must be reachable over public HTTPS, since Claude's
connectors connect from Anthropic's cloud. - CORS on
/mcp/<agent-slug>, so browser-based clients such as MCP Inspector can read the
session id and the OAuth challenge.
v1.4.3
Fixed
- OAuth no longer breaks for good when
PUBLIC_URLchanges. A dynamically registered OAuth
client is bound to the redirect URI it was registered with, so afterPUBLIC_URLchanged the
stored registration kept sending the old URI and providers rejected every attempt with
"Invalid redirect URI … does not match any registered URI for this client" (Linear's wording) —
with no way out from the UI. A registration whose redirect URI no longer matches is now discarded
and re-created on the next authorization, and a redirect-URI error explains that the provider
wants an https or loopbackPUBLIC_URL.
v1.4.2
Fixed
- Idle agent sessions are less likely to be dropped by a reverse proxy. The MCP SDK was updated
to 1.30.0, whose Streamable HTTP server transport now emits SSE keep-alive comment frames (and
fixes the keep-alive timer's lifecycle) — an agent that sits idle between tool calls no longer
looks like a dead connection to an intermediary that times out silent streams, which showed up as
a session vanishing mid-conversation. The same bump tightensContent-Typevalidation to parse
the media type instead of substring-matching it, and bounds the read buffer for stdio servers that
emit very large responses.
v1.4.1
Fixed
gitin the Docker image. stdio MCP servers installed from agit+https://…spec (e.g. via
pipx run/uvx) failed withCannot find command 'git'because the runtime image only had
python and pipx.gitandca-certificatesare now installed alongside them.
v1.4.0
Added
-
Lean mode per agent. An agent with 5–10 enabled servers can receive 100+ tool definitions —
tens of thousands of context tokens paid on every session for schemas it mostly never uses. A new
per-agent Tool exposure toggle (Agents page, default Full) switches an agent to Lean: its
tools/listshrinks to a constant-size set of meta-tools —switchboard__search_tools(ranked
lexical search over its enabled catalog),switchboard__describe_tools(full descriptions with
input/output shapes rendered as compact TypeScript instead of JSON Schema), and
switchboard__call_tool(invoke any enabled tool by namespaced name) — so tools are discovered on
demand via search → describe → call. The switch matrix still governs what is searchable and
callable, typo'd names come back with suggestions, the Logs page attributes wrapped calls to the
real upstream tool, and toggling the mode updates live sessions immediately. -
Agents can register MCP servers themselves. Discovering a useful server used to mean relaying
its config to a human to paste into the UI. An agent granted the new manager role (a per-agent
toggle on the Agents page, off by default) getsswitchboard__add_server— paste the same
claude mcp add …line ormcpServersJSON found in a README and the server is created, enabled,
and its tools appear in the same live session — plusswitchboard__assign_server,
switchboard__list_agentsandswitchboard__server_statusto manage the matrix and self-debug.
Local stdio servers are the deliberate exception: they execute a command on your machine, so no
agent can create one directly, whatever its role. -
A request/approval queue keeps humans in the loop. Every agent (manager or not) gets
switchboard__request_server: it files the ask — with a pasted config or just a reason — and
returns immediately. Pending requests show as a badge in the UI with a review panel that renders
stdio commands in a "this will execute on your machine" warning block; approving one creates the
server through the same path as the UI and pushes the new tools into the requesting agent's
still-open session. Denials carry an optional note the agent reads back with
switchboard__request_status. Stored request configs are encrypted at rest like every other
secret, and a Settings toggle hides the request tools entirely if you'd rather agents couldn't
ask. Servers created by agents show an "added by" chip for provenance, and because meta-tool
calls are ordinary MCP requests, every management action lands in the request logs.
Changed
- Calls to a server an agent lacks now fail exactly like calls to a server that doesn't exist.
The two cases used to return different errors ("not enabled for this agent" vs "unknown server"),
which let any agent probe which server slugs were configured globally. Both now return the same
Unknown servererror, so the switch matrix no longer leaks the existence of servers it hides.
Fixed
- Request logs no longer attribute
switchboard__*meta-tool calls to a phantom "switchboard"
server. Management and request meta-tools were logged withswitchboardas their upstream
server — a server that doesn't exist — polluting the Logs page's server filter. They now log with
no upstream server, like the other switchboard-native rows.
v1.3.0
v1.2.0
Added
MCP_PORTputs the agent endpoint on its own port. The UI, the REST API and the agent
endpoint all shared one port, so exposing/mcp/<agent>beyond the LAN meant exposing the admin
UI with it. SetMCP_PORTand the same process opens a second listener that serves only
/mcp/<agent-slug>— you can then firewall, tunnel or reverse-proxy that port on its own while
the UI stays on the trusted interface. Both listeners share the same database, upstream
connections and sessions.HOST/MCP_HOSTbind each listener to a specific interface, and
MCP_PUBLIC_URLoverrides the base URL shown in the connection snippets when the endpoint is
reached through a proxy or tunnel.- Request logs. A new Logs page records every JSON-RPC request an agent sent through the
switchboard and the response sent back, so "the agent says the tool failed" stops being a
guessing game. Each request is one line — time, agent, upstream server, tool name, arguments
preview, duration — that expands to the exact frames on the wire. Filter by agent, by server,
by method, or by errors / slow (>1s) / in-flight, and search across tool names, summaries and
error messages. Errors, slow calls and requests still in flight are distinguishable by shape,
not only colour. Headline counts for the last 24h (volume, error rate, median, p95) sit above
the list. - The log tails live. New requests appear as they arrive over a server-sent-events stream,
including long-running calls, which show up as in-flight the moment they start and update in
place when they finish. Some reverse proxies buffer or drop event streams; when the stream
can't be established the page falls back to polling and says so. - Log retention and payload capture are configurable in Settings → Logs. Requests are kept
for 48 hours by default and pruned automatically; shortening the window prunes immediately.
Full request/response payloads are recorded by default (capped at 32 KB per frame, with the
true size still reported) — turning capture off keeps the metadata but stores no frames, which
matters because tool arguments pass through unredacted.
v1.1.0
Added
- Light / dark / system theme switcher. The dark palette was previously locked to the OS
prefers-color-schemesetting with no way to override it. The choice now persists per
browser and, in system mode, still follows the OS live. The segmented picker sits in the
sidebar footer and in Settings → General (the sidebar is hidden below thesmbreakpoint). - Published to npm as
@cmer/mcp-switchboard, runnable withnpx @cmer/mcp-switchboard.
The package bundles the built UI alongside the compiled server, so trying the switchboard no
longer requires cloning the repo or installing Docker. Docker remains the better fit for a
long-running install.
Changed
- The data directory now defaults to
~/.config/mcp-switchboard(respecting
XDG_CONFIG_HOME) instead of./datarelative to the working directory. The old default
meant the switchboard you got depended on which directory you launched it from — harmless
under Docker, which pinsDATA_DIR, but a real hazard fornpx, where it would scatter
databases and encryption keys across the filesystem. Existing installs keep working: if a
cwd-relativedata/switchboard.dbis found and the new location is empty, it is used and a
warning points at the new path.DATA_DIRstill overrides everything. - The data directory is now created
0700. It holds the encryption key and every stored OAuth
token, and was previously world-readable (the key file itself was already0600).