What the MCP gateway does
GoModel can sit between your agent clients (Claude Code, Claude Desktop, Cursor, VS Code, …) and the MCP (Model Context Protocol) servers they use — the same way it already sits between your apps and model providers:- One endpoint, one key. Clients connect to
https://your-gateway/mcpwith a GoModel API key. They never hold upstream MCP credentials; the gateway injects each server’s headers itself. - Aggregation with namespacing. Tools and prompts from every configured
server appear in one catalog as
{server}_{name}(for examplegithub_create_issue), in a stable, deterministic order. - Least-privilege discovery. A server can be scoped to
user_paths; callers outside the subtree do not merely get errors — the tools never appear in theirtools/listat all. Operator-levelallowed_tools/disallowed_toolsfilters trim noisy servers, which keeps agent context small. - Observability. Every tool call becomes a usage entry (server, tool,
duration, sizes, error flag, labels, user path) and MCP requests appear in
the audit log and request log like any other model traffic — labelled with
the JSON-RPC method, and with the tool or prompt name for calls, so a
tools/callrow readsgithub_create_issue, not a bare path. User-path rate limits and budgets gate MCP requests too.
Connect a client
Point any streamable-HTTP MCP client at the gateway and pass your GoModel key as a bearer token:/mcp— everything the key’s user path may see, namespaced./mcp/{server}— a single server with its original tool names.X-MCP-Servers: github,jiraheader — a comma-separated subset on/mcp.
Declare servers
Servers can be managed in the dashboard (MCP Servers page) or declared as infrastructure-as-code — declarative entries override same-name dashboard rows and are read-only there:MCP_SERVERS env var (a JSON object, merged over YAML per name):
| Field | Default | Meaning |
|---|---|---|
url | — | Endpoint for http (streamable HTTP) and sse transports |
transport | http | http, sse (legacy), or stdio (config-only) |
headers | — | Sent verbatim upstream; values support ${ENV} |
command, args, env | — | stdio subprocess definition |
enabled | true | Toggle without deleting |
allowed_tools | all | Allowlist of upstream tool names |
disallowed_tools | none | Blocklist, applied after the allowlist |
user_paths | everyone | Visibility subtrees, like virtual models |
tool_timeout | 30s | Upper bound for one tools/call |
url/command, unknown transport)
abort startup with a clear error rather than silently dropping the server.
Health and lifecycle
The dashboard shows each server as connected, degraded, connecting, or disabled, with tool counts and the last error, and the Overview page summarizes MCP server health whenever servers are configured. A server whose listing fails keeps its previous catalog (marked degraded) and is re-probed every 60 seconds; healthy catalogs re-list every 5 minutes and refresh immediately when the upstream sends alist_changed notification.
Reconnect on the dashboard (or POST /admin/mcp-servers/{name}/reconnect)
forces a redial.
Inspect a server’s catalog
The dashboard’s catalog inspector (orGET /admin/mcp-servers/{name}/catalog) lists exactly what a server
currently exposes through the gateway — tools, prompts, resources, and
resource templates with their descriptions, after your allowed_tools /
disallowed_tools filters. Names are the upstream originals; the aggregated
/mcp endpoint serves them as {server}_{name}.
Security notes
- Credential boundary. The MCP spec forbids token passthrough; GoModel terminates the client’s bearer token and injects per-server credentials from configuration. Client keys never reach an upstream.
- stdio is declarative-only. stdio servers spawn subprocesses on the
gateway host, so they can only be declared in
config.yaml/MCP_SERVERS. The admin API and dashboard reject them — a dashboard login must never be equivalent to code execution on the gateway. - stdio subprocesses get a minimal environment. Only
PATH,HOME,TMPDIR,USER, andLANGare inherited — never the gateway’s provider API keys or master key. Pass anything else explicitly via the server’senv:map (values support${VAR}). - Dashboard-managed credentials live in the gateway database. Headers of
admin-created servers are stored in the configured storage backend (they
are only redacted at the API/UI layer). If your threat model excludes
secrets in the database, declare those servers in
config.yaml/MCP_SERVERSinstead —${ENV}references keep the secret in the environment, and declarative servers never touch the store. - Sessions are not authentication. Every request is bearer-authenticated, and a session is additionally bound to the user path that initialized it; presenting a leaked session ID under another identity returns 404.
- Secret header values are shown redacted (
***) in the admin API and dashboard; saving a form with***preserves the stored secret.
Protocol coverage
Tools, prompts, resources, and resource templates are aggregated and relayed with raw schemas and results untouched. Upstreaminstructions are merged
into the gateway’s initialize response. Server-initiated features
(sampling, elicitation, roots) and resource subscriptions are not negotiated
in this version, which downstream clients handle transparently.