mcp-compress-router 1.0.2 → 1.2.0
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 +551 -0
- package/build/cli/add-command.js +91 -20
- package/build/cli/disable-command.js +29 -0
- package/build/cli/enable-command.js +35 -0
- package/build/cli/index.js +3 -0
- package/build/cli/list-command.js +45 -3
- package/build/cli/login-command.js +56 -11
- package/build/cli/register-commands.js +213 -0
- package/build/cli/router-runner.js +89 -0
- package/build/cli/tools-command.js +115 -0
- package/build/index.js +3 -207
- package/build/services/auth-status.js +10 -8
- package/build/services/catalog.js +49 -14
- package/build/services/config.js +83 -2
- package/build/services/discovery.js +71 -2
- package/build/services/index.js +2 -1
- package/build/services/oauth-discovery.js +87 -0
- package/build/services/oauth.js +13 -1
- package/build/tools/get-tool-schema.js +1 -3
- package/build/utils/index.js +3 -0
- package/build/utils/text-format.js +14 -5
- package/build/utils/tool-filter.js +87 -0
- package/build/utils/validate-glob.js +22 -0
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# MCP Compressing Router
|
|
2
2
|
|
|
3
|
+
[](https://github.com/ameshkov/mcp-compress-router/actions/workflows/ci.yml)
|
|
4
|
+
[](https://www.npmjs.com/package/mcp-compress-router)
|
|
5
|
+
[](https://github.com/ameshkov/mcp-compress-router/releases)
|
|
6
|
+
|
|
3
7
|
<p align="center">
|
|
4
8
|
Compress all connected MCP into a single router MCP and save up to 99% on
|
|
5
9
|
tokens.
|
|
@@ -10,6 +14,30 @@
|
|
|
10
14
|
alt="MCP Compress Router" width="600"/>
|
|
11
15
|
</p>
|
|
12
16
|
|
|
17
|
+
## Table of Contents
|
|
18
|
+
|
|
19
|
+
- [The Problem](#the-problem)
|
|
20
|
+
- [The Solution](#the-solution)
|
|
21
|
+
- [Prerequisites](#prerequisites)
|
|
22
|
+
- [Quick Start](#quick-start)
|
|
23
|
+
- [Configuration](#configuration)
|
|
24
|
+
- [Config File Location](#config-file-location)
|
|
25
|
+
- [Adding Downstream Servers](#adding-downstream-servers)
|
|
26
|
+
- [Per-Server Enable/Disable](#per-server-enabledisable)
|
|
27
|
+
- [Per-Server Tool Selection](#per-server-tool-selection)
|
|
28
|
+
- [Inspecting Tools](#inspecting-tools)
|
|
29
|
+
- [OAuth](#oauth)
|
|
30
|
+
- [Redirect URL](#redirect-url)
|
|
31
|
+
- [GitHub MCP (special case)](#github-mcp-special-case)
|
|
32
|
+
- [Custom Headers](#custom-headers)
|
|
33
|
+
- [Secrets and Variable Expansion](#secrets-and-variable-expansion)
|
|
34
|
+
- [Connecting Coding Agents](#connecting-coding-agents)
|
|
35
|
+
- [Opencode](#opencode)
|
|
36
|
+
- [Claude Code](#claude-code)
|
|
37
|
+
- [Codex](#codex)
|
|
38
|
+
- [GitHub Copilot](#github-copilot)
|
|
39
|
+
- [How It Works](#how-it-works)
|
|
40
|
+
|
|
13
41
|
## The Problem
|
|
14
42
|
|
|
15
43
|
When you have multiple MCPs every request to the LLM will include ALL their
|
|
@@ -49,3 +77,526 @@ an average coding session will be about **$0.032175** so we saved about
|
|
|
49
77
|
|
|
50
78
|
This is just a basic example with just 3 MCP servers, the more MCP servers you
|
|
51
79
|
have, the more you save.
|
|
80
|
+
|
|
81
|
+
## Prerequisites
|
|
82
|
+
|
|
83
|
+
- **Node.js 24 or later** — the router runs on Node.js and is launched
|
|
84
|
+
via `npx`, so no separate install step is needed.
|
|
85
|
+
- **A coding agent that supports stdio MCP servers** — this covers
|
|
86
|
+
virtually every modern coding agent (opencode, Claude Code, Codex,
|
|
87
|
+
GitHub Copilot, Cursor, etc.). The router exposes itself as a single
|
|
88
|
+
stdio MCP server, so any agent that can spawn a local MCP process
|
|
89
|
+
works.
|
|
90
|
+
|
|
91
|
+
## Quick Start
|
|
92
|
+
|
|
93
|
+
The router is published on npm as
|
|
94
|
+
[`mcp-compress-router`](https://www.npmjs.com/package/mcp-compress-router).
|
|
95
|
+
You do not need to install it — just run it with `npx`:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
npx mcp-compress-router add github -- npx -y @modelcontextprotocol/server-github
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
This registers a downstream MCP server named `github` and writes it to
|
|
102
|
+
your [config file](#config-file-location). Repeat for every MCP server you
|
|
103
|
+
want to compress.
|
|
104
|
+
|
|
105
|
+
Then point your [coding agent](#connecting-coding-agents) at the router:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
npx mcp-compress-router
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
When started without a subcommand, the router runs the MCP server over
|
|
112
|
+
stdio and exposes exactly two tools (`get_tool_schema`,
|
|
113
|
+
`invoke_tool`) to the agent.
|
|
114
|
+
|
|
115
|
+
## Configuration
|
|
116
|
+
|
|
117
|
+
The router reads its configuration from a single JSON(C) file that lists
|
|
118
|
+
every downstream MCP server to compress. You can edit this file by hand
|
|
119
|
+
or use the `add` / `remove` / `get` / `list` CLI commands.
|
|
120
|
+
|
|
121
|
+
### Config File Location
|
|
122
|
+
|
|
123
|
+
By default, the config file lives in a platform-specific directory
|
|
124
|
+
(`mcp.jsonc` is preferred over `mcp.json` when both exist):
|
|
125
|
+
|
|
126
|
+
- **Windows:** `%APPDATA%\mcp-compress-router\`
|
|
127
|
+
- **macOS:** `~/Library/Application Support/mcp-compress-router/`
|
|
128
|
+
- **Linux:** `~/.local/share/mcp-compress-router/`
|
|
129
|
+
|
|
130
|
+
You can override this with:
|
|
131
|
+
|
|
132
|
+
- The `-c, --config <path>` flag on any command, or
|
|
133
|
+
- The `MCP_COMPRESS_ROUTER_HOME` environment variable (points to a
|
|
134
|
+
directory containing the config file).
|
|
135
|
+
|
|
136
|
+
If the file does not exist when a management command runs, it is created
|
|
137
|
+
automatically with an empty `{ "mcpServers": {} }` body.
|
|
138
|
+
|
|
139
|
+
A `.env` file in the **same directory** is loaded automatically at
|
|
140
|
+
startup, so you can keep secrets out of the config (see
|
|
141
|
+
[Secrets and Variable Expansion](#secrets-and-variable-expansion)).
|
|
142
|
+
|
|
143
|
+
> **Note on `-c` and credential storage:** when you override the config
|
|
144
|
+
> path with `-c /some/dir/mcp.json`, both `credentials.json` (OAuth
|
|
145
|
+
> tokens) and `mcp.json` live in `/some/dir/` — i.e. next to the config
|
|
146
|
+
> file you specified. The `.env` file, however, is loaded from the
|
|
147
|
+
> [configuration directory](#config-file-location) resolved by
|
|
148
|
+
> `MCP_COMPRESS_ROUTER_HOME` or the platform default, *not* from beside
|
|
149
|
+
> the explicit `-c` path. To co-locate `.env` with a custom config, set
|
|
150
|
+
> `MCP_COMPRESS_ROUTER_HOME` to the same directory.
|
|
151
|
+
|
|
152
|
+
### Adding Downstream Servers
|
|
153
|
+
|
|
154
|
+
Use the `add` command to register a downstream MCP server.
|
|
155
|
+
|
|
156
|
+
A good description helps the LLM route requests to the correct server.
|
|
157
|
+
When several servers are compressed behind the router, the model sees
|
|
158
|
+
each server's name, its description, and a list of tool names in the
|
|
159
|
+
`get_tool_schema` catalog. A clear description (e.g. *"GitHub API tools
|
|
160
|
+
for issues, PRs, and repos"*) steers the model toward the right server
|
|
161
|
+
far better than a bare name.
|
|
162
|
+
|
|
163
|
+
**stdio server** (a local process):
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
npx mcp-compress-router add github --description "GitHub API tools" \
|
|
167
|
+
-- npx -y @modelcontextprotocol/server-github
|
|
168
|
+
|
|
169
|
+
# With environment variables
|
|
170
|
+
npx mcp-compress-router add github -e GITHUB_PERSONAL_TOKEN=ghp_xxx \
|
|
171
|
+
--description "GitHub API tools" \
|
|
172
|
+
-- npx -y @modelcontextprotocol/server-github
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
**HTTP server** (a remote endpoint; transport auto-detected from the
|
|
176
|
+
URL):
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
npx mcp-compress-router add my-http https://localhost:3100/mcp
|
|
180
|
+
|
|
181
|
+
# With a custom header
|
|
182
|
+
npx mcp-compress-router add my-http \
|
|
183
|
+
--header "Authorization: Bearer mytoken" \
|
|
184
|
+
https://localhost:3100/mcp
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
This produces a config file that looks like:
|
|
188
|
+
|
|
189
|
+
```jsonc
|
|
190
|
+
{
|
|
191
|
+
"mcpServers": {
|
|
192
|
+
"github": {
|
|
193
|
+
"type": "stdio",
|
|
194
|
+
"command": "npx",
|
|
195
|
+
"args": ["-y", "@modelcontextprotocol/server-github"],
|
|
196
|
+
"env": { "GITHUB_PERSONAL_TOKEN": "ghp_xxx" },
|
|
197
|
+
"description": "GitHub API tools"
|
|
198
|
+
},
|
|
199
|
+
"my-http": {
|
|
200
|
+
"type": "http",
|
|
201
|
+
"url": "https://localhost:3100/mcp",
|
|
202
|
+
"headers": { "Authorization": "Bearer mytoken" }
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Both `.json` and `.jsonc` (JSON with comments and trailing commas) are
|
|
209
|
+
supported. CLI commands write plain `.json`; hand-edited files may use
|
|
210
|
+
`.jsonc`.
|
|
211
|
+
|
|
212
|
+
Other management commands:
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
npx mcp-compress-router list # list all servers + auth status
|
|
216
|
+
npx mcp-compress-router get my-http # show one server's config
|
|
217
|
+
npx mcp-compress-router remove my-http # remove a server
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Per-Server Enable/Disable
|
|
221
|
+
|
|
222
|
+
Every server entry accepts an optional `enabled` boolean. When set to
|
|
223
|
+
`false`, the router skips that server entirely at startup — no process
|
|
224
|
+
spawn, no network connection, no discovery — and it is absent from the
|
|
225
|
+
`get_tool_schema` catalog. All configuration is preserved so the server
|
|
226
|
+
can be turned back on instantly. Omitting `enabled` (the default) means
|
|
227
|
+
enabled, keeping `mcp.json` clean and fully backward compatible.
|
|
228
|
+
|
|
229
|
+
Toggle it from the CLI without touching the rest of the config:
|
|
230
|
+
|
|
231
|
+
```bash
|
|
232
|
+
npx mcp-compress-router disable github # writes "enabled": false
|
|
233
|
+
npx mcp-compress-router enable github # removes the field
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
You can also set it at creation time:
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
npx mcp-compress-router add archive --disabled -- npx -y server-archive
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### Per-Server Tool Selection
|
|
243
|
+
|
|
244
|
+
Two optional fields control which of a server's advertised tools are
|
|
245
|
+
exposed to the LLM. Both are arrays of glob patterns
|
|
246
|
+
([picomatch](https://github.com/micromatch/picomatch) syntax: `*`, `?`,
|
|
247
|
+
`{a,b}`, `[abc]`) matched against bare tool names:
|
|
248
|
+
|
|
249
|
+
- **`allowedTools`** — when present, only matching tools are exposed.
|
|
250
|
+
An empty array (`[]`) exposes *no* tools (handy for staging a server
|
|
251
|
+
while you build the list).
|
|
252
|
+
- **`disabledTools`** — removes matching tools from whatever would
|
|
253
|
+
otherwise be exposed. The denylist wins: a tool matching both lists
|
|
254
|
+
is blocked.
|
|
255
|
+
|
|
256
|
+
Filtered tools are hidden from the catalog *and* hard-rejected by
|
|
257
|
+
`invoke_tool`, so even an LLM that guesses a filtered name cannot
|
|
258
|
+
reach the downstream server.
|
|
259
|
+
|
|
260
|
+
```jsonc
|
|
261
|
+
"dangerous": {
|
|
262
|
+
"type": "stdio",
|
|
263
|
+
"command": "npx",
|
|
264
|
+
"args": ["-y", "@some/mcp-server"],
|
|
265
|
+
"allowedTools": ["list_issues", "get_pull_request"],
|
|
266
|
+
"disabledTools": ["*_delete"]
|
|
267
|
+
}
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
A pattern that matches no real tool is not an error — the router logs a
|
|
271
|
+
warning (visible with `-v`) and continues. A malformed pattern is a
|
|
272
|
+
hard error at startup. Set filters at creation time with repeatable
|
|
273
|
+
flags:
|
|
274
|
+
|
|
275
|
+
```bash
|
|
276
|
+
npx mcp-compress-router add github \
|
|
277
|
+
--allowed-tools list_issues \
|
|
278
|
+
--allowed-tools get_pull_request \
|
|
279
|
+
-- npx -y server-github
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### Inspecting Tools
|
|
283
|
+
|
|
284
|
+
To see exactly which tools a server advertises — and which are
|
|
285
|
+
`[exposed]` or `[filtered]` under your current selection — connect to
|
|
286
|
+
it live without starting the full router:
|
|
287
|
+
|
|
288
|
+
```bash
|
|
289
|
+
npx mcp-compress-router tools github
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
This works regardless of the server's `enabled` state (inspecting a
|
|
293
|
+
disabled server is the primary way to build its allowlist). For HTTP
|
|
294
|
+
servers, stored OAuth credentials and `oauth` overrides are reused. If
|
|
295
|
+
the server cannot be reached or is missing required auth, the command
|
|
296
|
+
exits non-zero with a clear error and prints no partial list.
|
|
297
|
+
|
|
298
|
+
### OAuth
|
|
299
|
+
|
|
300
|
+
HTTP servers that require OAuth are supported. When you `add` an HTTP
|
|
301
|
+
server, the router probes it for OAuth metadata and starts the login
|
|
302
|
+
flow automatically if OAuth is advertised. You can also trigger it
|
|
303
|
+
manually:
|
|
304
|
+
|
|
305
|
+
```bash
|
|
306
|
+
npx mcp-compress-router login my-http
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
This opens your browser to complete the authorization-code flow. Tokens
|
|
310
|
+
are stored in a separate `credentials.json` in the same directory as
|
|
311
|
+
`mcp.json` (with `0600` permissions on Unix), so you can safely
|
|
312
|
+
share or version-control `mcp.json` without exposing tokens. Add
|
|
313
|
+
`credentials.json` to your `.gitignore`.
|
|
314
|
+
|
|
315
|
+
By default the router uses
|
|
316
|
+
[Dynamic Client Registration](https://datatracker.ietf.org/doc/html/rfc7591).
|
|
317
|
+
If your server requires a pre-registered client, add an `oauth` block to
|
|
318
|
+
the server entry (in `mcp.json`):
|
|
319
|
+
|
|
320
|
+
```jsonc
|
|
321
|
+
"my-http": {
|
|
322
|
+
"type": "http",
|
|
323
|
+
"url": "https://example.com/mcp",
|
|
324
|
+
"oauth": {
|
|
325
|
+
"clientId": "${MY_CLIENT_ID}",
|
|
326
|
+
"clientSecret": "${MY_CLIENT_SECRET}",
|
|
327
|
+
"scope": "read write"
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
Only `clientId` is required; `clientSecret` and `scope` are optional.
|
|
333
|
+
|
|
334
|
+
#### Redirect URL
|
|
335
|
+
|
|
336
|
+
During `login` the router starts a temporary local HTTP server and uses
|
|
337
|
+
a loopback redirect URI (per [RFC 8252](https://datatracker.ietf.org/doc/html/rfc8252)):
|
|
338
|
+
|
|
339
|
+
```text
|
|
340
|
+
http://localhost:<port>/mcp-compress-router/oauth-callback
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
`<port>` is chosen by the OS at login time, so there is no fixed port to
|
|
344
|
+
register. When a provider requires a pre-registered redirect URI,
|
|
345
|
+
register the loopback form **without a port**:
|
|
346
|
+
|
|
347
|
+
```text
|
|
348
|
+
http://localhost/mcp-compress-router/oauth-callback
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
Most providers (GitHub included) match the scheme, host, and path and
|
|
352
|
+
ignore the port on `localhost`. If your provider demands a redirect URI
|
|
353
|
+
with an **exact port**, pin it with `--port`:
|
|
354
|
+
|
|
355
|
+
```bash
|
|
356
|
+
npx mcp-compress-router login my-http --port 8765
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
This binds the callback server to `8765`, so the redirect URI becomes
|
|
360
|
+
`http://localhost:8765/mcp-compress-router/oauth-callback` — register
|
|
361
|
+
that exact URL with the provider. To reuse the same port on every
|
|
362
|
+
`login`, persist it in the server's `oauth` block instead of passing the
|
|
363
|
+
flag each time:
|
|
364
|
+
|
|
365
|
+
```jsonc
|
|
366
|
+
"my-http": {
|
|
367
|
+
"type": "http",
|
|
368
|
+
"url": "https://example.com/mcp",
|
|
369
|
+
"oauth": { "clientId": "${ID}", "callbackPort": 8765 }
|
|
370
|
+
}
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
`--port` overrides `oauth.callbackPort` for a single run. Pass `--port 0`
|
|
374
|
+
to force an OS-assigned port even when `oauth.callbackPort` is set.
|
|
375
|
+
|
|
376
|
+
#### GitHub MCP (special case)
|
|
377
|
+
|
|
378
|
+
The official GitHub MCP server at
|
|
379
|
+
`https://api.githubcopilot.com/mcp` advertises OAuth but does **not**
|
|
380
|
+
support Dynamic Client Registration, so you must pre-register a GitHub
|
|
381
|
+
OAuth App and pass its credentials via the `oauth` block. GitHub also
|
|
382
|
+
requires that the OAuth App be installed to the repositories and
|
|
383
|
+
organizations you want the MCP to access.
|
|
384
|
+
|
|
385
|
+
1. **Create a GitHub OAuth App.**
|
|
386
|
+
Open <https://github.com/settings/developers> → *New OAuth App* (or
|
|
387
|
+
*Register an application*). Give it any name and homepage URL.
|
|
388
|
+
2. **Configure the callback URL.**
|
|
389
|
+
Set the *Authorization callback URL* to:
|
|
390
|
+
`http://localhost/mcp-compress-router/oauth-callback`
|
|
391
|
+
3. **Add the GitHub MCP server by URL.**
|
|
392
|
+
|
|
393
|
+
```bash
|
|
394
|
+
npx mcp-compress-router add github https://api.githubcopilot.com/mcp
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
4. **Set `oauth` credentials in `mcp.json`.**
|
|
398
|
+
Copy the Client ID and generate a Client Secret, then put them in the
|
|
399
|
+
server entry (use variable expansion to keep secrets out of the
|
|
400
|
+
file):
|
|
401
|
+
|
|
402
|
+
```jsonc
|
|
403
|
+
"github": {
|
|
404
|
+
"type": "http",
|
|
405
|
+
"url": "https://api.githubcopilot.com/mcp",
|
|
406
|
+
"oauth": {
|
|
407
|
+
"clientId": "${GITHUB_OAUTH_CLIENT_ID}",
|
|
408
|
+
"clientSecret": "${GITHUB_OAUTH_CLIENT_SECRET}",
|
|
409
|
+
"scope": "repo read:org"
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
Request only the scopes the tools you need require; `repo read:org`
|
|
415
|
+
covers the common repo and organization operations. Put the actual
|
|
416
|
+
values in your `.env` file (see
|
|
417
|
+
[Secrets and Variable Expansion](#secrets-and-variable-expansion)).
|
|
418
|
+
5. **Run the login command.**
|
|
419
|
+
|
|
420
|
+
```bash
|
|
421
|
+
npx mcp-compress-router login github
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
Your browser opens to authorize. After you approve, tokens are stored
|
|
425
|
+
in `credentials.json` and the router can call GitHub MCP tools.
|
|
426
|
+
|
|
427
|
+
> **Note:** if you used a *GitHub App* (not a classic OAuth App), the
|
|
428
|
+
> App must be installed to the accounts/repos you want to access before
|
|
429
|
+
> login will succeed, and its client secret is generated under *General*
|
|
430
|
+
> → *Generate a new client secret*.
|
|
431
|
+
|
|
432
|
+
Other OAuth commands:
|
|
433
|
+
|
|
434
|
+
```bash
|
|
435
|
+
npx mcp-compress-router logout my-http # remove stored credentials
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
For headless or CI environments, override the browser with the
|
|
439
|
+
`MCP_COMPRESS_ROUTER_BROWSER` environment variable. The authorization
|
|
440
|
+
URL is appended as a single final argument (no shell):
|
|
441
|
+
|
|
442
|
+
```bash
|
|
443
|
+
MCP_COMPRESS_ROUTER_BROWSER="node /path/to/headless-browser.js" \
|
|
444
|
+
npx mcp-compress-router login my-http
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
The default login timeout is 120 seconds; override it with
|
|
448
|
+
`MCP_COMPRESS_ROUTER_LOGIN_TIMEOUT_MS`.
|
|
449
|
+
|
|
450
|
+
### Custom Headers
|
|
451
|
+
|
|
452
|
+
For HTTP servers that authenticate with a static API key or bearer
|
|
453
|
+
token instead of OAuth, use the `headers` field. You can set it via the
|
|
454
|
+
CLI or directly in `mcp.json`:
|
|
455
|
+
|
|
456
|
+
```bash
|
|
457
|
+
npx mcp-compress-router add my-http \
|
|
458
|
+
--header "Authorization: Bearer mytoken" \
|
|
459
|
+
--header "X-Custom: value" \
|
|
460
|
+
https://example.com/mcp
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
```jsonc
|
|
464
|
+
"my-http": {
|
|
465
|
+
"type": "http",
|
|
466
|
+
"url": "https://example.com/mcp",
|
|
467
|
+
"headers": {
|
|
468
|
+
"Authorization": "Bearer ${MY_SERVER_TOKEN}",
|
|
469
|
+
"X-Custom": "value"
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
Header values support
|
|
475
|
+
[variable expansion](#secrets-and-variable-expansion), so you can keep
|
|
476
|
+
the actual token out of the config file.
|
|
477
|
+
|
|
478
|
+
### Secrets and Variable Expansion
|
|
479
|
+
|
|
480
|
+
Every string field in a server entry (`command`, `args`, `env`,
|
|
481
|
+
`headers`, `url`, `oauth.*`) is expanded against the process
|
|
482
|
+
environment at load time. Two syntaxes are supported:
|
|
483
|
+
|
|
484
|
+
| Syntax | Behavior |
|
|
485
|
+
| --- | --- |
|
|
486
|
+
| `${VAR}` | Replaced with the value of `VAR`. Throws if unset. |
|
|
487
|
+
| `${VAR:-default}` | Replaced with `VAR` when set and non-empty, otherwise `default`. |
|
|
488
|
+
|
|
489
|
+
Put your secrets in a `.env` file next to `mcp.json`:
|
|
490
|
+
|
|
491
|
+
```bash
|
|
492
|
+
# <config directory>/.env
|
|
493
|
+
GITHUB_PERSONAL_TOKEN=ghp_abc123
|
|
494
|
+
MY_SERVER_TOKEN=secret-token
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
Shell environment variables always take precedence over `.env` values.
|
|
498
|
+
|
|
499
|
+
## Connecting Coding Agents
|
|
500
|
+
|
|
501
|
+
Once your downstream servers are configured, connect your agent to the
|
|
502
|
+
router the same way you would connect any other MCP server — by
|
|
503
|
+
pointing it at `npx mcp-compress-router`. The examples below assume the
|
|
504
|
+
default [config location](#config-file-location); pass `-c <path>` if
|
|
505
|
+
you use a custom one.
|
|
506
|
+
|
|
507
|
+
### Opencode
|
|
508
|
+
|
|
509
|
+
Add the router to your `opencode.json` under `mcp`:
|
|
510
|
+
|
|
511
|
+
```json
|
|
512
|
+
{
|
|
513
|
+
"$schema": "https://opencode.ai/config.json",
|
|
514
|
+
"mcp": {
|
|
515
|
+
"compress-router": {
|
|
516
|
+
"type": "local",
|
|
517
|
+
"command": ["npx", "-y", "mcp-compress-router"],
|
|
518
|
+
"enabled": true
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
### Claude Code
|
|
525
|
+
|
|
526
|
+
Add this to a project-level `.mcp.json` in your workspace root, or to
|
|
527
|
+
your user-level config (applies to every project):
|
|
528
|
+
|
|
529
|
+
- **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
530
|
+
- **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
|
|
531
|
+
- **Linux:** `~/.config/Claude/claude_desktop_config.json`
|
|
532
|
+
|
|
533
|
+
```json
|
|
534
|
+
{
|
|
535
|
+
"mcpServers": {
|
|
536
|
+
"compress-router": {
|
|
537
|
+
"command": "npx",
|
|
538
|
+
"args": ["-y", "mcp-compress-router"]
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
### Codex
|
|
545
|
+
|
|
546
|
+
Add a `[mcp_servers.compress-router]` table to your Codex config (note
|
|
547
|
+
the snake_case key). The config path is `~/.codex/config.toml` on
|
|
548
|
+
macOS/Linux, or `%USERPROFILE%\.codex\config.toml` on Windows; you can
|
|
549
|
+
also scope it to a single project via `.codex/config.toml` in trusted
|
|
550
|
+
projects.
|
|
551
|
+
|
|
552
|
+
```toml
|
|
553
|
+
[mcp_servers.compress-router]
|
|
554
|
+
command = "npx"
|
|
555
|
+
args = ["-y", "mcp-compress-router"]
|
|
556
|
+
enabled = true
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
### GitHub Copilot
|
|
560
|
+
|
|
561
|
+
Add this to `.vscode/mcp.json` in your workspace (project-level, applies
|
|
562
|
+
only to that workspace), or to your **user-level** MCP settings which
|
|
563
|
+
apply across every workspace: open the Command Palette →
|
|
564
|
+
`Preferences: Open User Settings (JSON)` and add the same `servers`
|
|
565
|
+
block under the `mcp` key. Project-level and user-level entries are
|
|
566
|
+
merged, with project-level taking precedence.
|
|
567
|
+
|
|
568
|
+
```json
|
|
569
|
+
{
|
|
570
|
+
"servers": {
|
|
571
|
+
"compress-router": {
|
|
572
|
+
"command": "npx",
|
|
573
|
+
"args": ["-y", "mcp-compress-router"]
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
## How It Works
|
|
580
|
+
|
|
581
|
+
Once connected, the agent sees exactly **two tools**:
|
|
582
|
+
|
|
583
|
+
- **`get_tool_schema(server, tools)`** — Retrieves the JSON parameter
|
|
584
|
+
schema for one or more tools on a downstream MCP server. The tool's
|
|
585
|
+
description includes a compact listing of all servers and their
|
|
586
|
+
available tool names.
|
|
587
|
+
- **`invoke_tool(server, tool, arguments)`** — Forwards a tool call to
|
|
588
|
+
the downstream MCP server and returns the result.
|
|
589
|
+
|
|
590
|
+
The typical workflow:
|
|
591
|
+
|
|
592
|
+
1. The agent reads the compact catalog from the `get_tool_schema`
|
|
593
|
+
description and identifies which tools it needs.
|
|
594
|
+
2. It calls `get_tool_schema` to learn the exact parameters.
|
|
595
|
+
3. It calls `invoke_tool` to execute a tool, validated against the
|
|
596
|
+
cached schema.
|
|
597
|
+
|
|
598
|
+
This replaces thousands of tokens of tool listings with a compact ~900
|
|
599
|
+
token catalog, regardless of how many downstream servers you have.
|
|
600
|
+
|
|
601
|
+
For the full configuration and environment variable reference, see
|
|
602
|
+
[configuration.md](docs/configuration.md).
|