Skip to main content
Glama
codespriha

mcp-router-local

by codespriha

mcp-router-local

Zero-dependency local Model Context Protocol (MCP) router. Aggregate multiple MCP servers behind a single endpoint so an LLM client (Claude Desktop, Claude Code, Cursor, or any JSON-RPC 2.0 over stdio/SSE client) connects to one router instead of managing many individual server processes.

Built on native Node.js modules only — child_process, readline, fs, path, http. No runtime dependencies, no third-party parsers, nothing to install but the router itself.

Features

  • Single endpoint aggregation — one stdio connection (or one local SSE endpoint) that fronts every configured sub-server.

  • Dynamic config discovery — reads mcp-router.config.json from the current working directory: executable paths, arguments, env vars, and per-server behavior.

  • Protocol aggregation — spawns every sub-server on startup, performs the MCP handshake, and merges tools/list, resources/list, resources/templates/list, and prompts/list into one unified capability manifest.

  • Intelligent routingtools/call, resources/read, and prompts/get are intercepted, matched to the owning sub-server, forwarded, and the response is safely returned to the client. Tool-name collisions across servers are auto-namespaced.

  • Process safety — a crashing sub-server is logged to a local debug file (never stdout, so the JSON-RPC stream stays clean) and restarted with capped exponential backoff. On exit, all children are terminated gracefully (SIGTERM → SIGKILL).

Related MCP server: Agent Aggregator

Requirements

  • Node.js ≥ 18 (ESM)

Install

npm install -g mcp-router-local   # global CLI: mcp-router
# or run without installing:
npx mcp-router-local

Quick start

Create mcp-router.config.json in the directory you'll run the router from:

{
  "servers": [
    {
      "id": "filesystem",
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
    },
    {
      "id": "db",
      "command": "python",
      "args": ["db_mcp_server.py"],
      "env": { "DATABASE_URL": "postgres://localhost/app" }
    }
  ]
}

Then start the router:

mcp-router

Point your LLM client at it. For a client that spawns servers over stdio, configure the command mcp-router (with --config <path> if needed). For example, Claude Code:

{
  "mcpServers": {
    "all-my-servers": {
      "command": "mcp-router",
      "args": ["--config", "/absolute/path/to/mcp-router.config.json"]
    }
  }
}

The router announces itself as a single server exposing the union of every sub-server's tools, resources, and prompts. From the client's perspective there is only one server.

Configuration reference

Key

Type

Default

Description

name

string

mcp-router-local

Server name sent in the initialize handshake.

version

string

0.1.0

Server version sent in the handshake.

transport.type

"stdio" | "sse"

"stdio"

Client-facing transport.

transport.host

string

127.0.0.1

SSE bind host.

transport.port

number

8765

SSE bind port.

servers[]

array

Required. At least one sub-server entry.

timeouts.initialize

number (ms)

15000

Handshake timeout per sub-server.

timeouts.list

number (ms)

15000

tools/list / resources/list / prompts/list timeout.

timeouts.call

number (ms)

60000

tools/call timeout.

timeouts.general

number (ms)

30000

resources/read / prompts/get timeout.

debug.enabled

boolean

false

Mirror warnings/errors to stderr.

debug.logFile

string

./mcp-router.debug.log

Diagnostic log path (resolved next to the config file).

Server entry (servers[])

Key

Type

Default

Description

id

string

Required. Unique id used for routing and logs.

command

string

Required. Executable to spawn.

args

string[]

[]

Arguments passed to the executable.

cwd

string

inherit

Working directory for the child process.

env

object

inherit

Extra env vars merged over the router's environment.

autoRestart

boolean

true

Restart the child after a crash.

maxRestarts

number

5

Restart attempts before giving up.

Transports

stdio (default)

mcp-router reads line-delimited JSON-RPC from stdin and writes responses to stdout. All diagnostics go to the debug file (and optionally stderr) — stdout carries only JSON-RPC, so your client never sees log noise.

SSE

Set transport.type to "sse", then:

  • GET http://host:port/sse — opens the event stream (sends event: endpoint).

  • POST http://host:port/message — accepts JSON-RPC bodies, returns 202, and pushes responses over the open stream. Requests received before a client connects are queued and drained on connect.

Handling tool-name collisions

If two sub-servers expose a tool with the same name, the router keeps the first server's name untouched and renames the later one to <serverId>__<toolName>. A warning is written to the debug log:

Tool "shared" exists on both "alpha" and "beta"; exposed as "beta__shared" to avoid collision

Call the renamed tool exactly as exposed; the router strips the prefix and forwards the original name to the owning sub-server.

Crash handling & restart backoff

When a sub-server exits unexpectedly:

  1. A clean error is written to the debug file (stderr too if debug.enabled).

  2. The router attempts a restart with exponential backoff: 1s, 2s, 4s, 8s, 15s… (capped at 15s), up to maxRestarts.

  3. On each restart the router re-runs the handshake, re-gathers capabilities, and rebuilds its routing indexes.

  4. A server that stays alive for 2 minutes resets its restart counter.

Demo

A self-contained demo ships in demo/ — no real MCP servers needed:

npm run build
node demo/run.mjs

It starts the router against two built-in mock servers (alpha and beta), runs an initialize handshake, lists the merged tools, and calls tools on both — including the collision-renamed beta__shared — then tears everything down. Open demo/mcp-router.config.json to see the shape it uses.

Development

npm install
npm run type-check   # strict TypeScript
npm run build        # tsup -> dist/index.js + dist/index.d.ts

License

MIT

F
license - not found
-
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

View all related MCP servers

Related MCP Connectors

  • Hosted MCP server for LLM cost estimation, model comparison, and budget-aware routing.

  • MCP server providing access to the Scorecard API to evaluate and optimize LLM systems.

  • Agent-native collaboration network: orchestrate a team of long-running agents from any MCP client.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/codespriha/mcp-router-local'

If you have feedback or need assistance with the MCP directory API, please join our Discord server