MCP Gateways and Registries — Enterprise Control Planes
A gateway is where an enterprise decides which MCP servers its developers can reach. It centralizes auth, RBAC, audit, rate limiting, caching, and tool-poisoning detection, then exposes the merged tool surface as a single MCP endpoint. The Official MCP Registry (Anthropic, GitHub, PulseMCP, and Microsoft, namespace-verified) is the canonical upstream. This lesson shows where a gateway fits, walks a minimal implementation, and surveys the 2026 vendor landscape.
Learning Objectives
- Explain where an MCP gateway sits (between MCP clients and multiple backend MCP servers).
- Implement the five gateway responsibilities: auth, RBAC, audit, rate limit, policy.
- Enforce a pinned-tool-hash manifest at the gateway layer.
- Differentiate the Official MCP Registry from metaregistries (Glama, MCPMarket, MCP.so, Smithery, LobeHub).
The Problem
Picture a Fortune 500 with 30 approved MCP servers, 5000 developers, compliance and audit requirements, and a security team that wants one place to set policy. Letting each developer install whatever server they like in their IDE doesn't survive the first compliance review.
The gateway pattern fixes this:
- The gateway runs as a single Streamable HTTP endpoint that developers connect to.
- It holds the credentials for each backend MCP server.
- Every developer request is authenticated and scoped through the gateway's own OAuth.
- The gateway routes the call to the backend server and applies policy on the way.
- Every call is logged for audit.
Cloudflare MCP Portals, Kong AI Gateway, IBM ContextForge, MintMCP, TrueFoundry, and Envoy AI Gateway all shipped gateways or gateway features in 2025-2026.
The Official MCP Registry launched alongside them as the canonical upstream: curated, namespace-verified, reverse-DNS-named servers that a gateway can pull from. Metaregistries (Glama, MCPMarket, MCP.so, Smithery, LobeHub) aggregate servers across several sources.
The Concept
Five gateway responsibilities
- Auth. OAuth 2.1 to identify the developer; maps to user roles.
- RBAC. Per-user policy: which servers, which tools, which scopes.
- Audit. Every call logged with who, what, when, result.
- Rate limit. Per-user / per-tool / per-server caps to prevent abuse.
- Policy. Reject poisoned descriptions, enforce Rule of Two, redact PII.
Gateway as a single endpoint
To developers, the gateway looks like one MCP server. Internally it routes to N backends. Session ids (Phase 13 · 09) are rewritten at the boundary.
Credential vaulting
Developers never see backend tokens. The gateway holds them (or proxies to an identity provider that does). A developer with notes:read on the gateway may transitively access the notes MCP server with the gateway's own backend credentials, but only under a policy that binds the transitive access.
Tool-hash pinning at the gateway
The gateway holds a manifest of approved tool descriptions (SHA256 hashes). At discovery time, it fetches each backend's tools/list, compares hashes to the manifest, and removes any tool whose description has mutated. This is the rug-pull defense from Phase 13 · 15 applied centrally.
Policy-as-code
Advanced gateways express policy in OPA/Rego, Kyverno, or Styra. Rules like "user alice may call github.open_pr only on repos in org acme" are encoded declaratively. Simple gateways use hand-coded Python. Both work.
Session-aware routing
When a user's session includes a mix of servers, the gateway multiplexes: the developer's single MCP session holds N backend sessions, one per server. Notifications from any backend route through the gateway to the developer's session.
Namespace merging
Gateways merge tool namespaces from all backends, typically with prefix-on-collision. github.open_pr, notes.search. This makes routing unambiguous.
Registries
- Official MCP Registry (
registry.modelcontextprotocol.io). Launched under Anthropic, GitHub, PulseMCP, Microsoft stewardship. Namespace-verified (reverse-DNS:io.github.user/server). Pre-filtered for basic quality. - Glama. Search-centric metaregistry aggregating many sources.
- MCPMarket. Commercial-leaning directory with vendor listings.
- MCP.so. Community directory; open submissions.
- Smithery. Package-manager-style installation flow.
- LobeHub. UI-integrated registry in their LobeChat app.
Enterprise gateways pull from the Official Registry by default, allow admin-curated additions from metaregistries, and reject anything unpinned.
Reverse-DNS naming
Official Registry mandates reverse-DNS names for public servers: io.github.alice/notes. Namespaces prevent squatting and make trust delegation clearer.
Vendor survey, April 2026
| Vendor | Strength |
|---|---|
| Cloudflare MCP Portals | Edge-hosted; OAuth integrated; free tier |
| Kong AI Gateway | K8s-native; fine-grained policy; logs to OpenTelemetry |
| IBM ContextForge | Enterprise IAM; compliance; audit export |
| TrueFoundry | DevOps-leaning; metrics-first |
| MintMCP | Developer-platform oriented |
| Envoy AI Gateway | Open-source; customizable filters |
Phase 17 (production infrastructure) goes deeper on gateway operations.
Use It
main.py is a minimal gateway in about 200 lines. It authenticates users by a fake Bearer token, holds a per-user RBAC policy, routes calls to two in-process stub backends (notes and github), writes every authenticated tools/call decision (allow, forbidden, rate_limited, hash_mismatch) to an audit log, enforces a rate limit, and rejects any backend tool whose description hash doesn't match a pinned manifest.
What to look at:
- The
RBACdict, keyed by user id, with the allowedserver.toolnames. AUDIT_LOG, an append-only list of events.- The rate limiter, a token bucket per user (capacity 5, refilling 1 token per second).
- The pinned manifest, a dict of
server::tool -> hash.
Ship It
This lesson produces outputs/skill-gateway-bootstrap.md. Given an enterprise MCP plan (users, backends, compliance), the skill produces a gateway configuration spec.
I'd run main.py first and read the printed output against the code. Alice and bob see different tool lists from the same gateway, bob's call to github.open_pr comes back 403, and a burst of eight calls from alice gets some of them rate limited. The demo ends by mutating a notes tool description on the backend, and the hash check drops it from alice's list and answers 409 on a call.
The part I'd read twice is where the pin comes from. pin_manifest hashes the backend descriptions when the module loads, so the manifest is only as trustworthy as the backend was at that moment. That is a decent stand-in for a reviewed manifest in a demo, but in a real gateway the hashes should come from an approval step, not from whatever the server says at startup.
I'd also be honest about what the sketch leaves out. The policy responsibility in the five-item list is covered only by hash pinning here. There is no PII redaction (exercise 2 adds it), no Rule of Two check, and no session id rewriting, because the backends are in-process stubs. The rate limiter keeps its buckets in memory, so a restart resets everyone to a full bucket, and tools/list drops a mutated tool without writing anything to the audit log, which is a gap I'd close before trusting it.
Exercises
-
Run
main.py. Make a call as an allowed user; then as a disallowed user; then a rate-limit-exceeded burst. Verify all three flows. -
Add a policy that redacts PII from results before returning to the client. Use a simple regex pass for SSN-shaped strings; note the gap (emails, phone numbers).
-
Extend the audit log to emit OpenTelemetry GenAI spans. Phase 13 · 20 covers the exact attributes.
-
Design an RBAC policy for a 50-developer team with five backends (notes, github, postgres, jira, slack). Who gets read-only on each? Who gets write?
-
Read the Cloudflare enterprise MCP post top to bottom. Identify one feature Cloudflare ships that this stdlib gateway does not.
Key Terms
| Term | What people say | What it actually means |
|---|---|---|
| Gateway | "MCP proxy" | Centralizing server between clients and backends |
| Credential vaulting | "Backend tokens stay server-side" | Developers never see upstream tokens |
| Session-aware routing | "Multi-backend session" | Gateway multiplexes N backend sessions per developer session |
| Tool-hash pinning | "Approved manifest" | SHA256 of every approved tool description; blocks rug-pulls centrally |
| RBAC | "Per-user policy" | Role-based access control for tools and servers |
| Policy-as-code | "Declarative rules" | OPA/Rego, Kyverno, Styra policies enforced at gateway |
| Audit log | "Who, what, when" | Append-only event log for compliance |
| Rate limit | "Per-user token bucket" | Per-minute caps to prevent abuse |
| Official MCP Registry | "Canonical upstream" | registry.modelcontextprotocol.io, namespace-verified |
| Reverse-DNS naming | "Registry namespace" | io.github.user/server convention |
Further Reading
- Official MCP Registry: canonical upstream, namespace-verified
- Cloudflare: Enterprise MCP: gateway pattern with OAuth and policy
- agentic-community: MCP gateway registry: open-source reference gateway
- TrueFoundry: What is an MCP gateway?: feature comparison article
- IBM: MCP context forge: enterprise gateway from IBM
Code
- main.py (python, 197 lines)