When you set out to build a first-class MCP gateway, the first decision you have to make is also the most consequential: how do you represent an MCP proxy definition at the gateway level?
Not what features to ship. Not what the UI looks like. The definition format. Get that wrong and nothing downstream works properly. After all, you can’t govern what you can’t describe.
We’ve been on this journey at Tyk, so thought you might like to come along for the ride as we share our experiences.
This isn’t just a config choice, it’s a structural one
The definition format determines everything: what you can authenticate, what you can rate-limit, what you can document, and what you can observe. It’s the contract between the developer who configures the proxy and the gateway that enforces it.
For REST APIs, this is a solved problem. OpenAPI is the industry standard. You describe your endpoints, your parameters, and your security schemes, and a generation of seasoned tooling knows exactly what to do with it. Developer portals, validators, mock servers, code generators: all of it flows from the OpenAPI definition.
MCP had no equivalent. The MCP specification defines the protocol clearly but says nothing about how a gateway should represent an MCP server for the purposes of governance. We were starting from a blank page.
The MCP Registry is interesting but solves a different problem entirely. It answers: where do I find MCP servers? Not: how do I govern one once I’ve found it? Discovery and governance are different layers. Even the MCP ecosystem’s own tooling doesn’t address the governance gap.
So that’s the gap we had to fill.
OpenAPI’s virtual endpoints pattern
MCP is JSON-RPC 2.0 under the hood. Clients send requests over POST /mcp. They can open a persistent SSE connection over GET /mcp for server-initiated messages. Everything meaningful (tool calls, resource reads, prompt retrievals) travels as a structured JSON-RPC payload inside those two endpoints.
So the question we were facing became: how do you describe a single-endpoint, method-based protocol?
The answer was already documented in the OpenAPI community. The virtual endpoints pattern for JSON-RPC treats each JSON-RPC method as a conceptual path in the OpenAPI spec – not a real HTTP endpoint, but a named, typed, documented operation that tooling can understand. It’s the established approach for making JSON-RPC APIs legible to a world built around REST documentation conventions.
The pattern gave us the north star we needed: represent each JSON-RPC method as a first-class OpenAPI operation. That discovery shaped everything that followed.
Building on strong foundations
We didn’t start from zero when building our MCP gateway. Tyk has a mature, battle-tested gateway definition format – Tyk OAS – built on OpenAPI 3.0.x and extended with our x-tyk-api-gateway vendor extension.
Tyk OAS solved the “how do you describe a non-trivial API for a gateway” problem years ago for REST. Its design philosophy is deliberate: OpenAPI is the source of truth for API semantics. The x-tyk-api-gateway extension handles everything the gateway adds and nothing else. No redundancy. Only what’s needed.
The extension organizes gateway config into four sections:
- info – API identity and state
- server – client-facing interface: listen path, authentication
- upstream – backend connectivity: URL, load balancing, TLS
- middleware – processing chains: rate limiting, transformations, CORS, plugins
Every Tyk API definition, across hundreds of enterprise deployments, follows this shape. It’s validated, versioned, documented field by field, and understood by the full Tyk toolchain. That’s what we had to build on.
Combining the two — and inventing what was missing
The OpenAPI virtual endpoints pattern showed us the right model for JSON-RPC. Tyk OAS gave us the scaffolding. The question was whether they could be made to work together. And what we’d have to invent in the gaps.
From the OpenAPI virtual endpoints pattern, we took the method model. Each JSON-RPC method ( tools/call, resources/read, prompts/get ) is represented as a documented path in the OpenAPI spec: /mcp/tools/call, /mcp/resources/read. These aren’t real HTTP endpoints. All traffic still flows through POST /mcp. But by representing each method as an OpenAPI operation, we made every JSON-RPC method a first-class entity: addressable, documentable, and governable.
From Tyk OAS, we took the extension pattern. The same four-section structure. The same validation model. The same developer experience. An MCP proxy definition looks and behaves like any other Tyk OAS definition – because it is one.
What we had to invent was primitive-level governance. MCP servers expose three categories of capability (tools, resources, and prompts). A serious gateway needs to work at that level. Our early discovery sessions highlighted the need for granular controls, such as the ability to rate limit a specific tool independently, block a specific resource URI, or restrict a specific prompt to a particular consumer tier. OpenAPI has no model for this.
What we eventually built was three primitive middleware maps inside the x-tyk-api-gateway extension – mcpTools, mcpResources, and mcpPrompts – each keyed by primitive name and each independently configurable. Enabling allow on any primitive in a category switches that entire category into allowlist mode: only the explicitly listed primitives are accessible; everything else is rejected.
{ "mcpTools": { "get-weather": { "allow": { "enabled": true }, "rateLimit": { "enabled": true, "rate": 100, "per": 60 } }, "execute-query": { "allow": { "enabled": true }, "requestSizeLimit": { "enabled": true, "value": 8192 } } } }
The result is a three-level middleware hierarchy:
- Global middleware applies to all requests
- The operations map applies per JSON-RPC method (keyed by convention: tools/callPOST, resources/readPOST)
- The primitive maps apply to individual named tools, resources, and prompts
Each level evaluates in order. Each can reject independently.
OAS for MCP
What we’ve built is OAS for MCP: a definition format for MCP proxies that is formally specified, fully documented, and understood by the complete Tyk toolchain. Developer portals, analytics, policy enforcement, versioning… all of it works, because the definition is rich enough to support it.
It’s the same idea as OpenAPI for REST. A contract precise enough that tooling can be built on top of it. A format expressive enough to capture not just what the API is, but how the gateway should behave when it’s called.
We didn’t set out to coin a phrase. But when we looked at what we’d built – an OpenAPI definition extended with the virtual endpoints pattern for JSON-RPC and our own primitive-level governance model – “OAS for MCP” was the shortest accurate description we could find.
What getting the foundation right actually unlocks
Once we nailed the definition format, everything else followed quickly. Authentication, rate limiting, per-primitive access control, analytics, developer portal integration, and security policies all landed fast, because the scaffolding was already there and we had years of technical assets and expertise to draw upon.
The result is a full MCP gateway, built from the ground up in time to matter.
And it was the definition format that made that possible.
Feed your curiosity
Read the MCP OAS definition reference to see the full structure or book a demo to see Tyk MCP Gateway in action.


