Uber's MCP Gateway at Scale: 800 Servers and 5,000 Tools Behind One Control Surface

·10 min read·Evergreen Tools Team

In an October 2026 engineering post, Uber described the MCP Gateway it built to run the Model Context Protocol at production scale. The numbers are the story: more than 800 MCP servers and 5,000 individual tools behind a single control surface, serving roughly 60,000 agent tasks a week for thousands of engineers. It is the first publicly documented Fortune 500 MCP deployment at this size, and it answers the question most teams hit within weeks of adopting MCP: once you have dozens of tools, who governs them?

Rows of servers in a data center

800 MCP servers and 5,000 tools behind one control surface at Uber

The problem with five thousand tools

MCP adoption rarely fails at the first server. It fails at the hundredth. Each new server arrives with its own auth, its own error handling, and its own idea of what a tool call looks like. Teams rebuild the same plumbing, nobody owns tool governance, and the catalog quietly drifts out of sync with the services behind it. Uber's gateway is the answer to that drift: rather than let every team improvise, it centralizes MCP logic so that agents and services speak through one consistent, auditable path.

# The registry is the source of truth: every backend service and
# native MCP server is declared once, then exposed as governed tools.

MCP_GATEWAY = {
    'servers': 800,          # upstream MCP servers
    'tools': 5000,           # individual callable tools
    'agent_tasks_per_week': 60000,
    'consumers': 'thousands of engineers',
}

# Teams do not hand-roll MCP plumbing. They register an API and
# the gateway does the rest.

What the gateway actually does

At its core the gateway is an orchestration and routing layer. Agents call tools; the gateway resolves each call to the right server, applies policy, and returns the result. The key decision is centralization: by moving MCP logic into a single microservice, Uber gives agent-to-service interactions one execution model and removes the need for each team to reinvent core infrastructure. Existing APIs can be exposed as MCP tools without bespoke integration work, which is what made a 5,000-tool catalog tractable in the first place.

# The gateway is an orchestration + routing layer between agents
# and backend services. One execution model, everywhere.

class McpGateway:
    def route(self, agent, tool_call):
        server = self.registry.resolve(tool_call.name)
        policy = self.charter.policy_for(agent, tool_call.name)
        if not policy.allowed:
            raise ToolDenied(tool_call.name, policy.reason)
        payload = redact_pii(tool_call.args)   # automatic
        return server.invoke(payload)

# Centralizing this logic is what lets 5,000 tools share one
# consistent, auditable execution path.
A network of connected nodes

The gateway is the orchestration layer between agents and backend services

Governance in one place

The second job is governance, and this is where a gateway earns its keep. Charter policies are enforced at the tool level, so the question 'may this agent call this tool?' has a single answer rather than fifty. PII redaction runs automatically inside the gateway, before any payload leaves the trust boundary, so agents never see raw customer identifiers. And access is tiered between first-party and third-party MCP servers - the difference between a tool your own engineers built and a tool someone else's agent can reach.

# Tool-level charter policies: who may call what, and how.
# Policy lives next to the tool, not scattered across services.

CHARTER = [
    {'agent': 'internal-bot',  'tool': 'orders/*',   'access': 'read' },
    {'agent': 'internal-bot',  'tool': 'orders/refund','access': 'write'},
    {'agent': 'third-party',   'tool': 'catalog/*',  'access': 'read' },
    {'agent': 'third-party',   'tool': '*',           'access': 'deny' },
]

def allowed(agent, tool):
    for rule in CHARTER:
        if fnmatch(tool, rule['tool']) and rule['agent'] == agent.kind:
            return rule['access']
    return 'deny'

AutoCrawler keeps the catalog honest

A catalog of 5,000 tools is only useful if it is current. Uber's answer is AutoCrawler, a Cadence-powered distributed workflow that continuously scans the company's IDL registry for new services, APIs, and schema changes. When a service appears, it can be onboarded; when an API changes shape, the corresponding tool schema is refreshed. Stale tool definitions are a silent outage - an agent calls a tool that no longer matches the service behind it and gets a plausible-looking error far from the real cause.

# PII redaction runs inside the gateway, before anything leaves
# the trust boundary. Agents never see raw customer identifiers.

PII_PATTERNS = [r'\b\d{3}-\d{2}-\d{4}\b', r'[\w.]+@[\w.]+',
               r'\b4\d{3}[ -]?\d{4}[ -]?\d{4}[ -]?\d{4}\b']

def redact_pii(args):
    for k, v in args.items():
        if isinstance(v, str):
            for pat in PII_PATTERNS:
                v = re.sub(pat, '[REDACTED]', v)
            args[k] = v
    return args

# One redaction layer beats 5,000 teams each rolling their own.
Abstract representation of data streams

AutoCrawler keeps the tool catalog fresh by scanning the IDL registry

Why the pattern matters beyond Uber

The gateway is an architectural pattern, not a one-off. It turns MCP from a pile of connectors into a control surface that doubles as a security boundary. That is why enterprises are converging on it: vendors are shipping native MCP support, and large employers are pushing MCP into everyday workflows. Once MCP moves from experiment to critical business logic, the absence of a gateway becomes a governance gap, not just an engineering inconvenience.

# AutoCrawler: a Cadence-style distributed workflow that keeps the
# catalog honest by scanning the IDL registry for changes.

def autocrawler_tick(registry, idl_index):
    changed = idl_index.diff_since(registry.last_scan)
    for svc in changed.new_services:
        registry.register_mcp_server(svc)   # onboard automatically
    for api in changed.modified_apis:
        registry.refresh_tools(api)         # keep schemas current
    registry.last_scan = now()

# Stale tool schemas are a silent outage. Discovery is not optional.

A practical checklist for your own gateway

If you are scaling MCP, start with three things. One: put a single routing layer between agents and servers, so there is one place to observe and one place to change. Two: attach policy to tools, not to callers, so access rules survive team reorganizations. Three: automate discovery against your service registry, because hand-maintained tool lists rot within a quarter. Add PII redaction at the boundary and tier third-party servers separately. None of this is exotic - it is the same discipline you already apply to API gateways, now pointed at agents.

📌 Frequently Asked Questions

What is Uber's MCP Gateway?

Per Uber Engineering, it is a foundational microservice that powers all MCP interactions at Uber, acting as an orchestration and routing layer between AI agents and existing backend services and native MCP servers.

How many MCP servers and tools does Uber run?

Uber states it operates more than 800 MCP servers and roughly 5,000 individual tools in production, serving about 60,000 agent tasks per week.

What does the gateway add over a plain MCP server?

A single execution model: centralized routing, tool-level charter policies, automatic PII redaction, and tiered access between first-party and third-party servers.

What is AutoCrawler?

AutoCrawler is a Cadence-powered distributed workflow that continuously scans Uber's IDL registry for new services, APIs, and schema changes so the tool catalog stays current.

Can I use this design?

The blog describes Uber's internal architecture rather than a product, but the patterns - a centralized gateway, tool-level policy, and automated discovery - are portable to any organization running MCP at scale.