Documentation Index
Fetch the complete documentation index at: https://tyk.io/docs/llms.txt
Use this file to discover all available pages before exploring further.
This page covers the technical foundation for working with Tyk’s MCP Gateway: the gateway’s role in the protocol flow, the MCP protocol concepts it builds on, the session lifecycle, the proxy definition, middleware levels, and the policy model for per-consumer access control and rate limiting.
The gateway role
Without a gateway, AI agents connect directly to MCP servers over HTTP. Each server is responsible for its own authentication, access control, and rate limiting, or has none at all. There is no central point to see which agents are calling which tools, no consistent way to revoke access, and no protection against a slow or unavailable server. For the full picture of why this creates operational risk at scale, see MCP Gateway overview.
Tyk sits between MCP clients and your upstream MCP servers. Unlike a generic reverse proxy that treats all traffic as an opaque HTTP stream, Tyk understands the MCP protocol. It parses the JSON-RPC request body on every POST /mcp to identify the method being called and the specific primitive being accessed. This is what makes primitive-level control possible.
Because Tyk knows that a particular request is a tools/call for get_current_weather (not just a POST to /mcp), it can:
- Rate limit that tool independently, without affecting other tools on the same server
- Block access to a specific resource URI without restricting the entire resources category
- Enforce a timeout on a slow tool without affecting fast tools
- Strip that tool from
tools/list responses for consumers whose policy does not permit it
- Record the exact tool name in analytics so you can see precisely which primitives agents are calling
The fundamental difference from a REST proxy is how operations are identified. REST APIs use URL paths and HTTP methods: Tyk routes GET /weather differently from GET /weather/forecast. MCP routes all traffic through a single endpoint and identifies the operation from the request body:
REST API (Tyk OAS):
GET /weather → weather current conditions
GET /weather/forecast → weather forecast
MCP proxy (Tyk MCP):
POST /mcp { "method": "tools/call", "params": { "name": "get-weather" } }
POST /mcp { "method": "tools/call", "params": { "name": "get-forecast" } }
MCP proxies share the same authentication mechanisms, policy engine, and analytics infrastructure as your REST and GraphQL APIs. The body inspection is the only difference in how operations are identified and matched.
MCP definitions are supported in Tyk OAS format only. They are not available as Tyk Classic API definitions.
Transport
MCP uses Streamable HTTP as its transport. The MCP specification defines a single endpoint path (/mcp) that supports two HTTP methods with distinct roles. Tyk proxies both.
POST /mcp: JSON-RPC messages. Clients send JSON-RPC 2.0 messages to POST /mcp. The upstream MCP server can respond with:
200 application/json: a single JSON-RPC response, for operations that complete immediately.
200 text/event-stream: a Server-Sent Events stream carrying multiple JSON-RPC messages, used when the server streams results or sends progress notifications.
202 Accepted: an acknowledgement for JSON-RPC notifications that do not expect a response body.
Tyk executes the middleware chain against the incoming POST request (authenticating, applying rate limits, checking allowlists) and then proxies it to the upstream. Tyk preserves the response content type and streams SSE responses through to the client without buffering or transforming the body.
GET /mcp: Server-Sent Events. Clients open a persistent GET /mcp connection to receive server-initiated messages. The upstream MCP server uses this channel to push progress notifications, resource update notifications, and server-to-client requests such as sampling/createMessage. Tyk proxies the SSE stream transparently, maintaining the long-lived connection for the duration of the session.
MCP defines several protocol-specific headers that Tyk passes through unchanged in both directions:
| Header | Direction | Purpose |
|---|
MCP-Protocol-Version | Client → Server | Required. Specifies the MCP protocol revision (for example, 2025-11-25). |
Mcp-Session-Id | Server → Client, then Client → Server | Session identifier. Returned by the server after initialization; clients echo it on subsequent requests. |
Last-Event-ID | Client → Server | SSE resume token sent when reconnecting to a GET /mcp stream. |
Origin | Client → Server | Used by servers for origin-based security validation. |
The client and upstream MCP server handle version negotiation and session management. Tyk does not modify any MCP protocol headers.
What is MCP?
New to MCP? The MCP introduction is a good starting point before reading further.
The Model Context Protocol (MCP) is an open standard that defines how AI applications connect to external tools, data sources, and services. It uses a client-server model: an MCP client (an AI agent, LLM orchestration framework, or application) connects to an MCP server that exposes capabilities, and the two communicate using JSON-RPC 2.0 messages carried over HTTP.
Tyk supports the 2025-11-25 revision of the MCP specification.
Primitives
MCP servers expose three types of capability, collectively called primitives.
| Primitive | Description | Discovery method | Invocation method |
|---|
| Tool | A callable function that takes structured arguments and returns a result. Used for actions and computed queries. | tools/list | tools/call |
| Resource | A readable data source identified by a URI. Used for documents, files, and live data feeds. | resources/list | resources/read |
| Prompt | A reusable prompt template the server exposes for common tasks. | prompts/list | prompts/get |
Each primitive has a name (or URI for resources) that uniquely identifies it within the server:
- A
tools/call request names the tool in params.name
- A
resources/read request names the resource URI in params.uri
- A
prompts/get request names the prompt in params.name
This name is what Tyk uses to apply primitive-level middleware and policy controls.
Client-side primitives
MCP also defines primitives that run in the opposite direction: capabilities that servers can request from clients rather than expose themselves.
| Primitive | Description | Method |
|---|
| Sampling | Server requests the client to perform LLM inference on its behalf and return the result. | sampling/createMessage |
| Roots | Server requests the list of filesystem roots (directories or URIs) the client is willing to share. | roots/list |
| Elicitation | Server requests structured input from the user, mediated through the client. | elicitation/create |
Tyk passes client-side primitive messages through to the upstream and back. Primitive-level middleware configuration (rate limits, access control, timeouts) applies to server-side primitives only.
Every MCP operation is a JSON-RPC 2.0 message sent to POST /mcp. Each message carries a method field that identifies the operation and, for invocation requests, a params object that names the specific primitive being accessed.
A typical tool call looks like this:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "get_current_weather",
"arguments": { "location": "London" }
}
}
The method field identifies the category of operation: tools/call in this example. The params.name field identifies the specific tool. Tyk reads both fields on every incoming POST /mcp request to determine which middleware to execute before forwarding to the upstream.
JSON-RPC methods
The MCP specification defines a fixed set of JSON-RPC method names, grouped into four categories.
| Method | Category | Description |
|---|
initialize | Session | Opens the session and negotiates capabilities. |
notifications/initialized | Session | Client confirms session is ready. |
tools/list | Tools | Returns the list of tools the server exposes. |
tools/call | Tools | Invokes a named tool with the supplied arguments. |
resources/list | Resources | Returns the list of resources the server exposes. |
resources/read | Resources | Reads the content of a named resource URI. |
prompts/list | Prompts | Returns the list of prompt templates the server exposes. |
prompts/get | Prompts | Retrieves a named prompt template, optionally with arguments. |
sampling/createMessage | Sampling | Requests the client to perform LLM sampling on behalf of the server. |
notifications/tools/list_changed | Notifications | Server-initiated notification that the tool list has changed. |
Tyk can apply rate limits, access control, and middleware at the method level (for example, capping all tools/call requests) and at the primitive level (for example, rate limiting a specific named tool). The distinction matters: method-level controls apply to every invocation of that method regardless of which primitive is named; primitive-level controls apply only when that specific tool, resource, or prompt is requested.
Session lifecycle
MCP is a stateful protocol. When a client sends an initialize request, the upstream server responds with an Mcp-Session-Id header. The client includes this identifier on all subsequent requests, allowing the server to associate them with the established session context. Tyk passes the header through unmodified and does not maintain session state itself.
A typical session proceeds through four phases.
- Handshake: the client and server negotiate capabilities and establish a session identifier.
- Discovery: the client queries the server’s available tools, resources, and prompts.
- Invocation: the client calls primitives; Tyk applies rate limiting, access control, and observability on each request.
- Session close: the client terminates the session; the session identifier is invalidated.
Handshake
Tyk authenticates the initialize request before proxying it to the upstream. The upstream responds with an Mcp-Session-Id header that Tyk passes through to the client unchanged. The client confirms readiness with a notifications/initialized message, and the session is established.
Discovery
Once the session is open, the client calls tools/list (and optionally resources/list and prompts/list) to learn what the server exposes. Tyk intercepts the upstream’s response and strips any primitives the consumer is not permitted to see, based on the policy attached to their key. The client receives a filtered view of the server’s capabilities.
Invocation
Each primitive call passes through Tyk’s full middleware chain. Rate limiting, access control, and observability all fire on every tools/call request. If the consumer’s policy permits the named tool and rate limits allow the request, Tyk proxies it to the upstream and returns the response. This phase repeats for every tool, resource, or prompt the client invokes.
Session close
When the client has finished, it sends DELETE /mcp with the Mcp-Session-Id header. Tyk proxies the request to the upstream, which terminates the session. After session close, the Mcp-Session-Id is invalid; a new initialize request is required to open a new session.
If the GET /mcp SSE connection drops, the client can reconnect by opening a new GET /mcp request with the Last-Event-ID header set to the ID of the last event received. Tyk passes this through to the upstream, which resumes the stream from that point.
The proxy definition
The MCP proxy definition is the configuration object that describes the proxy. It is a Tyk OAS API definition, an OpenAPI 3.0 document extended with x-tyk-api-gateway, and it is both the single source of truth for everything about the proxy and its registry entry: the listen path, the upstream URL, authentication, middleware, and versioning.
The x-tyk-api-gateway extension has four top-level sections:
| Section | What it configures |
|---|
info | API name, active state, and internal identifier |
server | Client-facing settings: listen path, authentication, IP access control, custom domain |
upstream | Upstream MCP server: target URL, load balancing, upstream rate limits, mTLS |
middleware | Request processing: global, per-method, and per-primitive middleware |
A minimal MCP proxy definition looks like this:
{
"openapi": "3.0.3",
"info": { "title": "Weather MCP proxy", "version": "2025-11-25" },
"paths": {
"/mcp": {
"post": { "operationId": "mcpTransportPost", "responses": { "200": { "description": "JSON-RPC response" } } },
"get": { "operationId": "mcpSSEGet", "responses": { "200": { "description": "SSE stream" } } }
}
},
"x-tyk-api-gateway": {
"info": {
"name": "Weather MCP proxy",
"state": { "active": true }
},
"server": {
"listenPath": { "value": "/weather/", "strip": true },
"authentication": { "enabled": true }
},
"upstream": {
"url": "https://weather-mcp.example.com"
}
}
}
Clients connect to Tyk at https://my-gateway.example.com/weather/mcp. Tyk authenticates the request, applies any configured middleware, and proxies it to https://weather-mcp.example.com/mcp. Tyk serves both the POST and GET transport endpoints under the same listen path.
You manage MCP proxy definitions through the Tyk Gateway API (at /tyk/mcps) or the Tyk Dashboard. For the full definition structure and field reference, see MCP OAS definitions.
Every tool, resource, and prompt on an MCP server has a name (or URI for resources) that uniquely identifies it within that server. Understanding how names are assigned, and how Tyk uses them, is a prerequisite for configuring primitive-level middleware, blocking specific tools, or writing policies with allowlists and blocklists.
In MCP Proxy pass-through mode (Tyk proxying an existing MCP server), tool names come from the upstream server verbatim. Tyk does not modify or namespace them. If the upstream server exposes a tool named get-weather, that is the name Tyk uses for middleware matching, policy rules, and analytics.
In HTTP-to-MCP translation mode (Tyk converting a REST API into MCP tools via AI Studio), tool names are derived from the operationId field of each OpenAPI operation. An operation with operationId: getWeatherForecast becomes a tool named getWeatherForecast. If your OpenAPI spec does not set operationId on every operation, Tyk cannot create a stable tool name. Adding operationId values to every exposed operation is a prerequisite for this mode.
Discovery filtering applies at the tools/list, resources/list, and prompts/list level. When a client requests the list of available primitives, Tyk intercepts the upstream’s response and removes any entries that the consumer’s policy does not permit. The client only sees and can only call the primitives its key is authorized to access.
Name collisions: When proxying multiple MCP servers behind a single gateway, or when combining proxy pass-through and HTTP-to-MCP translation, tool names from different upstream servers may collide. Each MCP proxy definition is a separate Tyk API with its own listen path, so collisions are isolated per proxy: a tool named search on one proxy does not conflict with search on another. However, if you are using a single proxy to aggregate multiple upstream MCP servers (via the mcp-registry plugin), ensure that upstream tool names do not overlap, or use the plugin’s namespacing configuration to prefix tool names per upstream.
Middleware
Tyk applies middleware to MCP traffic at three levels, all configured in the x-tyk-api-gateway.middleware section of the proxy definition. The levels are evaluated in order from broadest to most specific.
Global middleware
Global middleware applies to every request that reaches the proxy, before any method-level or primitive-level processing. Use it for server-wide concerns: CORS configuration, traffic logging, header injection into upstream requests, or custom plugins that should run on all traffic.
Operation middleware
Operation middleware applies to all requests for a specific JSON-RPC method, regardless of which primitive is called. Configure it in middleware.operations, keyed by the JSON-RPC method name with its HTTP method suffix (for example, tools/callPOST). Use it for method-wide policies, such as a rate limit that applies to all tools/call requests without distinguishing between individual tools.
{
"middleware": {
"operations": {
"tools/callPOST": {
"rateLimit": { "enabled": true, "rate": 500, "per": 60 }
}
}
}
}
This rate limit applies to every tools/call request, regardless of which tool is named in params.
Primitive middleware
Primitive middleware applies to a specific tool, resource, or prompt. Configure it in one of three maps (middleware.mcpTools, middleware.mcpResources, or middleware.mcpPrompts), keyed by the primitive’s identifier: the tool name, resource URI (or URI pattern), or prompt name.
{
"middleware": {
"mcpTools": {
"execute-query": {
"allow": { "enabled": true },
"rateLimit": { "enabled": true, "rate": 10, "per": 60 }
}
}
}
}
This configuration allowlists the execute-query tool and applies a rate limit of 10 requests per minute, independently of any other tools on the same proxy.
When both operation-level and primitive-level middleware are configured, both apply. A tools/call request to execute-query must pass the operation-level limit (500/min for all tool calls) and the primitive-level limit (10/min for this tool). Access control follows the same pattern: allowlisting specific tools in mcpTools puts the entire tools category into allowlist mode, blocking any tool not explicitly listed.
Tyk evaluates the three primitive categories (tools, resources, and prompts) independently. Allowlisting a tool has no effect on whether resources or prompts are accessible.
See MCP middleware for the full list of available capabilities: access control, request and response transformation, traffic management (rate limiting, timeouts, circuit breakers), virtual endpoints, and observability controls.
Policies
A Tyk security policy is a reusable template of access rights and usage limits that you apply to one or more API keys. You define a policy once and issue keys that inherit its rules automatically, rather than configuring each key individually. When you update the policy, every key bound to it picks up the change.
Policies give you per-consumer control at every level of the MCP protocol:
- Proxy access: control which MCP proxies a consumer key can reach
- JSON-RPC method access: restrict which protocol operations a consumer can use (for example, allow
tools/call but block sampling/createMessage)
- Primitive access: define per-consumer allowlists and blocklists for individual tools, resources, and prompts, using regular expressions to match by name
- Per-primitive rate limits: set independent rate limits on specific primitives, so a consumer exhausting their quota on one tool does not affect their access to others
- Quotas: cap total call volume over a renewal period
Primitive access control is enforced at two points in the MCP protocol.
At invocation time: Tyk checks tools/call, resources/read, and prompts/get requests against the consumer’s permitted primitives. Blocked calls return a JSON-RPC error before the request reaches the upstream.
At discovery time: Tyk intercepts tools/list, resources/list, and prompts/list responses from the upstream and strips out any primitives the consumer cannot see. Each consumer receives a filtered view of the server’s capabilities from the moment they connect.
Policies versus middleware
Both middleware and policies can enforce limits on MCP primitives, but they operate on different subjects.
Middleware applies to all traffic through the proxy: a primitive rate limit in mcpTools caps the call rate for a tool across every caller combined. It protects the upstream from overload.
Policies apply per consumer. A primitive rate limit in a policy caps the call rate for one specific key, with each consumer’s counters tracked independently. This is how you enforce different entitlements for different consumers: a standard tier with read-only access and lower limits, a premium tier with access to sensitive tools and higher quotas.
The two work together: middleware sets the ceiling for all traffic, policies determine what each consumer is entitled to within that ceiling.
See MCP proxy policies for the full configuration reference, Dashboard UI walkthrough, and API examples.