MCP Gateway
A service orchestration layer for the Model Context Protocol. Manages multiple MCP services through a single unified interface — spawn, supervise, and route tool calls across all your services.
README
MCP Gateway
A service orchestration layer for the Model Context Protocol. Manages multiple MCP services through a single unified interface — spawn, supervise, and route tool calls across all your services.
Key Feature: Lazy Activate
By default, services activate in lazy mode — the process spawns and tool list is fetched, but zero tool schemas are injected into the LLM context. This means you can have hundreds of tools across dozens of services with no token overhead.
activate({name: "google-workspace"}) → 281 tools ready, 0 context tokens
tools({service: "google-workspace"}) → browse available tools
call({service: "...", tool: "...", args}) → call any tool directly
Features
- Lazy activate — spawn services with 0 context tokens, browse with
tools(), call withcall() - Service orchestration — spawn, stop, restart child MCP services
- On-demand tool browsing —
tools({service, filter})returns tool descriptions as conversation text (not system prompt) - Direct routing —
call()routes to child connections without needing schema registration - Environment variable expansion — use
$VARor${VAR}in config for secrets - Dynamic management — add/remove services at runtime without restarting
- Health monitoring — built-in ping/health checks
- Any command — supports
bun,node,npx,ssh, or any executable
Quick Start
# Install
bun install
# Create your config from the example
cp gateway.config.example.json gateway.config.json
# Edit gateway.config.json with your services
# Then start the gateway
bun run start
Configuration
gateway.config.json defines your services:
{
"services": [
{
"name": "my-service",
"command": "bun",
"args": ["run", "/path/to/service/index.ts"],
"env": { "API_KEY": "$MY_API_KEY" },
"autoActivate": false
}
]
}
| Field | Required | Default | Description |
|---|---|---|---|
name |
yes | — | Unique service identifier |
command |
yes | — | Executable to run (bun, node, npx, ssh, ...) |
args |
no | [] |
Command arguments |
env |
no | {} |
Environment variables (supports $VAR expansion) |
autoActivate |
no | false |
Start automatically on gateway launch |
keepAlive |
no | false |
Always-on: respawn with exponential backoff on crash; never GC'd when idle |
groups |
no | — | Named tool subsets for full-mode activation, e.g. {"gmail": ["send", "search"]} |
Environment Variables
Config values support $VAR and ${VAR} syntax, resolved from process.env at load time:
{
"env": { "API_KEY": "$MY_SECRET_KEY" },
"args": ["--config", "${HOME}/.config/my-service.json"]
}
This keeps secrets out of your config file. Pass them through your MCP client config (see below).
Built-in Tools
Once running, the gateway exposes these management tools:
| Tool | Description |
|---|---|
services |
List all services with status, mode (lazy/full), tool count, uptime |
activate |
Start a service. Default lazy (0 context tokens). Set lazy=false for full schema registration |
tools |
List available tools for an active service. Supports filter for keyword search |
deactivate |
Stop a service and clean up |
restart |
Kill and respawn a service (preserves lazy/full mode) |
health |
Ping all active services |
add |
Register a new service dynamically (persists to config) |
remove |
Remove a service from config |
call |
Call any tool on any active service |
Workflow
1. activate({name: "my-service"}) → spawn process, 0 tokens
2. tools({service: "my-service"}) → see all tools
3. tools({service: "my-service", filter: "search"}) → filter by keyword
4. call({service: "my-service", tool: "...", args: {}}) → call a tool
5. deactivate({name: "my-service"}) → stop when done
Full Mode (optional)
If you want tool schemas injected into the LLM context (traditional MCP behavior):
activate({name: "my-service", lazy: false}) → register all schemas
activate({name: "my-service", lazy: false, groups: ["gmail", "drive"]}) → register specific groups
HTTP Daemon Mode (always-on, shared)
Set GATEWAY_HTTP_PORT to run the gateway as a long-lived Streamable HTTP daemon instead of per-client stdio:
GATEWAY_HTTP_PORT=8770 bun run start
- Endpoint:
http://127.0.0.1:8770/mcp(Streamable HTTP,Mcp-Session-Idper client) - Health:
GET /healthreturns JSON with session count and per-service status/pid - Shared processes, isolated views: child services are spawned once and shared by every connected client; each session keeps its own tool registry, so one agent's full-mode activation never leaks into another's context
- Session GC: sessions idle longer than the TTL are swept automatically (clients often exit without sending DELETE). Tune with
GATEWAY_SESSION_TTL_MS(default 60 min) andGATEWAY_SESSION_SWEEP_MS(default 5 min) - Safe boot:
GATEWAY_NO_AUTOACTIVATE=1skipsautoActivateservices (e.g. when stateful singletons are already running elsewhere)
A systemd unit is provided in deploy/mcp-gateway.service.
Point Claude Code (or any MCP client) at the daemon:
{
"mcpServers": {
"gateway": { "type": "http", "url": "http://127.0.0.1:8770/mcp" }
}
}
Using with Claude Code
Add to your Claude Code MCP config (~/.claude/config.json or project settings).
API keys go in the env block — they're passed to the gateway process and expanded in gateway.config.json via $VAR syntax:
{
"mcpServers": {
"gateway": {
"command": "bun",
"args": ["run", "/path/to/mcp-gateway/src/index.ts"],
"env": {
"GEMINI_API_KEY": "your-gemini-key",
"EXA_API_KEY": "your-exa-key"
}
}
}
}
License
MIT
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.