Skip to main content
Glama
README.md
# mcp-toolmux

`mcp-toolmux` is an independent MCP proxy-style tool multiplexer that exposes a small set of meta-tools and routes calls to downstream MCP servers with concurrency control, caching, and structured partial-failure handling.

It is inspired by callmux, but it is not a full clone. The current release focuses on a practical proxy shape: downstream registry, exposure modes, meta-tools, direct qualified calls, parallel calls, batch calls, dependent pipelines, tool search, schema compression, status, and lightweight caching.

中文说明:这是一个独立的 MCP proxy 项目,用来把多个下游 stdio MCP server 汇聚成一个上游可调用的 MCP server。本项目不是简单 demo,而是一个独立的 MCP 工具调用多路复用项目,目标是逐步完善工具路由、并发调度、批处理、流水线、缓存和协议层优化能力。

## Architecture

```mermaid
flowchart LR
  Client["Codex / Claude MCP client"] --> Proxy["mcp-toolmux stdio MCP server"]
  Proxy --> Meta["Meta-tools\nstatus / search / call / parallel / batch / pipeline"]
  Meta --> Registry["Downstream registry\nqualified + unqualified names"]
  Registry --> Search["Tool search\ncompressed summaries"]
  Meta --> Cache["Read-tool cache\nTTL + max entries"]
  Registry --> Fake["fake stdio MCP server"]
  Registry --> Other["other trusted stdio MCP servers"]
```

## Features

- stdio MCP proxy server
- downstream MCP server registry from config
- tool exposure modes: `standard` and `meta-only`
- meta-tools: `toolmux_status`, `toolmux_search_tools`, `toolmux_call`, `toolmux_parallel`, `toolmux_batch`, `toolmux_pipeline`
- direct qualified tool calls in standard mode, using names like `server__tool`
- unqualified tool calls when the tool name is not ambiguous
- global concurrency limit for parallel calls
- `toolmux_batch` for multiple argument sets against the same downstream tool
- `toolmux_pipeline` for serial dependent tool chains
- input mapping with `$previous`, `$previous.result`, and `$steps.N.result`
- `toolmux_search_tools` for downstream tool discovery
- schema compression for compact tool summaries
- partial failure handling with `failedIndexes`
- lightweight TTL cache for read-style tool names

`toolmux_parallel` is for independent tool calls.
`toolmux_batch` is for multiple argument sets against the same tool.
`toolmux_pipeline` is for dependent tool chains where later steps consume earlier outputs.

## Tool Exposure Modes

`standard` exposes meta-tools and qualified downstream tools. This mode is useful when you want transparent tool lists and direct calls such as `fake__echo`.

`meta-only` exposes only `toolmux_*` meta-tools. Downstream tools are discovered through `toolmux_search_tools` and invoked through `toolmux_call`, `toolmux_parallel`, `toolmux_batch`, or `toolmux_pipeline`.

## Tool Search and Compression

`toolmux_search_tools` searches downstream tools by tool name, qualified name, description, and server name. It returns compressed summaries instead of full tool definitions by default.

Compressed tool summaries include:

- `name`
- `server`
- `qualifiedName`
- truncated `description`
- `required`
- `inputProperties`
- optional `inputSchema`

## Not Implemented Yet

- HTTP/SSE listener
- auth, dashboard, and metrics
- advanced policy controls
- persistent cache

The project is still evolving and does not yet include HTTP/SSE listener, auth, dashboard, advanced policy controls, or persistent cache.

## Install

```bash
npm install
```

## Build

```bash
npm run build
```

## CLI Usage

```bash
npm install
npm run build

node dist/cli.js --help
node dist/cli.js init --output mcp-toolmux.config.json
node dist/cli.js doctor --config examples/mcp-toolmux.config.json
node dist/cli.js tools --config examples/mcp-toolmux.config.json
node dist/cli.js serve --config examples/mcp-toolmux.config.json
```

`serve` starts the stdio MCP server mode. Logs are written to stderr so MCP protocol messages on stdout stay clean.

`doctor` checks config shape, defaults, command availability, and common mistakes before you start the proxy.

`tools` briefly connects to downstream MCP servers and prints compressed downstream tool summaries as JSON.

`init` creates a starter standard-mode config and refuses to overwrite an existing file.

## Run the Fake Server

The fake server is meant to be launched by the proxy after build:

```bash
npm run build
node dist/examples/fake-mcp-server.js
```

## Run the Proxy

Use the example config:

```bash
npm run build
node dist/src/index.js --config examples/mcp-toolmux.config.json
```

The proxy always exposes six MCP meta-tools:

- `toolmux_status`
- `toolmux_search_tools`
- `toolmux_call`
- `toolmux_parallel`
- `toolmux_batch`
- `toolmux_pipeline`

In `standard` mode it also exposes qualified downstream tools such as `fake__echo`.

## Example Config

```json
{
  "mode": "standard",
  "schemaCompression": {
    "enabled": true,
    "descriptionMaxLength": 180,
    "includeInputSchema": false,
    "includeRequired": true
  },
  "servers": {
    "fake": {
      "command": "node",
      "args": ["dist/examples/fake-mcp-server.js"]
    }
  },
  "maxConcurrency": 5,
  "cache": {
    "enabled": true,
    "ttlSeconds": 300,
    "maxEntries": 256
  }
}
```

By default, `mcp-toolmux` reads `mcp-toolmux.config.json` from the current directory. Pass `--config path` to use another file.

## Tests

```bash
npm test
```

The handler tests use a mock upstream manager to keep the test suite fast. The fake MCP server remains available for manual stdio testing.

## Security Note

Only configure trusted MCP server commands. `mcp-toolmux` never accepts arbitrary commands from tool input, and downstream server commands must come from the config file. Treat downstream MCP servers as executable code with your local privileges.