What a gateway is
- A host:
mcp-{handle}.noorle.com, matched by the handle you chose. - An MCP server, speaking Streamable HTTP.
- A capability surface: whichever built-ins, plugins, and connectors you bound, presented as tools.
- Its own OAuth authorization server. A token minted for one gateway does not work on another.
Transport
Streamable HTTP, and only Streamable HTTP. The MCP service is mounted as the router’s fallback, so it answers on the origin root — there is no separate/sse endpoint and no WebSocket endpoint anywhere on the gateway.
Practical consequences:
- A
POSTmust send anAcceptheader containing bothapplication/jsonandtext/event-stream, or it is rejected with 406. - Responses come back as
text/event-streamframes on the POST response. SSE is the response encoding, not a separate channel. - SSE keep-alive is disabled.
- For clients on protocol revision
2026-07-28or later,GETreturns 405. That is what the revision prescribes; resumable SSE viaLast-Event-IDis not supported.
GET stream, for compatibility.
The advertised protocol-version fallback is 2025-11-25. A client asking for a version the transport knows gets that version echoed back; only an unknown version falls back.
What the gateway implements
The gateway advertises tools only.
There is no resource implementation and no prompt implementation. A gateway serves tools.
notifications/tools/list_changed is never sent. When you change a gateway’s bindings, connected clients are not notified.
The tool list is per caller
Two callers hitting the same gateway can legitimately get different lists. Membership differs. Tools that need a workspace to write into — all of Files, all of Sandbox, and Browser’sscreenshot / pdf / snapshot — are withheld from a caller with no authenticated identity. They are removed from tools/list and from the discovery corpus, so they cannot be reached by name either.
Annotations differ. Each listed tool carries a spec-native readOnlyHint derived from its risk tier, plus a dev.noorle/autonomy entry in _meta carrying the outcome that caller would get. The outcome is caller-specific because the account’s deny ledger is caller-keyed.
Denied tools stay listed rather than disappearing. Omitting them would churn the surface on every policy edit and would hide a deliberate “exposed but never autonomous” configuration.
The annotation carries an outcome and no reason — tools/list is reachable unauthenticated on a public gateway, and the reason would name the account’s policy internals.
Caching
tools/list responses carry ttlMs: 300000 (five minutes) and cacheScope: "private".
cacheScope is always private, on every gateway, precisely because of the two paragraphs above. Neither value is configurable.
The TTL is a freshness hint, not a snapshot guarantee. The list can change before it expires, and staleness never grants authority — a stale allow annotation is re-evaluated at dispatch and can still be denied.
Workspace anchoring
When a gateway tool needs storage — a file write, a sandbox, a screenshot — the workspace it writes into is derived server-side from the gateway id and the authenticated user id. Nothing comes off the wire for this. In particular the client-sentMcp-Session-Id header is never consulted: it is client-chosen and unvalidated, and modern clients do not send one at all.
An anonymous caller on a public gateway gets no workspace. Rather than inventing one, the platform withholds the tools that would need it.
The gateway id is part of the derivation, so one principal bound to two gateways gets two separate workspaces.
Authentication
Three auth modes per gateway:- Public — no authentication. Anonymous callers get the reduced tool list described above.
- Private — a credential is required.
- Private with dynamic registration — same, plus
/oauth/registeraccepts dynamic client registration. This is the default.
ak- is an API key, eyJ is a JWT, anything else is rejected.
A JWT is admitted only if it validates against that gateway’s issuer, carries the mcp scope, matches the gateway’s account, and lists that gateway’s resource URN in its audience. There is no cross-gateway fallback.
An API key is admitted if it is valid, belongs to the account, and its principal holds Read on the gateway.
After authentication, a billing check runs. No budget returns 402 Payment Required; a failure to check returns 503.
Each gateway is its own authorization server
mcp-{handle}.noorle.com serves /oauth/authorize, /oauth/token, and /oauth/register, plus RFC 9728 protected-resource metadata and RFC 8414 authorization-server metadata.
jwks_uri is null on purpose: platform OAuth tokens are HS256-symmetric, and publishing a JWKS would mean publishing the signing secret.
There is no device authorization endpoint on a gateway.
Human consent for /oauth/authorize is handed to the Portal carrying only an opaque handoff id. All protocol validation — client, registered redirect URI, PKCE, resource indicator — happens at the gateway before that hop.
Rate limits
Two limiters, both fixed 60-second windows, both keyed on(gateway, caller). An anonymous caller keys on peer IP rather than sharing one bucket with every other anonymous caller.
Both defaults ship unset in every environment overlay, so these are the live values.
Scope caveat worth planning around: the request limiter covers the path that resolves caller context, so
tools/call and tools/list share one budget. initialize and ping sit outside it, which is why the handshake cap is a separate middleware.
Both limiters fail open if Redis is unreachable.
Other hard limits: a 4 MiB maximum POST body and a 240-second server-side request timeout, after which the gateway returns 504.
Autonomy on a gateway
An MCP gateway is an unattended surface. There is no live channel to ask a human on. That means a tool call which would pause for approval is instead denied, with reasonnon_interactive_surface. Pinning a tool as always-ask on a gateway is a deterministic deny, not a prompt.
Per-gateway policy carries a level, an allow_autonomous list, and an always_ask list. Saving a gateway policy is load-bearing: its presence enables gating regardless of the account-level toggle, and it supersedes per-user auto-approve caches on that gateway — Act-tier tools and above deny until they are listed in allow_autonomous.
Which system tools appear
Almost none. Journal tools are agent-only. Skills tools need an agent id, which a gateway call has none of. Form-rendering tools need an interactive surface. Computer isAGENT-scoped and never appears.
The workflow tools are the only system tools on a gateway, listing the workflows attached to it.
Troubleshooting
Next: Capabilities — what you bind to a gateway. For the product overview, see the MCP gateway page.