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 sourceThe 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
- 01AuthAPI keys, OAuth2/JWT or mTLS, each resolving to a tenant
- 02RBACAllow/deny globs over namespaced tools and resources
- 03Rate limitsToken buckets per tenant and per tool, plus daily quotas
- 04CacheOpt-in TTL cache for idempotent tool calls
- 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.