Virtual MCP Servers: Exposing Internal APIs to Agents with a Config Change A developer built a proof-of-concept MCP gateway that exposes seven internal QA services—including users, products and orders—to AI agents as virtual MCP servers defined entirely by YAML config, without modifying any backend service. Each virtual server is a config entry (name, backend URL, tool list) served by one process at its own URL, with tools mapping one-to-one onto existing REST endpoints and a file watcher that reloads the registry while retaining the last valid version on schema errors. The design mirrors Uber's MCP Gateway split between a registry control plane and a runtime proxy, keeping both inside a single process. On our team, we have been building skills for very specific tasks that call various endpoints. Some skills call the same endpoints, and many people maintained these endpoints. Some people pulled a skill to their local machine, made updates, and never pushed them back to our skills repo. I was looking into building an MCP server for these skills, but then I read about Uber's MCP Gateway https://www.infoq.com/news/2026/11/uber-mcp-gateway-ai-agents/ and its virtual MCP servers. It behaves like an API gateway, and it lets us add a new endpoint for the rest of the team with a short config change. No need to hand-build an MCP server for each set of functions. The virtual MCP servers follow the same pattern as an API gateway. With an API gateway, clients call the gateway, and the gateway routes the request to the right backend service. The client doesn't need to know where the service lives or how to call it. An MCP gateway behaves the same way. Your local AI agent calls the MCP gateway, and the gateway makes the call to the right backend service. The servers are "virtual" because none of them is a program. Normally every system an agent talks to gets its own MCP server, written, deployed and kept in sync with the service it fronts. In the gateway, a virtual server is a config entry: a name, a backend URL and a list of tools. One process serves all of them, each at its own URL, and to the agent each one looks like any other MCP server. I built a small version as a proof of concept. It runs on my laptop against our QA environment and fronts seven internal services, such as users, products and orders. None of the backend services had to change. one gateway process +-------------------------------+ | | Claude Code ----- | /shop/mcp reads |---- users, products, orders, ... | /shop-write/mcp writes |---- users, orders | | | /users/mcp |---- users | /products/mcp |---- products | /orders/mcp |---- orders | ...one URL per service | | | | registry/ .yaml defines all | +-------------------------------+ Uber splits its gateway into a registry, which is the control plane, and a proxy that does the runtime work. Mine keeps the same split inside one process. The registry is a folder of YAML files in a git repo: /