Skip to content
Building

Engineering notes

MCP Gateway

One secure, observable endpoint in front of every MCP server an organization runs.

Open source · MIT · TypeScript · started June 2026 · by Adeen Shukla

View source

The problem

Model Context Protocol adoption inside an organization turns into N clients × M servers very quickly. Every client carries its own credentials for every server.

There's no central policy, no usage attribution and no rate control, and one flaky server can take every agent that depends on it down with it.

MCP Gateway collapses that into client → gateway → servers: one auth surface, one policy engine, one place to look when something breaks.

How a request flows

  1. 01AuthAPI keys, OAuth2/JWT or mTLS, each resolving to a tenant
  2. 02RBACAllow/deny globs over namespaced tools and resources
  3. 03Rate limitsToken buckets per tenant and per tool, plus daily quotas
  4. 04CacheOpt-in TTL cache for idempotent tool calls
  5. 05RouterNamespaces tools as upstream__tool across stdio, HTTP and SSE

Decisions worth explaining

Deny always wins
RBAC deny rules beat allow rules, unknown tenants are rejected, and tool listings are filtered so each tenant only sees what it may call.
Tool calls are never blindly retried
Retries (exponential backoff with jitter) apply only to idempotent operations. Retrying a tool call could run a side effect twice.
Errors are never cached
Caching is opt-in per tool pattern, and an error result is never stored, so a transient failure can't become a sticky one.
One bad server can't break discovery
Every upstream sits behind a circuit breaker and health checks, and the router skips unhealthy upstreams when building tools/list.
Multi-replica from day one
Rate limits and cache can run in Redis using atomic Lua scripts, so several gateway replicas share one view of each tenant's quota.
Every hop is observable
Auth, RBAC, limits, cache and the upstream call are each an OpenTelemetry span, with Prometheus metrics and a one-line-per-request audit log.