@jadchene/mcp-gateway-service
v0.5.0
Published
A token-efficient MCP gateway that provides one unified entry point for multiple downstream MCP services.
Maintainers
Readme
English | 简体中文
MCP Gateway
MCP Gateway is a lightweight Model Context Protocol gateway that exposes one small MCP entry point for multiple downstream MCP services.
Instead of flattening every downstream tool into the client at startup, the gateway exposes a fixed discovery and routing API. Agents can list services, inspect tools for one service, fetch one schema, and then forward the actual tool call.
Features
- One MCP entry point for multiple downstream MCP services.
- Token-efficient discovery through a small fixed gateway tool surface.
- Stdio and Streamable HTTP downstream transports.
- Optional inbound Streamable HTTP endpoint enabled by CLI flags.
- Hot reload for service-pool config changes.
- Stops removed, disabled, or replaced downstream services during reload.
- Restarts failed downstream processes up to three times before marking them unavailable.
- Atomic config reload that keeps the previous valid config when a new config is invalid.
- Optional newline-delimited JSON file logging that never writes operational logs to MCP stdout.
- Version reporting through
--versionor-v.
Why Use It
- Keep agent-side MCP configuration small: every agent connects to the gateway, while downstream services are managed in one config file.
- Reduce initial tool context: agents discover only the service, tool, and schema needed for the current task.
- Keep service lifecycle control centralized instead of duplicating command paths, environment variables, and secrets across multiple clients.
Quick Start
Install globally:
npm install -g @jadchene/mcp-gateway-serviceCreate a local config:
cp config.example.json config.jsonStart the stdio gateway:
mcp-gateway-service --config ./config.jsonStart with inbound Streamable HTTP:
mcp-gateway-service --config ./config.json --http --host 127.0.0.1 --port 3100 --path /mcpUse stateless JSON responses for HTTP clients that expect direct JSON-RPC responses from POST:
mcp-gateway-service --config ./config.json --http --port 3100 --path /mcp --json-responseCheck the installed version:
mcp-gateway-service --version
mcp-gateway-service -vConfiguration
Pass the config file by CLI argument:
mcp-gateway-service --config ./config.jsonOr by environment variable:
MCP_GATEWAY_CONFIG=./config.json mcp-gateway-serviceIf neither is provided, the service tries config.json in the current working directory.
Config example:
{
"logging": {
"enable": false,
"path": "./logs/mcp-gateway.log"
},
"services": [
{
"serviceId": "demo-echo",
"enable": true,
"name": "Demo Echo Service",
"description": "Sample echo MCP service.",
"transport": {
"type": "stdio",
"command": "node",
"args": [
"--experimental-strip-types",
"examples/echo-service.ts"
]
}
},
{
"serviceId": "remote-http",
"enable": false,
"name": "Remote Streamable HTTP Service",
"description": "Example downstream MCP service over Streamable HTTP.",
"transport": {
"type": "http",
"url": "http://127.0.0.1:3200/mcp",
"headers": {
"Authorization": "Bearer ${MCP_TOKEN}"
},
"enableJsonResponse": false
}
}
]
}Configuration notes:
logging.enabledefaults tofalse.logging.pathis required only whenlogging.enableistrue.- Relative
logging.pathvalues are resolved from the config file directory. - Service
enabledefaults totrue; setting it tofalseskips that service. cwdandenvare optional for stdio services.- Stdio
transport.framingmay belineorcontent-length. When omitted, the gateway trieslineand thencontent-length. - HTTP downstream services use
transport.type: "http"andtransport.url. - HTTP
transport.headersprovides static request headers. - HTTP
transport.enableJsonResponseenables stateless JSON response mode for that downstream service.
Inbound Streamable HTTP
Inbound HTTP is enabled only with --http. Passing --host, --port, --path, or --json-response without --http does not start an HTTP listener.
The HTTP endpoint uses the same path for GET and POST:
GET /mcpopens the SSE read channel and returns the session in theMcp-Session-Idresponse header.POST /mcpsends JSON-RPC messages. New clients should bind the session through theMcp-Session-Idrequest header.- Query-string
sessionIdis accepted for compatibility. - The
endpointSSE event advertises the single path, such as/mcp.
Gateway Tools
The gateway exposes six public tools:
| Tool | Purpose |
| --- | --- |
| gateway_list_services | List downstream services with each logical serviceId, description, and current availability. |
| gateway_get_service | Return one service's identity, availability, recent error and connection time, protocol version, and server information. Use this for diagnostics. |
| gateway_list_tools | Search tool names or descriptions by case-insensitive literal substrings. Optional unique non-empty toolName and desc arrays use OR; includeSchema: true includes schemas. |
| gateway_get_tool_schema | Return schemas for unique exact, case-sensitive tool names. Results are keyed by name, and any unknown name fails the whole request. |
| gateway_manage_service | Reconnect without changing config, or persistently enable/disable a service in the config and reload the registry. |
| gateway_call_tool | Call one exact downstream tool and forward its result unchanged. The downstream tool may have read or write side effects. |
Default token-efficient workflow:
- Call
gateway_list_servicesonce. - Call
gateway_list_tools(serviceId)only when a service is needed. Use atoolNamearray for name keywords and adescarray for description keywords. - When all filtered matches need schemas, pass
includeSchema: true; when exact tool names are already known, callgateway_get_tool_schemawith a non-empty name array. - Call
gateway_call_toolto execute the downstream tool. - Use
gateway_get_serviceonly for diagnostics. - Use
gateway_manage_serviceonly to reconnect, enable, or disable a service.
gateway_get_tool_schema.toolName is a required unique non-empty string array and returns a schemas object keyed by each requested exact tool name. Use a one-element array when requesting one schema.
gateway_list_tools.toolName and gateway_list_tools.desc are optional unique non-empty string arrays. Matching is case-insensitive and uses literal substrings. When both are present, a tool is returned when either its name or description matches any supplied keyword. Description matching can also hit negative guidance such as "when not to use", so inspect the returned descriptions before selecting a tool.
All gateway tools with stable structured content expose an outputSchema. gateway_call_tool intentionally omits a fixed output schema because it forwards arbitrary downstream results. Its arguments object is always required; pass {} for a downstream tool with no arguments.
gateway_manage_service actions:
reconnect: retry the current downstream lifecycle without modifying config.enable: persistenable: truefor the service and reload config.disable: persistenable: falsefor the service and reload config.
Skill Integration
This repository includes a public gateway skill:
- Skill path:
skills/mcp-gateway/SKILL.md
Use it when your agent supports skills. It keeps discovery token-efficient and routes downstream calls through the minimal gateway contract.
MCP Client Configuration
Codex:
[mcp_servers.gateway]
command = "mcp-gateway-service"
args = ["--config", "./config.json"]Gemini CLI:
{
"mcpServers": {
"gateway": {
"type": "stdio",
"command": "mcp-gateway-service",
"args": ["--config", "./config.json"]
}
}
}Claude Code:
{
"mcpServers": {
"gateway": {
"type": "stdio",
"command": "mcp-gateway-service",
"args": ["--config", "./config.json"]
}
}
}Streamable HTTP mode:
Start one shared HTTP gateway process first:
mcp-gateway-service --config ./config.json --http --host 127.0.0.1 --port 3100 --path /mcpThen point MCP clients at the HTTP endpoint.
Codex:
[mcp_servers.gateway]
url = "http://127.0.0.1:3100/mcp"Gemini CLI:
{
"mcpServers": {
"gateway": {
"httpUrl": "http://127.0.0.1:3100/mcp"
}
}
}Claude Code:
{
"mcpServers": {
"gateway": {
"type": "http",
"url": "http://127.0.0.1:3100/mcp"
}
}
}Use the same URL for every client that should share the gateway service pool. Use --json-response only when your HTTP client expects stateless JSON-RPC responses directly from POST requests.
Development
npm install
npm run devBuild and test:
npm run build
npm testRun the built server:
node dist/index.js --config ./config.jsonLicense
MIT. See LICENSE.
