Skip to content

Releases: wellknownmcp/cortex-gateway

v0.2.0 — security controls for a federating gateway

Choose a tag to compare

@wellknownmcp wellknownmcp released this 20 Jul 11:18

A gateway that federates N backends sees things a single MCP server does not: every backend's tool definitions, the transport to each of them, and the full call path from agent to application. This release adds the controls that follow from that position. All of them are documented, with their limits, in docs/security.md.

Tool definition integrity (rug-pull detection)

A backend that rewrites an approved tool's description or inputSchema keeps the name — the client's approval still looks valid while the model reads different instructions. The gateway now fingerprints scope, description, params, inputSchema, version and deprecated at first sight and re-checks them at every refresh, reporting added / removed / mutated with the changed field names. Key order is normalized, so a reserialized schema is not a false positive.

CORTEX_TOOL_INTEGRITY_MODE=warn    # default: log + push tools/list_changed, serve the new definition
CORTEX_TOOL_INTEGRITY_MODE=block   # quarantine: withheld from tools/list, refused at tools/call

In block mode the baseline keeps the approved definition, so a mutation stays reported instead of quietly becoming the new normal. A backend absent from a refresh is not treated as a withdrawal unless it actually answered — otherwise going briefly unreachable would launder a rewritten definition into a fresh approval.

The baseline lives in the process and is rebuilt at boot: this is mutation detection during a process's lifetime, not attestation. A persistent, operator-signed baseline is the next step.

Outbound transport policy

Every federated call forwards the caller's bearer token. Plaintext HTTP to a remote host is now refused at load — the backend is dropped with an error while the others keep serving. Loopback stays allowed (stdio bridge, local development). CORTEX_ALLOW_INSECURE_BACKENDS=true opts out for a private network with transport security at another layer, and warns on every load.

The same policy applies to URLs the gateway did not choose: in the adapter's discovery path (RFC 9728 → RFC 8414), the issuer and the authorization / token / registration endpoints all come from the remote server's metadata. Each is validated before use, and a discovered endpoint cross-origin to its issuer is logged. This is the class of bug behind CVE-2025-6514.

Audit attribution

target_app and scope_used were written as null on every line. They are now resolved from the federated catalog for tools/call and from the URI scheme for resources/read; gateway marks a builtin. Without them, the audit trail of a federating gateway can only say which tool name was called.

Baseline scope

Per-tool scopes are the authorization model, but the builtins (whoami, list_cortex_resources, ...) require none by design — so without a floor, any valid token for this audience reaches them.

OAUTH_REQUIRED_SCOPES=mcp:access   # unset keeps the previous behaviour

Also

  • The linking callback no longer interpolates a provider-supplied error string into HTML unescaped.
  • X-Cortex-Backends is now documented, in the server instructions and inline, as a context-size optimization and not an access control: it narrows what tools/list shows, never what a token may call.

Upgrading

No breaking change with default configuration. Two things to check before deploying: a backend configured over remote http:// will now be dropped (switch it to https, or set CORTEX_ALLOW_INSECURE_BACKENDS=true deliberately), and CORTEX_TOOL_INTEGRITY_MODE defaults to warn — set it to block once you have seen a few refreshes come back clean.

Image: ghcr.io/wellknownmcp/cortex-gateway:v0.2.0

v0.1.0 — first public release

Choose a tag to compare

@wellknownmcp wellknownmcp released this 04 Jul 16:32

First public release.

Cortex Gateway is a self-hosted, federated MCP gateway: one spec-compliant, OAuth 2.1-protected MCP server (Streamable HTTP, MCP 2025-06-18) in front of N plain-HTTP backends. Permissions are never mirrored — the gateway propagates the real user identity, so each app's native permission model applies per user.

Highlights

  • Federation: backends implement a single POST endpoint (~120-line contract, no MCP library); the gateway discovers tools every 60s, merges them into one catalog with <backend>_ prefixes, and routes tools/call to the owning backend (SSE tools/list_changed push included).
  • OAuth 2.1 resource server: RFC 9728 discovery (401 + WWW-Authenticate), scope-filtered tools/list — scopes double as plan entitlements, zero paywall code.
  • Identity propagation: your JWT to first-party backends (RFC 8707 audience), the user's own linked token to proxied third-party MCP servers.
  • MCP→backend proxy adapter (beta): federate native MCP servers, with a per-user AES-256-GCM token vault and OAuth/DCR/PKCE downstream discovery. Unit-tested against the spec, not yet against a commercial provider — beta means beta.
  • Self-describing backends + agent feedback loop: get_help convention pushed in server instructions; report_missing_capability / list_cortex_tickets builtins (deduplicated, triaged, optionally backend-owned).
  • Agent-ready surfaces: server icons + websiteUrl (2025-11-25 spec fields), /llms.txt on the gateway itself, AGENTS.md with verifiable claims.
  • Demo authorization server included: OAuth 2.1 with DCR, PKCE, strict refresh rotation, magic-link signup, consent, scope tiering (RFC 8414/7591/7009/7662).

Try it

Live demo (plug into claude.ai → Settings → Connectors → Add custom connector):

https://mcp.cortex-gateway.dev/mcp

Self-host:

docker run ghcr.io/wellknownmcp/cortex-gateway:v0.1.0

Docs: backend contract · deployment runbook · cortex-gateway.dev

Validated end-to-end on 2026-07-04: claude.ai Custom Connector → magic link → consent → scope-filtered tools/list → tools/call.