MCP gateway security

Require authentication on every gateway with API keys, Basic Auth or bearer tokens.

Every MCP gateway requires authentication - a gateway cannot be left open. An AI agent presents a credential with each request, the credential resolves to a security definition, and that definition is the agent's identity everywhere else: in sessions, in the audit log and in rate limiting.

Credential types

TypeHow the agent sends it
API keyThe X-API-Key header - the header name can be redefined through an environment variable
Basic AuthThe standard Authorization header, e.g. curl -u user:password
Bearer tokenAuthorization: Bearer <token> - a static token or a JWT verified against a JWKS endpoint, with audience and claim filters
OAuthAuthorization: Bearer <token> too, with the token obtained by the person signing in through your identity provider from inside their AI client - the gateway's OAuth field on, and a bearer token definition with an issuer and an audience in its group

Assign definitions to a gateway

The Definitions tab of the Security card on the wizard's step 01, How do agents connect?, lists the available API key, Basic Auth and bearer token definitions. Each gateway has a security group named mcp.<gateway-name> and the picker manages that group's members - the same group is visible under Security > Groups, and a member added there is shown as assigned the next time the wizard opens the gateway.

A request is accepted when any member of the group matches the presented credentials. Membership changes are live - adding or removing a member is reflected in enforcement immediately, without restarts. Changes to a definition itself, e.g. a new username, issuer or audience, apply to every gateway that uses it in the same way, and a definition that is not active authenticates no requests until it is made active again.

The group follows the gateway. A gateway renamed in the wizard, on the gateway list, through enmasse or through the API has its group renamed to mcp.<new-name> along with it, and a deleted gateway has its group deleted too, which removes the group from every other channel that uses it. The dashboard refuses a rename to a name whose group already exists and a new gateway under a name whose group another channel already uses.

A gateway may also use security groups of its own, e.g. groups imported with enmasse. The wizard and the gateway list keep those groups on every save, and the gateway list counts their members along with those of mcp.<gateway-name>. Deleting such a group under Security > Groups removes it from the gateway.

Names and URL paths

A gateway is reachable through an HTTP channel of its own, under the gateway's name and at its URL path. A gateway cannot take the name of an existing REST or SOAP channel or of another gateway, and no other channel can use a gateway's URL path, whatever HTTP method that channel accepts. The dashboard, the API and enmasse refuse such a save and name the channel that holds the name or the path, and the existing channel is left as it was.

When a JWT matches a claim-filtered bearer definition, the resolved identity is that specific definition - two definitions with different claim filters on one gateway resolve to different identities, so a session initialized with one token cannot be reused by a caller whose token resolves to the other. A definition with an identity claim goes one step further and resolves each person to an identity of their own, <definition>/<claim value>, so that two people let in by one definition are two callers. The details are on the bearer tokens page.

Rejections

A request without valid credentials never reaches any tool, and how it is refused depends on the gateway's OAuth field:

  • With OAuth off, the request is refused with HTTP 403 and an empty body.
  • With OAuth on, the request is refused with HTTP 401 and a WWW-Authenticate header naming the gateway's metadata document, from which an MCP client learns where to send the person to sign in. A request with a token the gateway did not accept also gets error="invalid_token" in the header:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://api.example.com/.well-known/oauth-protected-resource/mcp/billing", error="invalid_token"

Each rejection is logged in the server log with the gateway, the security definition and the username involved, e.g.:

log
MCP gateway `billing` rejected unauthenticated request (sec name=`partner.key` username=`partner1`)

With the audit log on, rejections are recorded too, as auth-failed events that say why the token was refused and, when it could be read, who presented it.

Sessions

A request with an MCP-Session-Id header that names no session of the caller's gets HTTP 404. This covers a session that expired, a session that belongs to another identity and a session opened before the gateway was last saved, since saving a gateway closes its sessions. An MCP client that receives the 404 opens a new session with an initialize request.

Origin validation

The Zato_MCP_Check_Origin environment variable, set to true, refuses every request that carries an Origin header with HTTP 403 and logs it. Browsers send this header with their requests, so the variable keeps web pages from calling your gateways:

log
MCP gateway `billing` rejected origin `https://evil.example` (sec name=`partner.key` username=`partner1`)

With validation off, which is the default, the header is ignored. Requests without the header, e.g. from command-line clients, are never affected either way. The value must be true in lowercase, and Zato reads it when the server starts.

Note: The same security definitions and groups also protect REST channels - one credential can serve both an agent-facing gateway and the REST APIs behind it, with one shared identity. What the shared identity means for quotas is under rate limits.

See also

FeatureWhat it does
Rate limitsTraffic caps configured on the same security definitions
Audit logHow accepted and rejected requests are recorded
Bearer tokensStatic tokens and JWTs with JWKS, audience and claim filters
OAuthSign-in through your identity provider in place of a key
REST authenticationThe same definitions and groups protecting REST channels

Learn more