mcp-compress-router 1.5.2 → 1.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -20,6 +20,9 @@
20
20
  - [The Solution](#the-solution)
21
21
  - [Prerequisites](#prerequisites)
22
22
  - [Quick Start](#quick-start)
23
+ - [1. Connect your coding agent](#1-connect-your-coding-agent)
24
+ - [2. Add downstream MCP servers](#2-add-downstream-mcp-servers)
25
+ - [3. Verify and use](#3-verify-and-use)
23
26
  - [Configuration](#configuration)
24
27
  - [Config File Location](#config-file-location)
25
28
  - [Adding Downstream Servers](#adding-downstream-servers)
@@ -29,17 +32,12 @@
29
32
  - [Inspecting Tools](#inspecting-tools)
30
33
  - [OAuth](#oauth)
31
34
  - [Redirect URL](#redirect-url)
32
- - [GitHub MCP (special case)](#github-mcp-special-case)
33
- - [Figma MCP (special case)](#figma-mcp-special-case)
35
+ - [GitHub MCP with OAuth (special case)](#github-mcp-with-oauth-special-case)
36
+ - [Figma MCP with OAuth (special case)](#figma-mcp-with-oauth-special-case)
34
37
  - [Custom Headers](#custom-headers)
35
38
  - [Secrets and Variable Expansion](#secrets-and-variable-expansion)
36
- - [Connecting Coding Agents](#connecting-coding-agents)
37
- - [Opencode](#opencode)
38
- - [Claude Code](#claude-code)
39
- - [Codex](#codex)
40
- - [GitHub Copilot](#github-copilot)
41
39
  - [How It Works](#how-it-works)
42
- - [Aknowledgements](#acknowledgements)
40
+ - [Acknowledgements](#acknowledgements)
43
41
 
44
42
  ## The Problem
45
43
 
@@ -95,17 +93,99 @@ have, the more you save.
95
93
 
96
94
  The router is published on npm as
97
95
  [`mcp-compress-router`](https://www.npmjs.com/package/mcp-compress-router).
98
- You do not need to install it — just run it with `npx`:
96
+ You do not need to install it — just run it with `npx`.
97
+
98
+ Setup is two steps: first connect your coding agent to the router, then
99
+ add the MCP servers you want to compress behind it.
100
+
101
+ ### 1. Connect your coding agent
102
+
103
+ Point your agent at the router the same way you would point it at any
104
+ other MCP server. The router reads its server list from a
105
+ [user-wide config file](#config-file-location) by default, so register
106
+ it at the **user** scope (or your agent's equivalent) — every project
107
+ then gets the same compressed catalog with no per-project setup.
108
+
109
+ - **Claude Code** — see the
110
+ [Claude Code MCP docs](https://code.claude.com/docs/en/mcp).
111
+ Add it at `user` scope so it applies everywhere (Claude Code also
112
+ supports `local` for a single private project and `project` for a
113
+ shareable `.mcp.json`):
114
+
115
+ ```sh
116
+ claude mcp add mcp-compress-router --scope user -- npx -y mcp-compress-router@latest
117
+ ```
118
+
119
+ - **Opencode** — see the
120
+ [opencode MCP servers docs](https://opencode.ai/docs/mcp-servers/).
121
+
122
+ ```sh
123
+ opencode mcp add mcp-compress-router -- npx -y mcp-compress-router@latest
124
+ ```
125
+
126
+ - **Codex** — see the
127
+ [Codex MCP docs](https://developers.openai.com/codex/mcp).
128
+
129
+ ```sh
130
+ codex mcp add mcp-compress-router -- npx -y mcp-compress-router@latest
131
+ ```
132
+
133
+ - **GitHub Copilot (VS Code)** — see the
134
+ [VS Code MCP docs](https://code.visualstudio.com/docs/agent-customization/mcp-servers).
135
+ Open the Command Palette (`Cmd+Shift+P`) →
136
+ `MCP: Open User Configuration` and add the server block under
137
+ `mcp.servers` (project-level `.vscode/mcp.json` is also supported
138
+ and merged with the user-level settings, project taking precedence):
139
+
140
+ ```json
141
+ {
142
+ "servers": {
143
+ "mcp-compress-router": {
144
+ "command": "npx",
145
+ "args": ["-y", "mcp-compress-router@latest"]
146
+ }
147
+ }
148
+ }
149
+ ```
150
+
151
+ ### 2. Add downstream MCP servers
152
+
153
+ Use the `add` command to register each MCP server you want to compress.
154
+ The router writes them to its [config file](#config-file-location) and
155
+ they appear in the catalog the next time the router starts.
99
156
 
100
157
  ```bash
101
158
  npx mcp-compress-router@latest add playwright -- npx -y @playwright/mcp
102
159
  ```
103
160
 
104
- This registers a downstream MCP server named `playwright` and writes it
105
- to your [config file](#config-file-location). Repeat for every MCP server
106
- you want to compress.
161
+ Add a description so the LLM can pick the right server, and use
162
+ environment variables to keep secrets out of the config:
163
+
164
+ ```bash
165
+ npx mcp-compress-router@latest add github \
166
+ --description "GitHub API tools" \
167
+ -e GITHUB_PERSONAL_TOKEN=ghp_xxx \
168
+ -- npx -y @modelcontextprotocol/server-github
169
+ ```
107
170
 
108
- Then point your [coding agent](#connecting-coding-agents) at the router:
171
+ Repeat for every MCP server you want to compress. See
172
+ [Adding Downstream Servers](#adding-downstream-servers) for HTTP
173
+ servers, custom headers, OAuth, and other options.
174
+
175
+ ### 3. Verify and use
176
+
177
+ Check that everything is wired up:
178
+
179
+ ```bash
180
+ npx mcp-compress-router@latest list
181
+ ```
182
+
183
+ Then start a new session in your coding agent. The agent picks up the
184
+ router's two tools — `get_tool_schema` and `invoke_tool` — and uses
185
+ them to discover and call every server you added, without the agent
186
+ ever seeing the raw tool listings of each downstream server.
187
+
188
+ Under the hood your agent spawns the router as a child process with:
109
189
 
110
190
  ```bash
111
191
  npx mcp-compress-router@latest
@@ -113,7 +193,8 @@ npx mcp-compress-router@latest
113
193
 
114
194
  When started without a subcommand, the router runs the MCP server over
115
195
  stdio and exposes exactly two tools (`get_tool_schema`,
116
- `invoke_tool`) to the agent.
196
+ `invoke_tool`) to the agent. You normally do not run this yourself —
197
+ your agent spawns the router automatically.
117
198
 
118
199
  ## Configuration
119
200
 
@@ -338,6 +419,16 @@ A good rule of thumb:
338
419
  - Use `low` sparingly — only when full descriptions must be visible
339
420
  without a `get_tool_schema` call, since it costs the most tokens.
340
421
 
422
+ > **Note for Claude Code:** Claude Code truncates any single tool
423
+ > description at 2000 characters. The router renders the entire
424
+ > compressed catalog into the `get_tool_schema` description that the
425
+ > agent receives on every turn, so with several downstream servers or
426
+ > many tools per server the `high`, `medium`, or `low` listings can
427
+ > exceed that limit and get truncated — breaking routing. When using
428
+ > Claude Code, set `compressionLevel: "max"` on your servers (or pass
429
+ > `--compression-level max` to `add`) so each server's tool listing
430
+ > collapses to a comma-separated single line.
431
+
341
432
  ### Inspecting Tools
342
433
 
343
434
  To see exactly which tools a server advertises — and which are
@@ -640,52 +731,6 @@ MY_SERVER_TOKEN=secret-token
640
731
 
641
732
  Shell environment variables always take precedence over `.env` values.
642
733
 
643
- ## Connecting Coding Agents
644
-
645
- Once your downstream servers are configured, connect your agent to the
646
- router the same way you would connect any other MCP server — by
647
- pointing it at `npx mcp-compress-router@latest`. The examples below assume the
648
- default [config location](#config-file-location); pass `-c <path>` if
649
- you use a custom one.
650
-
651
- ### Opencode
652
-
653
- ```sh
654
- opencode mcp add mcp-compress-router -- npx -y mcp-compress-router@latest
655
- ```
656
-
657
- ### Claude Code
658
-
659
- ```sh
660
- claude mcp add mcp-compress-router -- npx -y mcp-compress-router@latest
661
- ```
662
-
663
- ### Codex
664
-
665
- ```sh
666
- codex mcp add mcp-compress-router -- npx -y mcp-compress-router@latest
667
- ```
668
-
669
- ### GitHub Copilot (VS Code)
670
-
671
- Add this to `.vscode/mcp.json` in your workspace (project-level, applies
672
- only to that workspace), or to your **user-level** MCP settings which
673
- apply across every workspace: open the Command Palette (`Cmd+Shift+P`) →
674
- `MCP: Open User Configuration` and add the same `servers`
675
- block under the `mcp` key. Project-level and user-level entries are
676
- merged, with project-level taking precedence.
677
-
678
- ```json
679
- {
680
- "servers": {
681
- "mcp-compress-router": {
682
- "command": "npx",
683
- "args": ["-y", "mcp-compress-router@latest"]
684
- }
685
- }
686
- }
687
- ```
688
-
689
734
  ## How It Works
690
735
 
691
736
  Once connected, the agent sees exactly **two tools**:
@@ -17,7 +17,7 @@ function validateToolListPatterns(field, patterns) {
17
17
  }
18
18
  catch (err) {
19
19
  const reason = err instanceof Error ? err.message : String(err);
20
- throw new Error(`Invalid "${field}" pattern "${pattern}": ${reason}`);
20
+ throw new Error(`Invalid "${field}" pattern "${pattern}": ${reason}`, { cause: err });
21
21
  }
22
22
  }
23
23
  }
@@ -3,7 +3,7 @@ import { handleAdd, handleRemove, handleGet, handleList, handleLogin, handleLogo
3
3
  import { runRouter } from './router-runner.js';
4
4
  /**
5
5
  * Collects repeated `--header "K: V"` flags into a headers record.
6
- * @internal — Exported for tests only; not part of the public module API.
6
+ * @internal Exported for tests only; not part of the public module API.
7
7
  */
8
8
  export function collectHeaders(value, previous) {
9
9
  const colonIdx = value.indexOf(':');
@@ -16,7 +16,7 @@ export function collectHeaders(value, previous) {
16
16
  }
17
17
  /**
18
18
  * Collects repeated `-e KEY=value` flags into an env record.
19
- * @internal — Exported for tests only; not part of the public module API.
19
+ * @internal Exported for tests only; not part of the public module API.
20
20
  */
21
21
  export function collectEnv(value, previous) {
22
22
  const eqIdx = value.indexOf('=');
@@ -29,7 +29,7 @@ export function collectEnv(value, previous) {
29
29
  }
30
30
  /**
31
31
  * Collects repeated `--flag <value>` flags into an ordered string array.
32
- * @internal — Exported for tests only; not part of the public module API.
32
+ * @internal Exported for tests only; not part of the public module API.
33
33
  */
34
34
  export function collectStringArray(value, previous) {
35
35
  return [...previous, value];
@@ -38,7 +38,7 @@ export function collectStringArray(value, previous) {
38
38
  * Coerces a `--port` flag value into an integer. Throws on non-numeric
39
39
  * values so the user gets a clear error before any network activity.
40
40
  * Range validation is deferred to the command handlers.
41
- * @internal — Exported for tests only; not part of the public module API.
41
+ * @internal Exported for tests only; not part of the public module API.
42
42
  */
43
43
  export function parsePort(value) {
44
44
  const port = Number(value);
@@ -297,7 +297,9 @@ function validateToolList(name, field, value) {
297
297
  }
298
298
  catch (err) {
299
299
  const reason = err instanceof Error ? err.message : String(err);
300
- throw new Error(`Server "${name}" has invalid "${field}" pattern "${entry}": ${reason}`);
300
+ throw new Error(`Server "${name}" has invalid "${field}" pattern "${entry}": ${reason}`, {
301
+ cause: err,
302
+ });
301
303
  }
302
304
  patterns.push(entry);
303
305
  }
@@ -86,7 +86,7 @@ export async function discoverSingleServer(server, logger, getAuthProvider) {
86
86
  type: server.type,
87
87
  error: message,
88
88
  });
89
- throw new Error(`Failed to connect to server "${server.name}": ${message}`);
89
+ throw new Error(`Failed to connect to server "${server.name}": ${message}`, { cause: err });
90
90
  }
91
91
  finally {
92
92
  await client.close().catch(() => { });
@@ -16,6 +16,6 @@ export function validateGlobPattern(pattern) {
16
16
  }
17
17
  catch (err) {
18
18
  const reason = err instanceof Error ? err.message : String(err);
19
- throw new Error(`Invalid glob pattern "${pattern}": ${reason}`);
19
+ throw new Error(`Invalid glob pattern "${pattern}": ${reason}`, { cause: err });
20
20
  }
21
21
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-compress-router",
3
- "version": "1.5.2",
3
+ "version": "1.5.4",
4
4
  "description": "Compress all connected MCP servers into a single router MCP to save tokens",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -25,17 +25,17 @@
25
25
  "url": "https://github.com/ameshkov/mcp-compress-router/issues"
26
26
  },
27
27
  "scripts": {
28
- "build": "tsc && node -e \"require('fs').chmodSync('build/index.js', '755')\"",
29
- "typecheck": "tsc && tsc --project tsconfig.test.json",
28
+ "build": "tsc -p tsconfig.app.json && node -e \"require('fs').chmodSync('build/index.js', '755')\"",
29
+ "typecheck": "tsc -p tsconfig.app.json --noEmit && tsc -p tsconfig.test.json",
30
30
  "test": "vitest run",
31
31
  "test:watch": "vitest",
32
32
  "clean": "rm -rf node_modules build",
33
33
  "format:check": "prettier --check --no-error-on-unmatched-pattern --cache . && markdownlint-cli2 .",
34
34
  "format:fix": "prettier --write --no-error-on-unmatched-pattern --cache . && markdownlint-cli2 --fix .",
35
- "lint": "eslint src && pnpm knip",
36
- "lint:fix": "eslint src --fix",
35
+ "lint": "oxlint src && pnpm knip",
36
+ "lint:fix": "oxlint src --fix",
37
37
  "knip": "knip --production",
38
- "check": "pnpm run format:check && pnpm run lint && pnpm run typecheck && pnpm run test",
38
+ "check": "pnpm run format:check && pnpm run lint && pnpm run typecheck && pnpm run build && pnpm run test",
39
39
  "prepare": "husky || true"
40
40
  },
41
41
  "files": [
@@ -51,25 +51,23 @@
51
51
  ],
52
52
  "author": "Andrey Meshkov <am@adguard.com>",
53
53
  "devDependencies": {
54
- "@eslint/js": "9.16.0",
55
- "@types/node": "24.13.2",
54
+ "@types/node": "26.1.2",
56
55
  "@types/picomatch": "4.0.3",
57
- "eslint": "9.16.0",
58
56
  "husky": "9.1.7",
59
- "knip": "6.6.2",
60
- "markdownlint-cli2": "0.22.0",
61
- "prettier": "3.7.4",
62
- "tsx": "4.20.3",
63
- "typescript": "5.9.3",
64
- "typescript-eslint": "8.57.0",
65
- "vitest": "3.2.4"
57
+ "knip": "6.29.0",
58
+ "markdownlint-cli2": "0.23.2",
59
+ "oxlint": "1.76.0",
60
+ "prettier": "3.9.6",
61
+ "tsx": "4.23.1",
62
+ "typescript": "7.0.2",
63
+ "vitest": "4.1.10"
66
64
  },
67
65
  "dependencies": {
68
- "@modelcontextprotocol/sdk": "1.24.3",
69
- "commander": "14.0.2",
66
+ "@modelcontextprotocol/sdk": "1.30.0",
67
+ "commander": "15.0.0",
70
68
  "dotenv": "17.4.2",
71
69
  "jsonc-parser": "3.3.1",
72
- "picomatch": "4.0.4",
73
- "zod": "3.25.76"
70
+ "picomatch": "4.0.5",
71
+ "zod": "4.4.3"
74
72
  }
75
73
  }