autorouter-mcp 0.2.0 → 0.2.2
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 +96 -28
- package/dist/cli.js +1123 -772
- package/package.json +2 -2
- package/server.json +3 -3
package/README.md
CHANGED
|
@@ -12,9 +12,12 @@ handful of skills is routinely 20–30k tokens of permanent overhead, paid wheth
|
|
|
12
12
|
or not the task touches any of them. It also makes tool selection _worse_: more
|
|
13
13
|
candidates means more mis-picks.
|
|
14
14
|
|
|
15
|
-
autorouter is an MCP server that exposes
|
|
16
|
-
else behind a search. The model asks for what it needs in natural
|
|
17
|
-
back a few ranked candidates
|
|
15
|
+
autorouter is an MCP server that exposes a handful of stable tools and hides
|
|
16
|
+
everything else behind a search. The model asks for what it needs in natural
|
|
17
|
+
language, gets back a few ranked candidates with schemas attached, and calls one
|
|
18
|
+
through the router. A tool it actually uses is then promoted into the real tool
|
|
19
|
+
list, so the context is spent on what the session needs rather than on what it
|
|
20
|
+
might.
|
|
18
21
|
|
|
19
22
|
```
|
|
20
23
|
find_capabilities({ query: "inspect recent deployment errors" })
|
|
@@ -34,6 +37,9 @@ autorouter init --target claude # claude | codex | cursor | vscode
|
|
|
34
37
|
autorouter adopt --target claude # ← the step that actually saves context
|
|
35
38
|
```
|
|
36
39
|
|
|
40
|
+
That is a one-time migration of what you already have. New servers do not need
|
|
41
|
+
it — see [Adding an MCP server](#adding-an-mcp-server).
|
|
42
|
+
|
|
37
43
|
**`adopt` is not optional.** Registering the router alongside your existing
|
|
38
44
|
servers is a net _increase_: their schemas are still loaded and the router adds
|
|
39
45
|
four more tools. `adopt` moves the downstream entries out of the harness config
|
|
@@ -72,21 +78,24 @@ Run `autorouter doctor` to see the difference:
|
|
|
72
78
|
|
|
73
79
|
```
|
|
74
80
|
## Context cost
|
|
75
|
-
exposing everything: ~
|
|
76
|
-
router surface: ~
|
|
77
|
-
|
|
78
|
-
|
|
81
|
+
exposing everything: ~87,524 tokens
|
|
82
|
+
router surface: ~972 tokens
|
|
83
|
+
best case: ~86,552 tokens saved (99%)
|
|
84
|
+
|
|
85
|
+
per harness (a session only ever runs in one):
|
|
86
|
+
codex still loaded ~35,500 → saves ~51,052 (58%)
|
|
87
|
+
claude, cursor, vscode: fully adopted → saves ~86,552 (99%)
|
|
79
88
|
|
|
80
89
|
## Not yet adopted
|
|
81
|
-
|
|
90
|
+
codex
|
|
82
91
|
servers: project-tools, docs-search, issue-tracker
|
|
83
|
-
|
|
84
|
-
skills: code-review, incident-response
|
|
85
|
-
→ autorouter adopt --target claude
|
|
92
|
+
→ autorouter adopt --target codex
|
|
86
93
|
```
|
|
87
94
|
|
|
88
|
-
|
|
89
|
-
|
|
95
|
+
"Still loaded" is what adoption removes, and it is reported per harness rather
|
|
96
|
+
than summed: a session runs in exactly one, so a server still registered in Codex
|
|
97
|
+
costs a Claude Code session nothing. Every removal is backed up verbatim to
|
|
98
|
+
`~/.autorouter/adopted/` before anything is written;
|
|
90
99
|
`autorouter restore --target claude` puts it back byte for byte.
|
|
91
100
|
|
|
92
101
|
## How it finds things
|
|
@@ -169,12 +178,42 @@ when one of its capabilities is first called.
|
|
|
169
178
|
| `skill` | `**/SKILL.md` under your skill paths and plugin `skills/` dirs |
|
|
170
179
|
| `command`, `agent` | plugin `commands/*.md` and `agents/*.md` |
|
|
171
180
|
|
|
172
|
-
|
|
181
|
+
Plugin commands and agents are also republished as [slash commands](#slash-commands);
|
|
182
|
+
skills are searchable but not republished by default, because the prompt list
|
|
183
|
+
that would carry them is permanent context — see [Slash commands](#slash-commands).
|
|
173
184
|
|
|
174
185
|
Harness configs are imported rather than duplicated: `~/.claude.json` (global and
|
|
175
186
|
per-project) and `.mcp.json`, `~/.codex/config.toml`, `~/.cursor/mcp.json`,
|
|
176
187
|
`~/.vscode/mcp.json`, and installed Claude Code plugins.
|
|
177
188
|
|
|
189
|
+
## Adding an MCP server
|
|
190
|
+
|
|
191
|
+
Register it with the router directly — it never enters anyone's context:
|
|
192
|
+
|
|
193
|
+
```sh
|
|
194
|
+
autorouter add linear --url https://mcp.linear.app/mcp
|
|
195
|
+
autorouter add foo -- npx -y foo-mcp # stdio, like `claude mcp add`
|
|
196
|
+
autorouter add --json '{"mcpServers":{"linear":{"url":"…"}}}' # paste the vendor snippet
|
|
197
|
+
autorouter remove linear
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
The entry is saved before the connection is checked, because the usual reason a
|
|
201
|
+
new server does not answer is that it has no OAuth grant yet — and
|
|
202
|
+
`autorouter login <name>` needs the entry to exist before it can authorize it.
|
|
203
|
+
|
|
204
|
+
**You can also just use the harness.** `claude mcp add foo …` still works: a
|
|
205
|
+
running router notices the harness config changed, moves the entry into its own
|
|
206
|
+
config with the usual backup, and tells you on the next search. So there is no
|
|
207
|
+
second command to remember, and no window where you have forgotten it and are
|
|
208
|
+
paying for that server's schemas on every turn. Set `"autoAdopt": false` to keep
|
|
209
|
+
adoption manual.
|
|
210
|
+
|
|
211
|
+
**From inside a session**, ask for it in words — the router exposes an
|
|
212
|
+
`add_server` tool. Registering a stdio server means this machine will run that
|
|
213
|
+
command from then on, so the first call only reports what would be registered;
|
|
214
|
+
it takes a second call with `confirm: true` to write anything. Set
|
|
215
|
+
`"allowAddServer": false` to withdraw the tool.
|
|
216
|
+
|
|
178
217
|
## Configuration
|
|
179
218
|
|
|
180
219
|
`autorouter.json` — looked up at `$AUTOROUTER_CONFIG`, `./.autorouter.json`,
|
|
@@ -188,6 +227,10 @@ per-project) and `.mcp.json`, `~/.codex/config.toml`, `~/.cursor/mcp.json`,
|
|
|
188
227
|
"exclude": ["media.generate_video"], // never surfaced at all
|
|
189
228
|
"alwaysExpose": ["code-search.search"], // stays first-class, never adopted
|
|
190
229
|
"confirm": ["database.execute_statement"], // first call is rejected, must re-issue
|
|
230
|
+
"autoAdopt": true, // move servers added to a harness behind the router
|
|
231
|
+
"allowAddServer": true, // expose the add_server tool to the model
|
|
232
|
+
"promptMode": "commands", // slash commands: "all" | "commands" | "none"
|
|
233
|
+
"activation": "lazy", // promote to a real tool: "eager" | "lazy" | "off"
|
|
191
234
|
"selector": { "mode": "auto" },
|
|
192
235
|
"embeddings": {
|
|
193
236
|
"provider": "voyage",
|
|
@@ -198,7 +241,9 @@ per-project) and `.mcp.json`, `~/.codex/config.toml`, `~/.cursor/mcp.json`,
|
|
|
198
241
|
```
|
|
199
242
|
|
|
200
243
|
Env overrides (`AUTOROUTER_IMPORT`, `AUTOROUTER_SELECTOR_MODEL`,
|
|
201
|
-
`AUTOROUTER_SELECTOR_MODE`, `
|
|
244
|
+
`AUTOROUTER_SELECTOR_MODE`, `AUTOROUTER_PROMPT_MODE`, `AUTOROUTER_ACTIVATION`,
|
|
245
|
+
`AUTOROUTER_AUTO_ADOPT`, `AUTOROUTER_ALLOW_ADD_SERVER`,
|
|
246
|
+
`AUTOROUTER_EMBEDDINGS_PROVIDER`, …) let each harness
|
|
202
247
|
pin its own behaviour without a shared global file. `AUTOROUTER_HOME` redirects
|
|
203
248
|
every home-relative path, for tests and containers.
|
|
204
249
|
|
|
@@ -206,15 +251,24 @@ every home-relative path, for tests and containers.
|
|
|
206
251
|
|
|
207
252
|
Adopting a plugin into the router would otherwise cost you its slash commands:
|
|
208
253
|
Claude Code reads `commands/*.md` off disk, and nothing over MCP can add to that
|
|
209
|
-
list. What it _does_ surface as slash commands are MCP prompts, so
|
|
210
|
-
plugin
|
|
254
|
+
list. What it _does_ surface as slash commands are MCP prompts, so the catalog's
|
|
255
|
+
plugin commands and subagents are republished as ones:
|
|
211
256
|
|
|
212
257
|
```
|
|
213
258
|
/mcp__autorouter__find <what you want to do>
|
|
214
259
|
/mcp__autorouter__plugin_name_command_name
|
|
215
|
-
/mcp__autorouter__skill_name
|
|
216
260
|
```
|
|
217
261
|
|
|
262
|
+
**Skills are not republished by default** (`promptMode: "commands"`). The prompt
|
|
263
|
+
list is permanent context — the host fetches it once and carries it for the whole
|
|
264
|
+
session — and skills are the bulk of it: one plugin shipping 141 of them costs
|
|
265
|
+
~11.5k tokens on every turn, which is more than adopting that plugin saves. The
|
|
266
|
+
alias is also mostly redundant, since `adopt --skill-mode user-invocable-only`
|
|
267
|
+
leaves a local skill's native `/name` working and a plugin's skills are surfaced
|
|
268
|
+
by the harness on demand rather than injected. Skills stay fully searchable
|
|
269
|
+
either way; set `"promptMode": "all"` to get `/mcp__autorouter__skill_name` back,
|
|
270
|
+
or `"none"` to publish only `find`.
|
|
271
|
+
|
|
218
272
|
Bodies are substituted the way the native loader substitutes them — `$ARGUMENTS`
|
|
219
273
|
for everything you typed, `$1`..`$9` positionally — so a command file written for
|
|
220
274
|
Claude Code behaves identically through the router. `argument-hint` frontmatter
|
|
@@ -233,12 +287,18 @@ summary — the same information a native tool listing carries, because a trunca
|
|
|
233
287
|
description leaves the model guessing argument names, and a guessed argument is
|
|
234
288
|
the whole difference between roughly reliable and reliable.
|
|
235
289
|
|
|
236
|
-
Better still, where the client honours `notifications/tools/list_changed`,
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
290
|
+
Better still, where the client honours `notifications/tools/list_changed`, a tool
|
|
291
|
+
you **use** is **promoted** to a real first-class tool. From then on the model
|
|
292
|
+
makes an ordinary tool call: the host validates arguments against the real
|
|
293
|
+
schema, the permission prompt names the real tool rather than `call_capability`,
|
|
294
|
+
and the router is not in the execution path at all. It becomes a loader that
|
|
295
|
+
decides what is in your tool list, not a middleman on every call.
|
|
296
|
+
|
|
297
|
+
Promotion is deferred to the first successful call (`activation: "lazy"`) because
|
|
298
|
+
a promoted tool is permanent context and a search hit is not evidence of need —
|
|
299
|
+
most of what a search matches is never called. Set `"activation": "eager"` to
|
|
300
|
+
promote every hit as before, or `"off"` to route everything through
|
|
301
|
+
`call_capability` and carry no tool definitions at all.
|
|
242
302
|
|
|
243
303
|
| supports `listChanged` | proxy only |
|
|
244
304
|
| ----------------------------------------------- | ------------------------------------------------ |
|
|
@@ -261,13 +321,17 @@ the model happened to search for.
|
|
|
261
321
|
|
|
262
322
|
| surface | budget | lifetime |
|
|
263
323
|
| ------------------------- | --------------------------------- | ---------- |
|
|
264
|
-
| promoted tool list | 3,000 tok, LRU eviction
|
|
265
|
-
| inline schemas per search | 700 tok, spent top-down
|
|
266
|
-
| prompt list |
|
|
324
|
+
| promoted tool list | 3,000 tok, LRU eviction, on use only | session |
|
|
325
|
+
| inline schemas per search | 700 tok, spent top-down | one result |
|
|
326
|
+
| prompt list | commands only, clamped to 120 chars | session |
|
|
267
327
|
|
|
268
|
-
|
|
328
|
+
The tool promoted by the call in flight is never evicted — a tool that vanishes
|
|
269
329
|
between being offered and being called is worse than one never offered.
|
|
270
330
|
|
|
331
|
+
`autorouter doctor` reports the real bill per harness rather than summing across
|
|
332
|
+
them, since a session only ever runs in one: a server still registered in Cursor
|
|
333
|
+
costs a Claude Code session nothing.
|
|
334
|
+
|
|
271
335
|
Schemas are **compacted** everywhere they are repeated: `$schema`, `title` and
|
|
272
336
|
`examples` are dropped, and prose is trimmed, more aggressively the deeper it
|
|
273
337
|
sits. Every structural field survives untouched — names, types, enums, `required`,
|
|
@@ -291,6 +355,10 @@ autorouter list --kind skill
|
|
|
291
355
|
autorouter doctor
|
|
292
356
|
autorouter reindex
|
|
293
357
|
|
|
358
|
+
autorouter add linear --url https://mcp.linear.app/mcp
|
|
359
|
+
autorouter add foo -- npx -y foo-mcp
|
|
360
|
+
autorouter remove linear
|
|
361
|
+
|
|
294
362
|
autorouter adopt --target claude --dry-run # preview, change nothing
|
|
295
363
|
autorouter adopt --target claude --servers-only # skip skills and plugins
|
|
296
364
|
autorouter adopt --target claude --keep project-tools --keep-plugin ui-toolkit
|