mcp-lazy 0.1.5 → 0.1.7
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 +59 -6
- package/dist/index.js +211 -94
- package/dist/index.js.map +1 -1
- package/docs/README.ko.md +64 -6
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
╚═╝ ╚═╝ ╚═════╝╚═╝ ╚══════╝╚═╝ ╚═╝╚══════╝ ╚═╝
|
|
8
8
|
</pre>
|
|
9
9
|
|
|
10
|
-
# mcp-lazy
|
|
10
|
+
# mcp-lazy 🫠
|
|
11
11
|
|
|
12
12
|
[한국어](./docs/README.ko.md)
|
|
13
13
|
|
|
@@ -15,18 +15,41 @@
|
|
|
15
15
|
|
|
16
16
|
- MCP servers load all tool definitions into the context window at startup — even before you use them. With 5-10 servers, this can consume 30-50% of your context window. **mcp-lazy** proxies all your MCP servers through a single lightweight proxy that loads tools on-demand.
|
|
17
17
|
|
|
18
|
+
<center>
|
|
19
|
+
|
|
20
|
+
<br>
|
|
21
|
+
|
|
22
|
+
`82 tools exposed at startup`
|
|
23
|
+

|
|
24
|
+
|
|
25
|
+
👇 `Just 2 with mcp-lazy`
|
|
26
|
+
|
|
27
|
+

|
|
28
|
+
|
|
29
|
+
</center>
|
|
30
|
+
|
|
18
31
|
<br>
|
|
19
32
|
|
|
20
33
|
## Quick Start
|
|
21
34
|
|
|
35
|
+
Pick one for your agent:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
npx mcp-lazy add --cursor # Cursor
|
|
39
|
+
npx mcp-lazy add --codex # Codex
|
|
40
|
+
npx mcp-lazy add --antigravity # Antigravity
|
|
41
|
+
npx mcp-lazy add --opencode # Opencode
|
|
42
|
+
npx mcp-lazy add --all # or all at once
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Then pre-build the tool cache (recommended):
|
|
46
|
+
|
|
22
47
|
```bash
|
|
23
|
-
npx mcp-lazy
|
|
24
|
-
npx mcp-lazy add --codex
|
|
25
|
-
npx mcp-lazy add --antigravity
|
|
26
|
-
npx mcp-lazy add --all # or register all at once
|
|
48
|
+
npx mcp-lazy init
|
|
27
49
|
```
|
|
28
50
|
|
|
29
|
-
-
|
|
51
|
+
- The `add` command reads your agent's existing MCP config, saves all server definitions to `~/.mcp-lazy/servers.json`, and replaces the agent config with only the mcp-lazy proxy entry.
|
|
52
|
+
- `init` pre-builds the tool cache so your first agent session starts instantly. Without it, the first session will be slightly slower while mcp-lazy discovers tools from all servers.
|
|
30
53
|
|
|
31
54
|
> **Tip:** Installed a new MCP server? Just re-run `npx mcp-lazy add --<agent>` — no extra steps.
|
|
32
55
|
|
|
@@ -100,6 +123,29 @@ Options:
|
|
|
100
123
|
|
|
101
124
|
<br>
|
|
102
125
|
|
|
126
|
+
### `npx mcp-lazy init`
|
|
127
|
+
|
|
128
|
+
Pre-build the tool cache by connecting to all registered servers:
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
$ npx mcp-lazy init
|
|
132
|
+
|
|
133
|
+
mcp-lazy init — building tool cache...
|
|
134
|
+
|
|
135
|
+
✓ github-mcp 15 tools 342ms
|
|
136
|
+
✓ postgres-mcp 12 tools 518ms
|
|
137
|
+
✗ slack-mcp connection timeout
|
|
138
|
+
✓ filesystem 8 tools 120ms
|
|
139
|
+
|
|
140
|
+
Cache saved: 35 tools from 3/4 servers in 1.2s
|
|
141
|
+
Ready! mcp-lazy serve will start instantly.
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
- Connects to every server in parallel and saves the tool index to `~/.mcp-lazy/tool-cache.json`
|
|
145
|
+
- Run this after `add` so the first agent session starts instantly instead of waiting for discovery
|
|
146
|
+
|
|
147
|
+
<br>
|
|
148
|
+
|
|
103
149
|
### `npx mcp-lazy doctor`
|
|
104
150
|
|
|
105
151
|
Diagnose your setup:
|
|
@@ -148,6 +194,13 @@ Results are sorted by relevance and returned to the agent.
|
|
|
148
194
|
|
|
149
195
|
## FAQ
|
|
150
196
|
|
|
197
|
+
### Q: The first run is slow.
|
|
198
|
+
|
|
199
|
+
- On the very first launch, mcp-lazy connects to every registered MCP server to discover available tools and build the search index. This can take 10-30 seconds depending on the number of servers.
|
|
200
|
+
- After that, the tool index is cached at `~/.mcp-lazy/tool-cache.json`. Subsequent launches load from cache and start in under a second.
|
|
201
|
+
- The cache is automatically refreshed when your server configuration changes.
|
|
202
|
+
- Run `npx mcp-lazy init` after setup to pre-build the cache and avoid the slow first start.
|
|
203
|
+
|
|
151
204
|
### Q: I'm getting "Error: Unexpected error" during setup.
|
|
152
205
|
|
|
153
206
|
- Check that you have read/write permissions for the config directory. For example:
|
package/dist/index.js
CHANGED
|
@@ -232,6 +232,49 @@ var init_version = __esm({
|
|
|
232
232
|
}
|
|
233
233
|
});
|
|
234
234
|
|
|
235
|
+
// src/utils/mcp-client.ts
|
|
236
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
237
|
+
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
238
|
+
async function connectToServer(command, args, env) {
|
|
239
|
+
const client = new Client({
|
|
240
|
+
name: "mcp-lazy-proxy",
|
|
241
|
+
version: VERSION
|
|
242
|
+
});
|
|
243
|
+
const mergedEnv = { ...process.env, ...env };
|
|
244
|
+
const transport = new StdioClientTransport({
|
|
245
|
+
command,
|
|
246
|
+
args,
|
|
247
|
+
env: mergedEnv
|
|
248
|
+
});
|
|
249
|
+
await client.connect(transport);
|
|
250
|
+
return { client, transport };
|
|
251
|
+
}
|
|
252
|
+
async function listServerTools(client) {
|
|
253
|
+
const allTools = [];
|
|
254
|
+
let cursor;
|
|
255
|
+
do {
|
|
256
|
+
const result = await client.listTools({ cursor });
|
|
257
|
+
for (const tool of result.tools) {
|
|
258
|
+
allTools.push({
|
|
259
|
+
name: tool.name,
|
|
260
|
+
description: tool.description,
|
|
261
|
+
inputSchema: tool.inputSchema
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
cursor = result.nextCursor;
|
|
265
|
+
} while (cursor);
|
|
266
|
+
return allTools;
|
|
267
|
+
}
|
|
268
|
+
async function disconnectServer(connection) {
|
|
269
|
+
await connection.client.close();
|
|
270
|
+
}
|
|
271
|
+
var init_mcp_client = __esm({
|
|
272
|
+
"src/utils/mcp-client.ts"() {
|
|
273
|
+
"use strict";
|
|
274
|
+
init_version();
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
|
|
235
278
|
// src/proxy/registry.ts
|
|
236
279
|
var registry_exports = {};
|
|
237
280
|
__export(registry_exports, {
|
|
@@ -320,13 +363,163 @@ var init_registry = __esm({
|
|
|
320
363
|
}
|
|
321
364
|
});
|
|
322
365
|
|
|
366
|
+
// src/utils/discovery.ts
|
|
367
|
+
var discovery_exports = {};
|
|
368
|
+
__export(discovery_exports, {
|
|
369
|
+
discoverTools: () => discoverTools
|
|
370
|
+
});
|
|
371
|
+
async function discoverTools(servers, options) {
|
|
372
|
+
const serverNames = Object.keys(servers);
|
|
373
|
+
const allTools = [];
|
|
374
|
+
const results = [];
|
|
375
|
+
const startMs = Date.now();
|
|
376
|
+
const settled = await Promise.allSettled(
|
|
377
|
+
serverNames.map(async (name) => {
|
|
378
|
+
const serverConfig = servers[name];
|
|
379
|
+
if (!serverConfig.command) {
|
|
380
|
+
const msg = "no command configured, skipping";
|
|
381
|
+
console.error(`Warning: ${name} has ${msg}`);
|
|
382
|
+
options?.onServerFailed?.(name, msg, 0);
|
|
383
|
+
results.push({
|
|
384
|
+
serverName: name,
|
|
385
|
+
status: "skipped",
|
|
386
|
+
toolCount: 0,
|
|
387
|
+
error: msg,
|
|
388
|
+
elapsedMs: 0
|
|
389
|
+
});
|
|
390
|
+
return [];
|
|
391
|
+
}
|
|
392
|
+
options?.onServerStart?.(name);
|
|
393
|
+
const serverStart = Date.now();
|
|
394
|
+
try {
|
|
395
|
+
const conn = await connectToServer(serverConfig.command, serverConfig.args, serverConfig.env);
|
|
396
|
+
const tools = await listServerTools(conn.client);
|
|
397
|
+
await disconnectServer(conn);
|
|
398
|
+
const elapsed = Date.now() - serverStart;
|
|
399
|
+
const entries = tools.map((tool) => ({
|
|
400
|
+
name: tool.name,
|
|
401
|
+
description: tool.description ?? "",
|
|
402
|
+
server: name,
|
|
403
|
+
serverDescription: serverConfig.description ?? "",
|
|
404
|
+
inputSchema: tool.inputSchema,
|
|
405
|
+
keywords: extractKeywords(tool.name, tool.description ?? "")
|
|
406
|
+
}));
|
|
407
|
+
options?.onServerDone?.(name, entries.length, elapsed);
|
|
408
|
+
results.push({
|
|
409
|
+
serverName: name,
|
|
410
|
+
status: "fulfilled",
|
|
411
|
+
toolCount: entries.length,
|
|
412
|
+
elapsedMs: elapsed
|
|
413
|
+
});
|
|
414
|
+
return entries;
|
|
415
|
+
} catch (error) {
|
|
416
|
+
const elapsed = Date.now() - serverStart;
|
|
417
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
418
|
+
options?.onServerFailed?.(name, message, elapsed);
|
|
419
|
+
results.push({
|
|
420
|
+
serverName: name,
|
|
421
|
+
status: "rejected",
|
|
422
|
+
toolCount: 0,
|
|
423
|
+
error: message,
|
|
424
|
+
elapsedMs: elapsed
|
|
425
|
+
});
|
|
426
|
+
throw error;
|
|
427
|
+
}
|
|
428
|
+
})
|
|
429
|
+
);
|
|
430
|
+
for (const result of settled) {
|
|
431
|
+
if (result.status === "fulfilled") {
|
|
432
|
+
for (const entry of result.value) {
|
|
433
|
+
allTools.push(entry);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
return {
|
|
438
|
+
tools: allTools,
|
|
439
|
+
results,
|
|
440
|
+
totalElapsedMs: Date.now() - startMs
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
var init_discovery = __esm({
|
|
444
|
+
"src/utils/discovery.ts"() {
|
|
445
|
+
"use strict";
|
|
446
|
+
init_mcp_client();
|
|
447
|
+
init_registry();
|
|
448
|
+
}
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
// src/cli/init.ts
|
|
452
|
+
var init_exports = {};
|
|
453
|
+
__export(init_exports, {
|
|
454
|
+
runInit: () => runInit
|
|
455
|
+
});
|
|
456
|
+
function formatTime(ms) {
|
|
457
|
+
return ms >= 1e3 ? `${(ms / 1e3).toFixed(1)}s` : `${ms}ms`;
|
|
458
|
+
}
|
|
459
|
+
async function runInit() {
|
|
460
|
+
console.log(BANNER2);
|
|
461
|
+
const servers = loadServersBackup();
|
|
462
|
+
const serverNames = Object.keys(servers);
|
|
463
|
+
if (serverNames.length === 0) {
|
|
464
|
+
console.log(" No MCP servers registered.");
|
|
465
|
+
console.log(" Run \x1B[36mmcp-lazy add --<agent>\x1B[0m first to register your servers.\n");
|
|
466
|
+
process.exit(1);
|
|
467
|
+
}
|
|
468
|
+
console.log(` Building tool cache from ${serverNames.length} server(s)...
|
|
469
|
+
`);
|
|
470
|
+
const result = await discoverTools(servers, {
|
|
471
|
+
onServerDone: (name, toolCount, elapsedMs) => {
|
|
472
|
+
const dim = "\x1B[2m";
|
|
473
|
+
const green = "\x1B[32m";
|
|
474
|
+
const reset = "\x1B[0m";
|
|
475
|
+
console.log(` ${green}\u2713${reset} ${name.padEnd(25)} ${String(toolCount).padStart(3)} tools ${dim}${formatTime(elapsedMs)}${reset}`);
|
|
476
|
+
},
|
|
477
|
+
onServerFailed: (name, error) => {
|
|
478
|
+
const red = "\x1B[31m";
|
|
479
|
+
const dim = "\x1B[2m";
|
|
480
|
+
const reset = "\x1B[0m";
|
|
481
|
+
console.log(` ${red}\u2717${reset} ${name.padEnd(25)} ${dim}${error}${reset}`);
|
|
482
|
+
}
|
|
483
|
+
});
|
|
484
|
+
const successCount = result.results.filter((r) => r.status === "fulfilled" && r.toolCount > 0).length;
|
|
485
|
+
const failedCount = result.results.filter((r) => r.status === "rejected").length;
|
|
486
|
+
const skippedCount = result.results.filter((r) => r.status === "skipped").length;
|
|
487
|
+
const totalServers = serverNames.length - skippedCount;
|
|
488
|
+
console.log("");
|
|
489
|
+
if (result.tools.length === 0) {
|
|
490
|
+
console.log(" No tools discovered from any server. Check your MCP configurations.\n");
|
|
491
|
+
process.exit(1);
|
|
492
|
+
}
|
|
493
|
+
const fingerprint = computeServerFingerprint(servers);
|
|
494
|
+
saveToolCache(fingerprint, result.tools);
|
|
495
|
+
const serverSummary = failedCount > 0 ? `${successCount}/${totalServers} servers (${failedCount} failed)` : `${successCount} servers`;
|
|
496
|
+
console.log(` Cache saved: ${result.tools.length} tools from ${serverSummary} in ${formatTime(result.totalElapsedMs)}`);
|
|
497
|
+
console.log(" \x1B[32mReady!\x1B[0m mcp-lazy serve will start instantly.\n");
|
|
498
|
+
}
|
|
499
|
+
var BANNER2;
|
|
500
|
+
var init_init = __esm({
|
|
501
|
+
"src/cli/init.ts"() {
|
|
502
|
+
"use strict";
|
|
503
|
+
init_config();
|
|
504
|
+
init_discovery();
|
|
505
|
+
BANNER2 = `
|
|
506
|
+
\x1B[36m\x1B[1m \u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557
|
|
507
|
+
\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u255A\u2550\u2550\u2588\u2588\u2588\u2554\u255D\u255A\u2588\u2588\u2557 \u2588\u2588\u2554\u255D
|
|
508
|
+
\u2588\u2588\u2554\u2588\u2588\u2588\u2588\u2554\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551 \u2588\u2588\u2588\u2554\u255D \u255A\u2588\u2588\u2588\u2588\u2554\u255D
|
|
509
|
+
\u2588\u2588\u2551\u255A\u2588\u2588\u2554\u255D\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551 \u2588\u2588\u2588\u2554\u255D \u255A\u2588\u2588\u2554\u255D
|
|
510
|
+
\u2588\u2588\u2551 \u255A\u2550\u255D \u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551
|
|
511
|
+
\u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D\x1B[0m
|
|
512
|
+
`;
|
|
513
|
+
}
|
|
514
|
+
});
|
|
515
|
+
|
|
323
516
|
// src/proxy/loader.ts
|
|
324
517
|
var loader_exports = {};
|
|
325
518
|
__export(loader_exports, {
|
|
326
519
|
ServerLoader: () => ServerLoader
|
|
327
520
|
});
|
|
328
|
-
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
329
|
-
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
521
|
+
import { Client as Client2 } from "@modelcontextprotocol/sdk/client/index.js";
|
|
522
|
+
import { StdioClientTransport as StdioClientTransport2 } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
330
523
|
var ServerLoader;
|
|
331
524
|
var init_loader = __esm({
|
|
332
525
|
"src/proxy/loader.ts"() {
|
|
@@ -381,12 +574,12 @@ var init_loader = __esm({
|
|
|
381
574
|
if (!config.command) {
|
|
382
575
|
throw new Error(`Server ${serverName} has no command configured`);
|
|
383
576
|
}
|
|
384
|
-
const client = new
|
|
577
|
+
const client = new Client2({
|
|
385
578
|
name: `mcp-lazy-proxy/${serverName}`,
|
|
386
579
|
version: VERSION
|
|
387
580
|
});
|
|
388
581
|
const env = { ...process.env, ...config.env };
|
|
389
|
-
const transport = new
|
|
582
|
+
const transport = new StdioClientTransport2({
|
|
390
583
|
command: config.command,
|
|
391
584
|
args: config.args,
|
|
392
585
|
env
|
|
@@ -570,63 +763,6 @@ var init_server = __esm({
|
|
|
570
763
|
}
|
|
571
764
|
});
|
|
572
765
|
|
|
573
|
-
// src/utils/mcp-client.ts
|
|
574
|
-
var mcp_client_exports = {};
|
|
575
|
-
__export(mcp_client_exports, {
|
|
576
|
-
callServerTool: () => callServerTool,
|
|
577
|
-
connectToServer: () => connectToServer,
|
|
578
|
-
disconnectServer: () => disconnectServer,
|
|
579
|
-
listServerTools: () => listServerTools
|
|
580
|
-
});
|
|
581
|
-
import { Client as Client2 } from "@modelcontextprotocol/sdk/client/index.js";
|
|
582
|
-
import { StdioClientTransport as StdioClientTransport2 } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
583
|
-
async function connectToServer(command, args, env) {
|
|
584
|
-
const client = new Client2({
|
|
585
|
-
name: "mcp-lazy-proxy",
|
|
586
|
-
version: VERSION
|
|
587
|
-
});
|
|
588
|
-
const mergedEnv = { ...process.env, ...env };
|
|
589
|
-
const transport = new StdioClientTransport2({
|
|
590
|
-
command,
|
|
591
|
-
args,
|
|
592
|
-
env: mergedEnv
|
|
593
|
-
});
|
|
594
|
-
await client.connect(transport);
|
|
595
|
-
return { client, transport };
|
|
596
|
-
}
|
|
597
|
-
async function listServerTools(client) {
|
|
598
|
-
const allTools = [];
|
|
599
|
-
let cursor;
|
|
600
|
-
do {
|
|
601
|
-
const result = await client.listTools({ cursor });
|
|
602
|
-
for (const tool of result.tools) {
|
|
603
|
-
allTools.push({
|
|
604
|
-
name: tool.name,
|
|
605
|
-
description: tool.description,
|
|
606
|
-
inputSchema: tool.inputSchema
|
|
607
|
-
});
|
|
608
|
-
}
|
|
609
|
-
cursor = result.nextCursor;
|
|
610
|
-
} while (cursor);
|
|
611
|
-
return allTools;
|
|
612
|
-
}
|
|
613
|
-
async function callServerTool(client, toolName, args) {
|
|
614
|
-
const result = await client.callTool({
|
|
615
|
-
name: toolName,
|
|
616
|
-
arguments: args
|
|
617
|
-
});
|
|
618
|
-
return result;
|
|
619
|
-
}
|
|
620
|
-
async function disconnectServer(connection) {
|
|
621
|
-
await connection.client.close();
|
|
622
|
-
}
|
|
623
|
-
var init_mcp_client = __esm({
|
|
624
|
-
"src/utils/mcp-client.ts"() {
|
|
625
|
-
"use strict";
|
|
626
|
-
init_version();
|
|
627
|
-
}
|
|
628
|
-
});
|
|
629
|
-
|
|
630
766
|
// src/index.ts
|
|
631
767
|
import { Command } from "commander";
|
|
632
768
|
|
|
@@ -963,15 +1099,19 @@ program.command("add").description("Register mcp-lazy proxy with an agent").opti
|
|
|
963
1099
|
program.command("doctor").description("Check installation status and token savings").action(async () => {
|
|
964
1100
|
await runDoctor();
|
|
965
1101
|
});
|
|
1102
|
+
program.command("init").description("Pre-build tool cache by connecting to all servers").action(async () => {
|
|
1103
|
+
const { runInit: runInit2 } = await Promise.resolve().then(() => (init_init(), init_exports));
|
|
1104
|
+
await runInit2();
|
|
1105
|
+
});
|
|
966
1106
|
program.command("serve").description("Start the mcp-lazy proxy server (stdio mode)").action(async () => {
|
|
967
1107
|
await runServe();
|
|
968
1108
|
});
|
|
969
1109
|
async function runServe() {
|
|
970
1110
|
const { loadServersBackup: loadServersBackup2, computeServerFingerprint: computeServerFingerprint2, loadToolCache: loadToolCache2, saveToolCache: saveToolCache2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
971
|
-
const { ToolRegistry: ToolRegistry2
|
|
1111
|
+
const { ToolRegistry: ToolRegistry2 } = await Promise.resolve().then(() => (init_registry(), registry_exports));
|
|
972
1112
|
const { ServerLoader: ServerLoader2 } = await Promise.resolve().then(() => (init_loader(), loader_exports));
|
|
973
1113
|
const { startProxyServer: startProxyServer2 } = await Promise.resolve().then(() => (init_server(), server_exports));
|
|
974
|
-
const {
|
|
1114
|
+
const { discoverTools: discoverTools2 } = await Promise.resolve().then(() => (init_discovery(), discovery_exports));
|
|
975
1115
|
const servers = loadServersBackup2();
|
|
976
1116
|
const serverNames = Object.keys(servers);
|
|
977
1117
|
if (serverNames.length === 0) {
|
|
@@ -989,37 +1129,14 @@ async function runServe() {
|
|
|
989
1129
|
const elapsed = Date.now() - startMs;
|
|
990
1130
|
console.error(`mcp-lazy: loaded ${registry.getToolCount()} tools from cache in ${elapsed}ms`);
|
|
991
1131
|
} else {
|
|
992
|
-
const
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
const tools = await listServerTools2(conn.client);
|
|
1001
|
-
await disconnectServer2(conn);
|
|
1002
|
-
return tools.map((tool) => ({
|
|
1003
|
-
name: tool.name,
|
|
1004
|
-
description: tool.description ?? "",
|
|
1005
|
-
server: name,
|
|
1006
|
-
serverDescription: serverConfig.description ?? "",
|
|
1007
|
-
inputSchema: tool.inputSchema,
|
|
1008
|
-
keywords: extractKeywords2(tool.name, tool.description ?? "")
|
|
1009
|
-
}));
|
|
1010
|
-
})
|
|
1011
|
-
);
|
|
1012
|
-
let successCount = 0;
|
|
1013
|
-
for (let i = 0; i < results.length; i++) {
|
|
1014
|
-
const result = results[i];
|
|
1015
|
-
if (result.status === "fulfilled") {
|
|
1016
|
-
for (const entry of result.value) {
|
|
1017
|
-
registry.addTool(entry);
|
|
1018
|
-
}
|
|
1019
|
-
if (result.value.length > 0) successCount++;
|
|
1020
|
-
} else {
|
|
1021
|
-
const message = result.reason instanceof Error ? result.reason.message : String(result.reason);
|
|
1022
|
-
console.error(`Warning: could not connect to ${serverNames[i]}: ${message}`);
|
|
1132
|
+
const result = await discoverTools2(servers);
|
|
1133
|
+
for (const entry of result.tools) {
|
|
1134
|
+
registry.addTool(entry);
|
|
1135
|
+
}
|
|
1136
|
+
const successCount = result.results.filter((r) => r.status === "fulfilled" && r.toolCount > 0).length;
|
|
1137
|
+
for (const r of result.results) {
|
|
1138
|
+
if (r.status === "rejected") {
|
|
1139
|
+
console.error(`Warning: could not connect to ${r.serverName}: ${r.error}`);
|
|
1023
1140
|
}
|
|
1024
1141
|
}
|
|
1025
1142
|
const elapsed = Date.now() - startMs;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/config.ts","../src/version.ts","../src/proxy/registry.ts","../src/proxy/loader.ts","../src/proxy/server.ts","../src/utils/mcp-client.ts","../src/index.ts","../src/agents/index.ts","../src/cli/add.ts","../src/cli/doctor.ts"],"sourcesContent":["import { z } from \"zod\";\nimport { readFileSync, writeFileSync, existsSync, mkdirSync } from \"node:fs\";\nimport { resolve, dirname } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { createHash } from \"node:crypto\";\n\n// Schema for a single MCP server config entry\n// Supports stdio servers (command+args) and URL-based servers (url)\nconst ServerConfigSchema = z.object({\n command: z.string().optional(),\n args: z.array(z.string()).default([]),\n url: z.string().optional(),\n serverUrl: z.string().optional(),\n headers: z.record(z.string()).optional(),\n env: z.record(z.string()).optional(),\n description: z.string().optional(),\n});\n\nexport type ServerConfig = z.infer<typeof ServerConfigSchema>;\n\n// Schema for .mcp.json format (used by agents)\nconst McpJsonSchema = z.object({\n mcpServers: z.record(ServerConfigSchema),\n});\n\nfunction getBackupPath(): string {\n return resolve(homedir(), \".mcp-lazy\", \"servers.json\");\n}\n\n/**\n * Save servers to ~/.mcp-lazy/servers.json (merges with existing)\n */\nexport function saveServersBackup(servers: Record<string, ServerConfig>): void {\n const existing = loadServersBackup();\n const merged = { ...existing, ...servers };\n // Never include mcp-lazy itself\n delete merged[\"mcp-lazy\"];\n\n const dir = dirname(getBackupPath());\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n writeFileSync(getBackupPath(), JSON.stringify({ servers: merged }, null, 2) + \"\\n\");\n}\n\n/**\n * Load servers from ~/.mcp-lazy/servers.json\n */\nexport function loadServersBackup(): Record<string, ServerConfig> {\n if (!existsSync(getBackupPath())) {\n return {};\n }\n try {\n const raw = JSON.parse(readFileSync(getBackupPath(), \"utf-8\"));\n return raw.servers ?? {};\n } catch {\n return {};\n }\n}\n\n/**\n * Convert a URL-based server config to a mcp-remote stdio command.\n * e.g., { url: \"https://mcp.notion.com/mcp\", headers: { \"Auth\": \"Bearer x\" } }\n * → { command: \"npx\", args: [\"-y\", \"mcp-remote\", \"https://mcp.notion.com/mcp\", \"--header\", \"Auth:Bearer x\"] }\n */\nexport function convertUrlToMcpRemote(url: string, headers?: Record<string, string>): ServerConfig {\n const args = [\"-y\", \"mcp-remote\", url];\n if (headers) {\n for (const [key, value] of Object.entries(headers)) {\n args.push(\"--header\", `${key}:${value}`);\n }\n }\n return { command: \"npx\", args };\n}\n\n/**\n * Extract MCP servers from a TOML config file (Codex format)\n * Parses [mcp_servers.XXX] sections and extracts command/args.\n * Filters out mcp-lazy entries.\n */\nexport function extractServersFromToml(content: string): Record<string, ServerConfig> {\n const servers: Record<string, ServerConfig> = {};\n // Match all [mcp_servers.XXX] section headers\n const sectionRegex = /^\\[mcp_servers\\.([^\\]]+)\\]/gm;\n let match: RegExpExecArray | null;\n\n while ((match = sectionRegex.exec(content)) !== null) {\n const name = match[1];\n if (name === \"mcp-lazy\") continue;\n\n const sectionStart = match.index + match[0].length;\n // Find next section header (any [xxx]) or end of string\n const nextSection = /^\\[[^\\]]+\\]/m.exec(content.slice(sectionStart));\n const sectionContent = nextSection\n ? content.slice(sectionStart, sectionStart + nextSection.index)\n : content.slice(sectionStart);\n\n // Extract command\n const cmdMatch = /^\\s*command\\s*=\\s*\"([^\"]+)\"/m.exec(sectionContent);\n const command = cmdMatch ? cmdMatch[1] : undefined;\n\n // Extract url (for HTTP/SSE-based servers)\n const urlMatch = /^\\s*url\\s*=\\s*\"([^\"]*)\"/m.exec(sectionContent);\n const serverUrlMatch = /^\\s*serverUrl\\s*=\\s*\"([^\"]*)\"/m.exec(sectionContent);\n const url = urlMatch ? urlMatch[1] : (serverUrlMatch ? serverUrlMatch[1] : undefined);\n\n // Extract args array: args = [\"a\", \"b\", ...]\n const argsMatch = /^\\s*args\\s*=\\s*\\[([^\\]]*)\\]/m.exec(sectionContent);\n const args: string[] = [];\n if (argsMatch) {\n const inner = argsMatch[1];\n const itemRegex = /\"([^\"]*)\"/g;\n let item: RegExpExecArray | null;\n while ((item = itemRegex.exec(inner)) !== null) {\n args.push(item[1]);\n }\n }\n\n // Extract env from [mcp_servers.NAME.env] subsection\n const env: Record<string, string> = {};\n const envSectionRegex = new RegExp(`^\\\\[mcp_servers\\\\.${name}\\\\.env\\\\]`, \"m\");\n if (envSectionRegex.test(content)) {\n const envStart = content.indexOf(`[mcp_servers.${name}.env]`) + `[mcp_servers.${name}.env]`.length;\n const envEnd = /^\\[[^\\]]+\\]/m.exec(content.slice(envStart));\n const envContent = envEnd\n ? content.slice(envStart, envStart + envEnd.index)\n : content.slice(envStart);\n\n const envPairRegex = /^\\s*(\\w+)\\s*=\\s*\"([^\"]*)\"/gm;\n let envMatch: RegExpExecArray | null;\n while ((envMatch = envPairRegex.exec(envContent)) !== null) {\n env[envMatch[1]] = envMatch[2];\n }\n }\n\n // Extract headers from [mcp_servers.NAME.http_headers] subsection\n const headers: Record<string, string> = {};\n const headersSectionRegex = new RegExp(`^\\\\[mcp_servers\\\\.${name}\\\\.http_headers\\\\]`, \"m\");\n if (headersSectionRegex.test(content)) {\n const headersStart = content.indexOf(`[mcp_servers.${name}.http_headers]`) + `[mcp_servers.${name}.http_headers]`.length;\n const headersEnd = /^\\[[^\\]]+\\]/m.exec(content.slice(headersStart));\n const headersContent = headersEnd\n ? content.slice(headersStart, headersStart + headersEnd.index)\n : content.slice(headersStart);\n const headerPairRegex = /^\\s*(\\S+)\\s*=\\s*\"([^\"]*)\"/gm;\n let headerMatch: RegExpExecArray | null;\n while ((headerMatch = headerPairRegex.exec(headersContent)) !== null) {\n headers[headerMatch[1]] = headerMatch[2];\n }\n }\n\n // Extract bearer_token_env_var and resolve to Authorization header\n const bearerMatch = /^\\s*bearer_token_env_var\\s*=\\s*\"([^\"]*)\"/m.exec(sectionContent);\n if (bearerMatch) {\n const envVarName = bearerMatch[1];\n const token = process.env[envVarName];\n if (token) {\n headers[\"Authorization\"] = `Bearer ${token}`;\n }\n }\n\n if (command) {\n servers[name] = { command, args, ...(url && { url }), ...(Object.keys(env).length > 0 && { env }), ...(Object.keys(headers).length > 0 && { headers }) };\n } else if (url) {\n servers[name] = { args, url, ...(Object.keys(env).length > 0 && { env }), ...(Object.keys(headers).length > 0 && { headers }) };\n }\n }\n\n return servers;\n}\n\n/**\n * Extract MCP servers from an agent's config file (JSON format)\n */\nexport function extractServersFromConfig(configPath: string): Record<string, ServerConfig> {\n if (!existsSync(configPath)) return {};\n try {\n const raw = JSON.parse(readFileSync(configPath, \"utf-8\"));\n const parsed = McpJsonSchema.safeParse(raw);\n if (!parsed.success) return {};\n const servers = { ...parsed.data.mcpServers };\n delete servers[\"mcp-lazy\"];\n // Normalize serverUrl → url\n for (const config of Object.values(servers)) {\n if (config.serverUrl && !config.url) {\n config.url = config.serverUrl;\n }\n delete (config as any).serverUrl;\n }\n return servers;\n } catch {\n return {};\n }\n}\n\nfunction getToolCachePath(): string {\n return resolve(homedir(), \".mcp-lazy\", \"tool-cache.json\");\n}\n\n/**\n * Compute a fingerprint for a set of server configs.\n * Any change to server names, commands, or args invalidates the cache.\n */\nexport function computeServerFingerprint(servers: Record<string, ServerConfig>): string {\n const parts = Object.keys(servers)\n .sort()\n .map((name) => {\n const s = servers[name];\n return `${name}:${s.command ?? \"\"}:${(s.args ?? []).join(\",\")}`;\n });\n return createHash(\"sha256\").update(parts.join(\"|\")).digest(\"hex\");\n}\n\n/**\n * Load the tool cache from ~/.mcp-lazy/tool-cache.json.\n * Returns null if the file does not exist or cannot be parsed.\n */\nexport function loadToolCache(): { fingerprint: string; tools: any[] } | null {\n const cachePath = getToolCachePath();\n if (!existsSync(cachePath)) return null;\n try {\n const raw = JSON.parse(readFileSync(cachePath, \"utf-8\"));\n if (typeof raw.fingerprint === \"string\" && Array.isArray(raw.tools)) {\n return raw as { fingerprint: string; tools: any[] };\n }\n return null;\n } catch {\n return null;\n }\n}\n\n/**\n * Save the tool cache to ~/.mcp-lazy/tool-cache.json.\n */\nexport function saveToolCache(fingerprint: string, tools: any[]): void {\n const cachePath = getToolCachePath();\n const dir = dirname(cachePath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n writeFileSync(cachePath, JSON.stringify({ fingerprint, tools }, null, 2) + \"\\n\");\n}\n\n/**\n * Extract MCP servers from Opencode's config format.\n * Opencode uses { mcp: { name: { type, command: [...], environment } } }\n */\nexport function extractServersFromOpencodeConfig(configPath: string): Record<string, ServerConfig> {\n if (!existsSync(configPath)) return {};\n try {\n const raw = JSON.parse(readFileSync(configPath, \"utf-8\"));\n const mcpSection = raw.mcp;\n if (!mcpSection || typeof mcpSection !== \"object\") return {};\n\n const servers: Record<string, ServerConfig> = {};\n for (const [name, config] of Object.entries(mcpSection)) {\n if (name === \"mcp-lazy\") continue;\n const cfg = config as any;\n\n if (cfg.type === \"local\" && Array.isArray(cfg.command) && cfg.command.length > 0) {\n // Stdio server: command is array, first element is command, rest are args\n servers[name] = {\n command: cfg.command[0],\n args: cfg.command.slice(1),\n ...(cfg.environment && { env: cfg.environment }),\n };\n } else if (cfg.type === \"remote\" && cfg.url) {\n // HTTP/SSE server\n servers[name] = {\n url: cfg.url,\n args: [],\n ...(cfg.headers && { headers: cfg.headers }),\n };\n }\n }\n return servers;\n } catch {\n return {};\n }\n}\n","export const VERSION = \"0.1.0\";\n","export interface ToolEntry {\n name: string;\n description: string;\n server: string;\n serverDescription: string;\n inputSchema: Record<string, unknown>;\n keywords: string[];\n}\n\nexport interface SearchResult {\n tool_name: string;\n server_name: string;\n description: string;\n relevance_score: number;\n}\n\nexport class ToolRegistry {\n private tools: ToolEntry[] = [];\n\n addTool(entry: ToolEntry): void {\n this.tools.push(entry);\n }\n\n addTools(entries: ToolEntry[]): void {\n this.tools.push(...entries);\n }\n\n getToolCount(): number {\n return this.tools.length;\n }\n\n getAllTools(): ToolEntry[] {\n return [...this.tools];\n }\n\n getServerNames(): string[] {\n return [...new Set(this.tools.map((t) => t.server))];\n }\n\n getToolsByServer(serverName: string): ToolEntry[] {\n return this.tools.filter((t) => t.server === serverName);\n }\n\n findTool(toolName: string, serverName: string): ToolEntry | undefined {\n return this.tools.find(\n (t) => t.name === toolName && t.server === serverName\n );\n }\n\n search(query: string, limit: number = 5): SearchResult[] {\n const queryLower = query.toLowerCase();\n const queryTokens = queryLower.split(/\\s+/).filter(Boolean);\n\n const scored: { entry: ToolEntry; score: number }[] = [];\n\n for (const entry of this.tools) {\n let score = 0;\n const nameLower = entry.name.toLowerCase();\n const descLower = entry.description.toLowerCase();\n const serverDescLower = entry.serverDescription.toLowerCase();\n\n // 1. tool_name exact match\n if (nameLower === queryLower) {\n score += 1.0;\n }\n // 2. tool_name partial match\n else if (\n nameLower.includes(queryLower) ||\n queryTokens.some((t) => nameLower.includes(t))\n ) {\n score += 0.8;\n }\n\n // 3. description keyword match (per token)\n for (const token of queryTokens) {\n if (descLower.includes(token)) {\n score += 0.6;\n }\n }\n\n // 4. server description match\n for (const token of queryTokens) {\n if (serverDescLower.includes(token)) {\n score += 0.4;\n break; // Only count once for server description\n }\n }\n\n // Also check keywords\n for (const token of queryTokens) {\n if (entry.keywords.some((k) => k.toLowerCase().includes(token))) {\n score += 0.3;\n }\n }\n\n if (score > 0) {\n scored.push({ entry, score });\n }\n }\n\n return scored\n .sort((a, b) => b.score - a.score)\n .slice(0, limit)\n .map(({ entry, score }) => ({\n tool_name: entry.name,\n server_name: entry.server,\n description: entry.description,\n relevance_score: Math.round(score * 100) / 100,\n }));\n }\n\n clear(): void {\n this.tools = [];\n }\n}\n\n// Helper to extract keywords from tool name and description\nexport function extractKeywords(name: string, description: string): string[] {\n const text = `${name} ${description}`;\n const words = text\n .replace(/[_-]/g, \" \")\n .replace(/([a-z])([A-Z])/g, \"$1 $2\")\n .toLowerCase()\n .split(/\\s+/)\n .filter((w) => w.length > 2);\n return [...new Set(words)];\n}\n","import { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { StdioClientTransport } from \"@modelcontextprotocol/sdk/client/stdio.js\";\nimport type { ServerConfig } from \"../utils/config.js\";\nimport { VERSION } from \"../version.js\";\n\ninterface LoadedServer {\n client: Client;\n transport: unknown;\n loadedAt: Date;\n}\n\nexport class ServerLoader {\n private servers = new Map<string, LoadedServer>();\n private serverConfigs: Record<string, ServerConfig>;\n private loading = new Map<string, Promise<Client>>();\n\n constructor(serverConfigs: Record<string, ServerConfig>) {\n this.serverConfigs = serverConfigs;\n }\n\n async getClient(serverName: string): Promise<Client> {\n // Return cached client\n const existing = this.servers.get(serverName);\n if (existing) {\n return existing.client;\n }\n\n // Deduplicate concurrent loads\n const pendingLoad = this.loading.get(serverName);\n if (pendingLoad) {\n return pendingLoad;\n }\n\n const loadPromise = this.loadServer(serverName);\n this.loading.set(serverName, loadPromise);\n\n try {\n const client = await loadPromise;\n return client;\n } finally {\n this.loading.delete(serverName);\n }\n }\n\n private async loadServer(serverName: string): Promise<Client> {\n const config = this.serverConfigs[serverName];\n if (!config) {\n throw new Error(`Unknown server: ${serverName}`);\n }\n\n try {\n return await this.attemptConnect(serverName, config);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (message.includes(\"timed out\")) {\n try {\n return await this.attemptConnect(serverName, config);\n } catch (retryError) {\n throw retryError;\n }\n }\n throw error;\n }\n }\n\n private async attemptConnect(serverName: string, config: ServerConfig): Promise<Client> {\n const timeoutMs = 30000;\n\n if (!config.command) {\n throw new Error(`Server ${serverName} has no command configured`);\n }\n\n const client = new Client({\n name: `mcp-lazy-proxy/${serverName}`,\n version: VERSION,\n });\n\n const env = { ...process.env, ...config.env } as Record<string, string>;\n const transport = new StdioClientTransport({\n command: config.command,\n args: config.args,\n env,\n });\n\n const connectPromise = client.connect(transport);\n const timeoutPromise = new Promise<never>((_, reject) =>\n setTimeout(() => reject(new Error(`Server ${serverName} timed out after ${timeoutMs}ms`)), timeoutMs)\n );\n\n await Promise.race([connectPromise, timeoutPromise]);\n\n this.servers.set(serverName, {\n client,\n transport: transport as unknown,\n loadedAt: new Date(),\n });\n\n return client;\n }\n\n getLoadedServers(): string[] {\n return [...this.servers.keys()];\n }\n\n isLoaded(serverName: string): boolean {\n return this.servers.has(serverName);\n }\n\n async closeServer(serverName: string): Promise<void> {\n const server = this.servers.get(serverName);\n if (server) {\n await server.client.close();\n this.servers.delete(serverName);\n }\n }\n\n async closeAll(): Promise<void> {\n const closePromises = [...this.servers.keys()].map((name) =>\n this.closeServer(name)\n );\n await Promise.allSettled(closePromises);\n }\n\n hasConfig(serverName: string): boolean {\n return serverName in this.serverConfigs;\n }\n}\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { z } from \"zod\";\nimport { ToolRegistry } from \"./registry.js\";\nimport { ServerLoader } from \"./loader.js\";\nimport { VERSION } from \"../version.js\";\n\nexport async function createProxyServer(\n registry: ToolRegistry,\n loader: ServerLoader\n): Promise<McpServer> {\n const server = new McpServer({\n name: \"mcp-lazy\",\n version: VERSION,\n });\n\n // Tool 1: mcp_search_tools\n server.tool(\n \"mcp_search_tools\",\n `Search available MCP tools by keyword.\nUse this BEFORE calling any MCP tool.\nReturns matching tool names, server names, and descriptions.\nExample: mcp_search_tools(\"query database\") → postgres-mcp.query_database`,\n {\n query: z.string().describe(\"What you want to do in natural language\"),\n limit: z.number().optional().default(5).describe(\"Max results to return (default: 5)\"),\n },\n async ({ query, limit }) => {\n const results = registry.search(query, limit);\n\n if (results.length === 0) {\n // Suggest similar tools\n const allServers = registry.getServerNames();\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n results: [],\n suggestion: `No tools found for \"${query}\". Available servers: ${allServers.join(\", \")}. Try different keywords.`,\n }),\n },\n ],\n };\n }\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({ results }),\n },\n ],\n };\n }\n );\n\n // Tool 2: mcp_execute_tool\n server.tool(\n \"mcp_execute_tool\",\n `Execute a specific MCP tool.\nUse tool_name and server_name from mcp_search_tools results.`,\n {\n tool_name: z.string().describe(\"Tool name from mcp_search_tools\"),\n server_name: z.string().describe(\"Server name from mcp_search_tools\"),\n arguments: z.record(z.unknown()).optional().describe(\"Tool arguments\"),\n },\n async ({ tool_name, server_name, arguments: args }) => {\n // Verify tool exists in registry\n const tool = registry.findTool(tool_name, server_name);\n if (!tool) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n error: `Tool \"${tool_name}\" not found in server \"${server_name}\". Use mcp_search_tools first.`,\n }),\n },\n ],\n isError: true,\n };\n }\n\n // Verify server config exists\n if (!loader.hasConfig(server_name)) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n error: `Server \"${server_name}\" is not configured.`,\n }),\n },\n ],\n isError: true,\n };\n }\n\n try {\n // Lazy-load server (cached after first call)\n const client = await loader.getClient(server_name);\n\n // Call the actual tool\n const result = await client.callTool({\n name: tool_name,\n arguments: args ?? {},\n });\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify(result),\n },\n ],\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n const alternatives = registry.search(tool_name, 3);\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n error: `Failed to execute ${tool_name} on ${server_name}: ${message}`,\n alternatives: alternatives.length > 0 ? alternatives : undefined,\n }),\n },\n ],\n isError: true,\n };\n }\n }\n );\n\n return server;\n}\n\nexport async function startProxyServer(\n registry: ToolRegistry,\n loader: ServerLoader\n): Promise<void> {\n const server = await createProxyServer(registry, loader);\n const transport = new StdioServerTransport();\n await server.connect(transport);\n\n // Graceful shutdown\n process.on(\"SIGINT\", async () => {\n await loader.closeAll();\n process.exit(0);\n });\n process.on(\"SIGTERM\", async () => {\n await loader.closeAll();\n process.exit(0);\n });\n}\n","import { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { StdioClientTransport } from \"@modelcontextprotocol/sdk/client/stdio.js\";\nimport { VERSION } from \"../version.js\";\n\nexport interface ToolDefinition {\n name: string;\n description?: string;\n inputSchema: Record<string, unknown>;\n}\n\nexport interface ServerConnection {\n client: Client;\n transport: unknown;\n}\n\nexport async function connectToServer(\n command: string,\n args: string[],\n env?: Record<string, string>\n): Promise<ServerConnection> {\n const client = new Client({\n name: \"mcp-lazy-proxy\",\n version: VERSION,\n });\n\n const mergedEnv = { ...process.env, ...env } as Record<string, string>;\n\n const transport = new StdioClientTransport({\n command,\n args,\n env: mergedEnv,\n });\n\n await client.connect(transport);\n return { client, transport };\n}\n\nexport async function listServerTools(\n client: Client\n): Promise<ToolDefinition[]> {\n const allTools: ToolDefinition[] = [];\n let cursor: string | undefined;\n\n do {\n const result = await client.listTools({ cursor });\n for (const tool of result.tools) {\n allTools.push({\n name: tool.name,\n description: tool.description,\n inputSchema: tool.inputSchema as Record<string, unknown>,\n });\n }\n cursor = result.nextCursor;\n } while (cursor);\n\n return allTools;\n}\n\nexport async function callServerTool(\n client: Client,\n toolName: string,\n args?: Record<string, unknown>\n): Promise<unknown> {\n const result = await client.callTool({\n name: toolName,\n arguments: args,\n });\n return result;\n}\n\nexport async function disconnectServer(\n connection: ServerConnection\n): Promise<void> {\n await connection.client.close();\n}\n","#!/usr/bin/env node\n\nimport { Command } from \"commander\";\nimport { runAdd } from \"./cli/add.js\";\nimport { runDoctor } from \"./cli/doctor.js\";\nimport { VERSION } from \"./version.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"mcp-lazy\")\n .description(\"MCP lazy loading proxy - reduce context window token usage by 90%+\")\n .version(VERSION);\n\nprogram\n .command(\"add\")\n .description(\"Register mcp-lazy proxy with an agent\")\n .option(\"--cursor\", \"Register with Cursor\")\n .option(\"--opencode\", \"Register with Opencode\")\n .option(\"--antigravity\", \"Register with Antigravity\")\n .option(\"--codex\", \"Register with Codex\")\n .option(\"--all\", \"Register with all agents\")\n .action(async (options) => {\n await runAdd(options);\n });\n\nprogram\n .command(\"doctor\")\n .description(\"Check installation status and token savings\")\n .action(async () => {\n await runDoctor();\n });\n\nprogram\n .command(\"serve\")\n .description(\"Start the mcp-lazy proxy server (stdio mode)\")\n .action(async () => {\n await runServe();\n });\n\nasync function runServe(): Promise<void> {\n const { loadServersBackup, computeServerFingerprint, loadToolCache, saveToolCache } = await import(\"./utils/config.js\");\n const { ToolRegistry, extractKeywords } = await import(\"./proxy/registry.js\");\n const { ServerLoader } = await import(\"./proxy/loader.js\");\n const { startProxyServer } = await import(\"./proxy/server.js\");\n const { connectToServer, listServerTools, disconnectServer } = await import(\n \"./utils/mcp-client.js\"\n );\n\n // Load servers from ~/.mcp-lazy/servers.json\n const servers = loadServersBackup();\n const serverNames = Object.keys(servers);\n\n if (serverNames.length === 0) {\n console.error(\"No MCP servers found. Check your MCP configurations.\");\n process.exit(1);\n }\n\n // Build the tool registry by connecting to each server once\n const registry = new ToolRegistry();\n const startMs = Date.now();\n\n const fingerprint = computeServerFingerprint(servers);\n const cached = loadToolCache();\n\n if (cached && cached.fingerprint === fingerprint) {\n // Cache hit: load tools directly, skip all connections\n for (const entry of cached.tools) {\n registry.addTool(entry);\n }\n const elapsed = Date.now() - startMs;\n console.error(`mcp-lazy: loaded ${registry.getToolCount()} tools from cache in ${elapsed}ms`);\n } else {\n // Cache miss or config changed: connect to all servers in parallel\n const results = await Promise.allSettled(\n serverNames.map(async (name) => {\n const serverConfig = servers[name];\n if (!serverConfig.command) {\n console.error(`Warning: ${name} has no command configured, skipping`);\n return [];\n }\n const conn = await connectToServer(serverConfig.command, serverConfig.args, serverConfig.env);\n const tools = await listServerTools(conn.client);\n await disconnectServer(conn);\n return tools.map((tool) => ({\n name: tool.name,\n description: tool.description ?? \"\",\n server: name,\n serverDescription: serverConfig.description ?? \"\",\n inputSchema: tool.inputSchema,\n keywords: extractKeywords(tool.name, tool.description ?? \"\"),\n }));\n })\n );\n\n let successCount = 0;\n for (let i = 0; i < results.length; i++) {\n const result = results[i];\n if (result.status === \"fulfilled\") {\n for (const entry of result.value) {\n registry.addTool(entry);\n }\n if (result.value.length > 0) successCount++;\n } else {\n const message = result.reason instanceof Error ? result.reason.message : String(result.reason);\n console.error(`Warning: could not connect to ${serverNames[i]}: ${message}`);\n }\n }\n\n const elapsed = Date.now() - startMs;\n console.error(`mcp-lazy: discovered ${registry.getToolCount()} tools from ${successCount} servers in ${elapsed}ms`);\n\n // Save cache for next startup\n saveToolCache(fingerprint, registry.getAllTools());\n }\n\n if (registry.getToolCount() === 0) {\n console.error(\"No tools discovered from any server. Check your MCP configurations.\");\n process.exit(1);\n }\n\n // Create the loader for lazy re-connections during execution\n const loader = new ServerLoader(servers);\n\n // Start the proxy server (stdio)\n await startProxyServer(registry, loader);\n}\n\nprogram.parse();\n","import { existsSync, readFileSync, writeFileSync, mkdirSync } from \"node:fs\";\nimport { resolve, dirname } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { extractServersFromConfig, extractServersFromToml, extractServersFromOpencodeConfig, saveServersBackup, convertUrlToMcpRemote, type ServerConfig } from \"../utils/config.js\";\n\nexport interface AgentInfo {\n name: string;\n displayName: string;\n configPaths: string[];\n format?: \"json\" | \"toml\" | \"opencode\";\n note?: string;\n}\n\nfunction resolvePath(p: string): string {\n const home = homedir();\n const cwd = process.cwd();\n return p.startsWith(\"~\") ? resolve(home, p.slice(2)) : resolve(cwd, p);\n}\n\nexport const AGENTS: AgentInfo[] = [\n {\n name: \"cursor\",\n displayName: \"Cursor\",\n configPaths: [\"~/.cursor/mcp.json\"],\n },\n {\n name: \"opencode\",\n displayName: \"Opencode\",\n configPaths: [\"~/.config/opencode/config.json\"],\n format: \"opencode\",\n },\n {\n name: \"antigravity\",\n displayName: \"Antigravity\",\n configPaths: [\"~/.gemini/antigravity/mcp_config.json\"],\n },\n {\n name: \"codex\",\n displayName: \"Codex\",\n configPaths: [\"~/.codex/config.toml\"],\n format: \"toml\",\n },\n];\n\nexport function detectInstalledAgents(): AgentInfo[] {\n return AGENTS.filter((agent) =>\n agent.configPaths.some((p) => existsSync(resolvePath(p)))\n );\n}\n\nexport function getAgentByName(name: string): AgentInfo | undefined {\n return AGENTS.find((a) => a.name === name);\n}\n\nexport function findAgentConfig(agent: AgentInfo): string | null {\n for (const p of agent.configPaths) {\n const resolved = resolvePath(p);\n if (existsSync(resolved)) {\n return resolved;\n }\n }\n return null;\n}\n\nfunction generateProxyEntry(): Record<string, unknown> {\n return {\n command: \"npx\",\n args: [\"-y\", \"mcp-lazy\", \"serve\"],\n };\n}\n\nexport function registerProxy(\n agent: AgentInfo\n): { configPath: string; created: boolean; serverCount: number } {\n const existing = findAgentConfig(agent);\n const fallback = agent.configPaths[0];\n let targetPath = existing ?? resolvePath(fallback);\n\n let created = false;\n let serverCount = 0;\n\n if (agent.format === \"opencode\") {\n if (existsSync(targetPath)) {\n try {\n const fullConfig = JSON.parse(readFileSync(targetPath, \"utf-8\"));\n const mcpSection = fullConfig.mcp || {};\n\n const serversToBackup: Record<string, ServerConfig> = {};\n\n for (const [name, cfg] of Object.entries(mcpSection)) {\n if (name === \"mcp-lazy\") continue;\n const c = cfg as any;\n if (c.type === \"remote\" && c.url) {\n // Convert URL to mcp-remote\n serversToBackup[name] = convertUrlToMcpRemote(c.url, c.headers);\n } else if (c.type === \"local\" && Array.isArray(c.command) && c.command.length > 0) {\n // Stdio: normalize from opencode format\n serversToBackup[name] = {\n command: c.command[0],\n args: c.command.slice(1),\n ...(c.environment && { env: c.environment }),\n };\n }\n }\n\n serverCount = Object.keys(serversToBackup).length;\n if (serverCount > 0) {\n saveServersBackup(serversToBackup);\n }\n\n // Write: only mcp-lazy (preserve non-mcp keys)\n fullConfig.mcp = {\n \"mcp-lazy\": {\n type: \"local\",\n command: [\"npx\", \"-y\", \"mcp-lazy\", \"serve\"],\n },\n };\n writeFileSync(targetPath, JSON.stringify(fullConfig, null, 2) + \"\\n\");\n } catch {\n // If can't parse, write fresh\n const config = { mcp: { \"mcp-lazy\": { type: \"local\", command: [\"npx\", \"-y\", \"mcp-lazy\", \"serve\"] } } };\n writeFileSync(targetPath, JSON.stringify(config, null, 2) + \"\\n\");\n }\n } else {\n created = true;\n const dir = dirname(targetPath);\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n const config = { mcp: { \"mcp-lazy\": { type: \"local\", command: [\"npx\", \"-y\", \"mcp-lazy\", \"serve\"] } } };\n writeFileSync(targetPath, JSON.stringify(config, null, 2) + \"\\n\");\n }\n return { configPath: targetPath, created, serverCount };\n }\n\n if (agent.format === \"toml\") {\n if (!existsSync(targetPath)) {\n created = true;\n const dir = dirname(targetPath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n }\n\n const existingContent = existsSync(targetPath)\n ? readFileSync(targetPath, \"utf-8\")\n : \"\";\n\n // Extract all servers\n const allServers = extractServersFromToml(existingContent);\n const serversToBackup: Record<string, ServerConfig> = {};\n\n for (const [name, cfg] of Object.entries(allServers)) {\n if (cfg.command) {\n serversToBackup[name] = cfg;\n } else if (cfg.url) {\n // Convert URL to mcp-remote\n serversToBackup[name] = convertUrlToMcpRemote(cfg.url, cfg.headers);\n }\n }\n\n serverCount = Object.keys(serversToBackup).length;\n if (serverCount > 0) {\n saveServersBackup(serversToBackup);\n }\n\n // Strip ALL mcp_servers sections (including URL ones)\n let cleaned = existingContent.replace(\n /\\n?\\[mcp_servers\\.[^\\]]+\\](?:\\n(?!\\[)[^\\n]*)*/g,\n \"\"\n ).trimEnd();\n\n const tomlBlock =\n `\\n\\n[mcp_servers.mcp-lazy]\\n` +\n `command = \"npx\"\\n` +\n `args = [\"-y\", \"mcp-lazy\", \"serve\"]\\n`;\n\n writeFileSync(targetPath, cleaned + tomlBlock);\n\n return { configPath: targetPath, created, serverCount };\n }\n\n // JSON agents: extract ALL servers → convert URL to mcp-remote → backup ALL → write only mcp-lazy\n if (existsSync(targetPath)) {\n // Read raw config to get original field names\n let rawConfig: any = {};\n try {\n rawConfig = JSON.parse(readFileSync(targetPath, \"utf-8\"));\n } catch {}\n const rawServers = rawConfig.mcpServers ?? {};\n\n const serversToBackup: Record<string, ServerConfig> = {};\n\n // Extract normalized servers via Zod\n const normalizedServers = extractServersFromConfig(targetPath);\n\n for (const [name, serverCfg] of Object.entries(rawServers)) {\n if (name === \"mcp-lazy\") continue;\n const cfg = serverCfg as any;\n\n if (cfg.url || cfg.serverUrl) {\n // URL server → convert to mcp-remote stdio command\n const url = cfg.url || cfg.serverUrl;\n const headers = cfg.headers;\n serversToBackup[name] = convertUrlToMcpRemote(url, headers);\n } else if (cfg.command && normalizedServers[name]) {\n // Stdio server → use normalized version\n serversToBackup[name] = normalizedServers[name];\n }\n }\n\n serverCount = Object.keys(serversToBackup).length;\n if (serverCount > 0) {\n saveServersBackup(serversToBackup);\n }\n\n // Write config with ONLY mcp-lazy (no URL servers kept)\n const config = {\n mcpServers: {\n \"mcp-lazy\": generateProxyEntry(),\n },\n };\n\n writeFileSync(targetPath, JSON.stringify(config, null, 2) + \"\\n\");\n } else {\n created = true;\n const dir = dirname(targetPath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n const config = {\n mcpServers: {\n \"mcp-lazy\": generateProxyEntry(),\n },\n };\n\n writeFileSync(targetPath, JSON.stringify(config, null, 2) + \"\\n\");\n }\n\n return { configPath: targetPath, created, serverCount };\n}\n\nexport function isProxyRegistered(agent: AgentInfo): boolean {\n const configPath = findAgentConfig(agent);\n if (!configPath) return false;\n\n if (agent.format === \"opencode\") {\n try {\n const config = JSON.parse(readFileSync(configPath, \"utf-8\"));\n return !!(config.mcp && config.mcp[\"mcp-lazy\"]);\n } catch {\n return false;\n }\n }\n\n if (agent.format === \"toml\") {\n try {\n const content = readFileSync(configPath, \"utf-8\");\n return content.includes(\"[mcp_servers.mcp-lazy]\");\n } catch {\n return false;\n }\n }\n\n try {\n const config = JSON.parse(readFileSync(configPath, \"utf-8\"));\n return !!(config.mcpServers && config.mcpServers[\"mcp-lazy\"]);\n } catch {\n return false;\n }\n}\n","import {\n AGENTS,\n getAgentByName,\n registerProxy,\n type AgentInfo,\n} from \"../agents/index.js\";\n\nconst BANNER = `\n\\x1b[36m\\x1b[1m ███╗ ███╗ ██████╗██████╗ ██╗ █████╗ ███████╗██╗ ██╗\n ████╗ ████║██╔════╝██╔══██╗ ██║ ██╔══██╗╚══███╔╝╚██╗ ██╔╝\n ██╔████╔██║██║ ██████╔╝█████╗██║ ███████║ ███╔╝ ╚████╔╝\n ██║╚██╔╝██║██║ ██╔═══╝ ╚════╝██║ ██╔══██║ ███╔╝ ╚██╔╝\n ██║ ╚═╝ ██║╚██████╗██║ ███████╗██║ ██║███████╗ ██║\n ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚══════╝╚═╝ ╚═╝╚══════╝ ╚═╝\\x1b[0m\n`;\n\ninterface AddOptions {\n cursor?: boolean;\n opencode?: boolean;\n antigravity?: boolean;\n codex?: boolean;\n all?: boolean;\n}\n\nexport async function runAdd(options: AddOptions): Promise<void> {\n console.log(BANNER);\n\n // Determine which agents to register\n let targets: AgentInfo[] = [];\n\n if (options.all) {\n targets = [...AGENTS];\n } else {\n const flagMap: Record<string, boolean | undefined> = {\n cursor: options.cursor,\n opencode: options.opencode,\n antigravity: options.antigravity,\n codex: options.codex,\n };\n\n for (const [name, enabled] of Object.entries(flagMap)) {\n if (enabled) {\n const agent = getAgentByName(name);\n if (agent) {\n targets.push(agent);\n }\n }\n }\n }\n\n if (targets.length === 0) {\n console.log(\" No agent specified. Use one of:\");\n console.log(\" mcp-lazy add --cursor\");\n console.log(\" mcp-lazy add --opencode\");\n console.log(\" mcp-lazy add --antigravity\");\n console.log(\" mcp-lazy add --codex\");\n console.log(\" mcp-lazy add --all\\n\");\n process.exit(1);\n }\n\n console.log(\" Registering mcp-lazy proxy...\\n\");\n\n for (const agent of targets) {\n try {\n const { configPath, created, serverCount } = registerProxy(agent);\n const action = created ? \"created\" : \"updated\";\n const servers = serverCount > 0 ? ` (${serverCount} servers captured)` : \"\";\n console.log(` ✓ ${agent.displayName}: ${action} ${configPath}${servers}`);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n console.log(` ✗ ${agent.displayName}: failed - ${message}`);\n }\n }\n\n console.log(\"\\n Done! Restart your agents to activate mcp-lazy.\\n\");\n}\n","import { loadServersBackup } from \"../utils/config.js\";\nimport { AGENTS, isProxyRegistered } from \"../agents/index.js\";\n\nconst TOKENS_PER_TOOL = 650;\nconst PROXY_BASE_TOKENS = 350;\n\nexport async function runDoctor(): Promise<void> {\n let hasIssues = false;\n\n console.log(\"\\nmcp-lazy status check\\n\");\n\n // 1. Check Node.js version\n const nodeVersion = process.versions.node;\n const major = parseInt(nodeVersion.split(\".\")[0], 10);\n if (major >= 18) {\n console.log(` ✓ Node.js ${nodeVersion}`);\n } else {\n console.log(` ✗ Node.js ${nodeVersion} (requires >= 18)`);\n hasIssues = true;\n }\n\n // 2. Check servers backup\n const servers = loadServersBackup();\n const serverCount = Object.keys(servers).length;\n\n if (serverCount > 0) {\n const serverNames = Object.keys(servers);\n console.log(` ✓ ${serverCount} MCP server(s) registered`);\n for (const name of serverNames) {\n console.log(` - ${name}`);\n }\n } else {\n console.log(` ✗ No MCP servers registered -> run 'mcp-lazy add --<agent>'`);\n hasIssues = true;\n }\n\n // 3. Check agent registrations\n console.log(\"\");\n let registeredCount = 0;\n for (const agent of AGENTS) {\n const registered = isProxyRegistered(agent);\n if (registered) {\n console.log(` ✓ ${agent.displayName} registered`);\n registeredCount++;\n } else {\n console.log(` - ${agent.displayName} not registered -> mcp-lazy add --${agent.name}`);\n }\n }\n\n if (registeredCount === 0) {\n console.log(\"\\n No agents registered. Run 'mcp-lazy add --<agent>' to register.\");\n hasIssues = true;\n }\n\n // 4. Token savings estimation\n if (serverCount > 0) {\n const estimatedTools = serverCount * 15;\n const estimatedTokens = estimatedTools * TOKENS_PER_TOOL;\n const savings = estimatedTokens > 0\n ? Math.round(((estimatedTokens - PROXY_BASE_TOKENS) / estimatedTokens) * 100)\n : 0;\n\n console.log(`\\n Token savings estimate:`);\n console.log(` ${serverCount} server(s) registered`);\n console.log(` Without mcp-lazy: ~${estimatedTokens.toLocaleString()} tokens`);\n console.log(` With mcp-lazy: ${PROXY_BASE_TOKENS.toLocaleString()} tokens`);\n console.log(` Estimated savings: ${savings}%`);\n }\n\n console.log(\"\");\n if (!hasIssues) {\n console.log(\" All checks passed.\\n\");\n } else {\n console.log(\" Some issues found. See above for details.\\n\");\n }\n}\n"],"mappings":"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","names":["z","Client","StdioClientTransport","existsSync","readFileSync","writeFileSync","mkdirSync","resolve","dirname","homedir","existsSync","readFileSync","writeFileSync","dirname","mkdirSync","loadServersBackup","computeServerFingerprint","loadToolCache","saveToolCache","ToolRegistry","extractKeywords","ServerLoader","startProxyServer","connectToServer","listServerTools","disconnectServer"]}
|
|
1
|
+
{"version":3,"sources":["../src/utils/config.ts","../src/version.ts","../src/utils/mcp-client.ts","../src/proxy/registry.ts","../src/utils/discovery.ts","../src/cli/init.ts","../src/proxy/loader.ts","../src/proxy/server.ts","../src/index.ts","../src/agents/index.ts","../src/cli/add.ts","../src/cli/doctor.ts"],"sourcesContent":["import { z } from \"zod\";\nimport { readFileSync, writeFileSync, existsSync, mkdirSync } from \"node:fs\";\nimport { resolve, dirname } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { createHash } from \"node:crypto\";\n\n// Schema for a single MCP server config entry\n// Supports stdio servers (command+args) and URL-based servers (url)\nconst ServerConfigSchema = z.object({\n command: z.string().optional(),\n args: z.array(z.string()).default([]),\n url: z.string().optional(),\n serverUrl: z.string().optional(),\n headers: z.record(z.string()).optional(),\n env: z.record(z.string()).optional(),\n description: z.string().optional(),\n});\n\nexport type ServerConfig = z.infer<typeof ServerConfigSchema>;\n\n// Schema for .mcp.json format (used by agents)\nconst McpJsonSchema = z.object({\n mcpServers: z.record(ServerConfigSchema),\n});\n\nfunction getBackupPath(): string {\n return resolve(homedir(), \".mcp-lazy\", \"servers.json\");\n}\n\n/**\n * Save servers to ~/.mcp-lazy/servers.json (merges with existing)\n */\nexport function saveServersBackup(servers: Record<string, ServerConfig>): void {\n const existing = loadServersBackup();\n const merged = { ...existing, ...servers };\n // Never include mcp-lazy itself\n delete merged[\"mcp-lazy\"];\n\n const dir = dirname(getBackupPath());\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n writeFileSync(getBackupPath(), JSON.stringify({ servers: merged }, null, 2) + \"\\n\");\n}\n\n/**\n * Load servers from ~/.mcp-lazy/servers.json\n */\nexport function loadServersBackup(): Record<string, ServerConfig> {\n if (!existsSync(getBackupPath())) {\n return {};\n }\n try {\n const raw = JSON.parse(readFileSync(getBackupPath(), \"utf-8\"));\n return raw.servers ?? {};\n } catch {\n return {};\n }\n}\n\n/**\n * Convert a URL-based server config to a mcp-remote stdio command.\n * e.g., { url: \"https://mcp.notion.com/mcp\", headers: { \"Auth\": \"Bearer x\" } }\n * → { command: \"npx\", args: [\"-y\", \"mcp-remote\", \"https://mcp.notion.com/mcp\", \"--header\", \"Auth:Bearer x\"] }\n */\nexport function convertUrlToMcpRemote(url: string, headers?: Record<string, string>): ServerConfig {\n const args = [\"-y\", \"mcp-remote\", url];\n if (headers) {\n for (const [key, value] of Object.entries(headers)) {\n args.push(\"--header\", `${key}:${value}`);\n }\n }\n return { command: \"npx\", args };\n}\n\n/**\n * Extract MCP servers from a TOML config file (Codex format)\n * Parses [mcp_servers.XXX] sections and extracts command/args.\n * Filters out mcp-lazy entries.\n */\nexport function extractServersFromToml(content: string): Record<string, ServerConfig> {\n const servers: Record<string, ServerConfig> = {};\n // Match all [mcp_servers.XXX] section headers\n const sectionRegex = /^\\[mcp_servers\\.([^\\]]+)\\]/gm;\n let match: RegExpExecArray | null;\n\n while ((match = sectionRegex.exec(content)) !== null) {\n const name = match[1];\n if (name === \"mcp-lazy\") continue;\n\n const sectionStart = match.index + match[0].length;\n // Find next section header (any [xxx]) or end of string\n const nextSection = /^\\[[^\\]]+\\]/m.exec(content.slice(sectionStart));\n const sectionContent = nextSection\n ? content.slice(sectionStart, sectionStart + nextSection.index)\n : content.slice(sectionStart);\n\n // Extract command\n const cmdMatch = /^\\s*command\\s*=\\s*\"([^\"]+)\"/m.exec(sectionContent);\n const command = cmdMatch ? cmdMatch[1] : undefined;\n\n // Extract url (for HTTP/SSE-based servers)\n const urlMatch = /^\\s*url\\s*=\\s*\"([^\"]*)\"/m.exec(sectionContent);\n const serverUrlMatch = /^\\s*serverUrl\\s*=\\s*\"([^\"]*)\"/m.exec(sectionContent);\n const url = urlMatch ? urlMatch[1] : (serverUrlMatch ? serverUrlMatch[1] : undefined);\n\n // Extract args array: args = [\"a\", \"b\", ...]\n const argsMatch = /^\\s*args\\s*=\\s*\\[([^\\]]*)\\]/m.exec(sectionContent);\n const args: string[] = [];\n if (argsMatch) {\n const inner = argsMatch[1];\n const itemRegex = /\"([^\"]*)\"/g;\n let item: RegExpExecArray | null;\n while ((item = itemRegex.exec(inner)) !== null) {\n args.push(item[1]);\n }\n }\n\n // Extract env from [mcp_servers.NAME.env] subsection\n const env: Record<string, string> = {};\n const envSectionRegex = new RegExp(`^\\\\[mcp_servers\\\\.${name}\\\\.env\\\\]`, \"m\");\n if (envSectionRegex.test(content)) {\n const envStart = content.indexOf(`[mcp_servers.${name}.env]`) + `[mcp_servers.${name}.env]`.length;\n const envEnd = /^\\[[^\\]]+\\]/m.exec(content.slice(envStart));\n const envContent = envEnd\n ? content.slice(envStart, envStart + envEnd.index)\n : content.slice(envStart);\n\n const envPairRegex = /^\\s*(\\w+)\\s*=\\s*\"([^\"]*)\"/gm;\n let envMatch: RegExpExecArray | null;\n while ((envMatch = envPairRegex.exec(envContent)) !== null) {\n env[envMatch[1]] = envMatch[2];\n }\n }\n\n // Extract headers from [mcp_servers.NAME.http_headers] subsection\n const headers: Record<string, string> = {};\n const headersSectionRegex = new RegExp(`^\\\\[mcp_servers\\\\.${name}\\\\.http_headers\\\\]`, \"m\");\n if (headersSectionRegex.test(content)) {\n const headersStart = content.indexOf(`[mcp_servers.${name}.http_headers]`) + `[mcp_servers.${name}.http_headers]`.length;\n const headersEnd = /^\\[[^\\]]+\\]/m.exec(content.slice(headersStart));\n const headersContent = headersEnd\n ? content.slice(headersStart, headersStart + headersEnd.index)\n : content.slice(headersStart);\n const headerPairRegex = /^\\s*(\\S+)\\s*=\\s*\"([^\"]*)\"/gm;\n let headerMatch: RegExpExecArray | null;\n while ((headerMatch = headerPairRegex.exec(headersContent)) !== null) {\n headers[headerMatch[1]] = headerMatch[2];\n }\n }\n\n // Extract bearer_token_env_var and resolve to Authorization header\n const bearerMatch = /^\\s*bearer_token_env_var\\s*=\\s*\"([^\"]*)\"/m.exec(sectionContent);\n if (bearerMatch) {\n const envVarName = bearerMatch[1];\n const token = process.env[envVarName];\n if (token) {\n headers[\"Authorization\"] = `Bearer ${token}`;\n }\n }\n\n if (command) {\n servers[name] = { command, args, ...(url && { url }), ...(Object.keys(env).length > 0 && { env }), ...(Object.keys(headers).length > 0 && { headers }) };\n } else if (url) {\n servers[name] = { args, url, ...(Object.keys(env).length > 0 && { env }), ...(Object.keys(headers).length > 0 && { headers }) };\n }\n }\n\n return servers;\n}\n\n/**\n * Extract MCP servers from an agent's config file (JSON format)\n */\nexport function extractServersFromConfig(configPath: string): Record<string, ServerConfig> {\n if (!existsSync(configPath)) return {};\n try {\n const raw = JSON.parse(readFileSync(configPath, \"utf-8\"));\n const parsed = McpJsonSchema.safeParse(raw);\n if (!parsed.success) return {};\n const servers = { ...parsed.data.mcpServers };\n delete servers[\"mcp-lazy\"];\n // Normalize serverUrl → url\n for (const config of Object.values(servers)) {\n if (config.serverUrl && !config.url) {\n config.url = config.serverUrl;\n }\n delete (config as any).serverUrl;\n }\n return servers;\n } catch {\n return {};\n }\n}\n\nfunction getToolCachePath(): string {\n return resolve(homedir(), \".mcp-lazy\", \"tool-cache.json\");\n}\n\n/**\n * Compute a fingerprint for a set of server configs.\n * Any change to server names, commands, or args invalidates the cache.\n */\nexport function computeServerFingerprint(servers: Record<string, ServerConfig>): string {\n const parts = Object.keys(servers)\n .sort()\n .map((name) => {\n const s = servers[name];\n return `${name}:${s.command ?? \"\"}:${(s.args ?? []).join(\",\")}`;\n });\n return createHash(\"sha256\").update(parts.join(\"|\")).digest(\"hex\");\n}\n\n/**\n * Load the tool cache from ~/.mcp-lazy/tool-cache.json.\n * Returns null if the file does not exist or cannot be parsed.\n */\nexport function loadToolCache(): { fingerprint: string; tools: any[] } | null {\n const cachePath = getToolCachePath();\n if (!existsSync(cachePath)) return null;\n try {\n const raw = JSON.parse(readFileSync(cachePath, \"utf-8\"));\n if (typeof raw.fingerprint === \"string\" && Array.isArray(raw.tools)) {\n return raw as { fingerprint: string; tools: any[] };\n }\n return null;\n } catch {\n return null;\n }\n}\n\n/**\n * Save the tool cache to ~/.mcp-lazy/tool-cache.json.\n */\nexport function saveToolCache(fingerprint: string, tools: any[]): void {\n const cachePath = getToolCachePath();\n const dir = dirname(cachePath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n writeFileSync(cachePath, JSON.stringify({ fingerprint, tools }, null, 2) + \"\\n\");\n}\n\n/**\n * Extract MCP servers from Opencode's config format.\n * Opencode uses { mcp: { name: { type, command: [...], environment } } }\n */\nexport function extractServersFromOpencodeConfig(configPath: string): Record<string, ServerConfig> {\n if (!existsSync(configPath)) return {};\n try {\n const raw = JSON.parse(readFileSync(configPath, \"utf-8\"));\n const mcpSection = raw.mcp;\n if (!mcpSection || typeof mcpSection !== \"object\") return {};\n\n const servers: Record<string, ServerConfig> = {};\n for (const [name, config] of Object.entries(mcpSection)) {\n if (name === \"mcp-lazy\") continue;\n const cfg = config as any;\n\n if (cfg.type === \"local\" && Array.isArray(cfg.command) && cfg.command.length > 0) {\n // Stdio server: command is array, first element is command, rest are args\n servers[name] = {\n command: cfg.command[0],\n args: cfg.command.slice(1),\n ...(cfg.environment && { env: cfg.environment }),\n };\n } else if (cfg.type === \"remote\" && cfg.url) {\n // HTTP/SSE server\n servers[name] = {\n url: cfg.url,\n args: [],\n ...(cfg.headers && { headers: cfg.headers }),\n };\n }\n }\n return servers;\n } catch {\n return {};\n }\n}\n","export const VERSION = \"0.1.0\";\n","import { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { StdioClientTransport } from \"@modelcontextprotocol/sdk/client/stdio.js\";\nimport { VERSION } from \"../version.js\";\n\nexport interface ToolDefinition {\n name: string;\n description?: string;\n inputSchema: Record<string, unknown>;\n}\n\nexport interface ServerConnection {\n client: Client;\n transport: unknown;\n}\n\nexport async function connectToServer(\n command: string,\n args: string[],\n env?: Record<string, string>\n): Promise<ServerConnection> {\n const client = new Client({\n name: \"mcp-lazy-proxy\",\n version: VERSION,\n });\n\n const mergedEnv = { ...process.env, ...env } as Record<string, string>;\n\n const transport = new StdioClientTransport({\n command,\n args,\n env: mergedEnv,\n });\n\n await client.connect(transport);\n return { client, transport };\n}\n\nexport async function listServerTools(\n client: Client\n): Promise<ToolDefinition[]> {\n const allTools: ToolDefinition[] = [];\n let cursor: string | undefined;\n\n do {\n const result = await client.listTools({ cursor });\n for (const tool of result.tools) {\n allTools.push({\n name: tool.name,\n description: tool.description,\n inputSchema: tool.inputSchema as Record<string, unknown>,\n });\n }\n cursor = result.nextCursor;\n } while (cursor);\n\n return allTools;\n}\n\nexport async function callServerTool(\n client: Client,\n toolName: string,\n args?: Record<string, unknown>\n): Promise<unknown> {\n const result = await client.callTool({\n name: toolName,\n arguments: args,\n });\n return result;\n}\n\nexport async function disconnectServer(\n connection: ServerConnection\n): Promise<void> {\n await connection.client.close();\n}\n","export interface ToolEntry {\n name: string;\n description: string;\n server: string;\n serverDescription: string;\n inputSchema: Record<string, unknown>;\n keywords: string[];\n}\n\nexport interface SearchResult {\n tool_name: string;\n server_name: string;\n description: string;\n relevance_score: number;\n}\n\nexport class ToolRegistry {\n private tools: ToolEntry[] = [];\n\n addTool(entry: ToolEntry): void {\n this.tools.push(entry);\n }\n\n addTools(entries: ToolEntry[]): void {\n this.tools.push(...entries);\n }\n\n getToolCount(): number {\n return this.tools.length;\n }\n\n getAllTools(): ToolEntry[] {\n return [...this.tools];\n }\n\n getServerNames(): string[] {\n return [...new Set(this.tools.map((t) => t.server))];\n }\n\n getToolsByServer(serverName: string): ToolEntry[] {\n return this.tools.filter((t) => t.server === serverName);\n }\n\n findTool(toolName: string, serverName: string): ToolEntry | undefined {\n return this.tools.find(\n (t) => t.name === toolName && t.server === serverName\n );\n }\n\n search(query: string, limit: number = 5): SearchResult[] {\n const queryLower = query.toLowerCase();\n const queryTokens = queryLower.split(/\\s+/).filter(Boolean);\n\n const scored: { entry: ToolEntry; score: number }[] = [];\n\n for (const entry of this.tools) {\n let score = 0;\n const nameLower = entry.name.toLowerCase();\n const descLower = entry.description.toLowerCase();\n const serverDescLower = entry.serverDescription.toLowerCase();\n\n // 1. tool_name exact match\n if (nameLower === queryLower) {\n score += 1.0;\n }\n // 2. tool_name partial match\n else if (\n nameLower.includes(queryLower) ||\n queryTokens.some((t) => nameLower.includes(t))\n ) {\n score += 0.8;\n }\n\n // 3. description keyword match (per token)\n for (const token of queryTokens) {\n if (descLower.includes(token)) {\n score += 0.6;\n }\n }\n\n // 4. server description match\n for (const token of queryTokens) {\n if (serverDescLower.includes(token)) {\n score += 0.4;\n break; // Only count once for server description\n }\n }\n\n // Also check keywords\n for (const token of queryTokens) {\n if (entry.keywords.some((k) => k.toLowerCase().includes(token))) {\n score += 0.3;\n }\n }\n\n if (score > 0) {\n scored.push({ entry, score });\n }\n }\n\n return scored\n .sort((a, b) => b.score - a.score)\n .slice(0, limit)\n .map(({ entry, score }) => ({\n tool_name: entry.name,\n server_name: entry.server,\n description: entry.description,\n relevance_score: Math.round(score * 100) / 100,\n }));\n }\n\n clear(): void {\n this.tools = [];\n }\n}\n\n// Helper to extract keywords from tool name and description\nexport function extractKeywords(name: string, description: string): string[] {\n const text = `${name} ${description}`;\n const words = text\n .replace(/[_-]/g, \" \")\n .replace(/([a-z])([A-Z])/g, \"$1 $2\")\n .toLowerCase()\n .split(/\\s+/)\n .filter((w) => w.length > 2);\n return [...new Set(words)];\n}\n","import type { ServerConfig } from \"./config.js\";\nimport type { ToolEntry } from \"../proxy/registry.js\";\nimport { connectToServer, listServerTools, disconnectServer } from \"./mcp-client.js\";\nimport { extractKeywords } from \"../proxy/registry.js\";\n\nexport interface ServerResult {\n serverName: string;\n status: \"fulfilled\" | \"rejected\" | \"skipped\";\n toolCount: number;\n error?: string;\n elapsedMs: number;\n}\n\nexport interface DiscoveryResult {\n tools: ToolEntry[];\n results: ServerResult[];\n totalElapsedMs: number;\n}\n\nexport async function discoverTools(\n servers: Record<string, ServerConfig>,\n options?: {\n onServerStart?: (serverName: string) => void;\n onServerDone?: (serverName: string, toolCount: number, elapsedMs: number) => void;\n onServerFailed?: (serverName: string, error: string, elapsedMs: number) => void;\n }\n): Promise<DiscoveryResult> {\n const serverNames = Object.keys(servers);\n const allTools: ToolEntry[] = [];\n const results: ServerResult[] = [];\n const startMs = Date.now();\n\n const settled = await Promise.allSettled(\n serverNames.map(async (name): Promise<ToolEntry[]> => {\n const serverConfig = servers[name];\n if (!serverConfig.command) {\n const msg = \"no command configured, skipping\";\n console.error(`Warning: ${name} has ${msg}`);\n options?.onServerFailed?.(name, msg, 0);\n results.push({\n serverName: name,\n status: \"skipped\",\n toolCount: 0,\n error: msg,\n elapsedMs: 0,\n });\n return [];\n }\n\n options?.onServerStart?.(name);\n const serverStart = Date.now();\n\n try {\n const conn = await connectToServer(serverConfig.command, serverConfig.args, serverConfig.env);\n const tools = await listServerTools(conn.client);\n await disconnectServer(conn);\n const elapsed = Date.now() - serverStart;\n\n const entries: ToolEntry[] = tools.map((tool) => ({\n name: tool.name,\n description: tool.description ?? \"\",\n server: name,\n serverDescription: serverConfig.description ?? \"\",\n inputSchema: tool.inputSchema,\n keywords: extractKeywords(tool.name, tool.description ?? \"\"),\n }));\n\n options?.onServerDone?.(name, entries.length, elapsed);\n results.push({\n serverName: name,\n status: \"fulfilled\",\n toolCount: entries.length,\n elapsedMs: elapsed,\n });\n return entries;\n } catch (error) {\n const elapsed = Date.now() - serverStart;\n const message = error instanceof Error ? error.message : String(error);\n options?.onServerFailed?.(name, message, elapsed);\n results.push({\n serverName: name,\n status: \"rejected\",\n toolCount: 0,\n error: message,\n elapsedMs: elapsed,\n });\n throw error;\n }\n })\n );\n\n for (const result of settled) {\n if (result.status === \"fulfilled\") {\n for (const entry of result.value) {\n allTools.push(entry);\n }\n }\n // Rejected results are already recorded in the results array via the catch block\n }\n\n return {\n tools: allTools,\n results,\n totalElapsedMs: Date.now() - startMs,\n };\n}\n","import {\n loadServersBackup,\n computeServerFingerprint,\n saveToolCache,\n} from \"../utils/config.js\";\nimport { discoverTools } from \"../utils/discovery.js\";\n\nconst BANNER = `\n\\x1b[36m\\x1b[1m ███╗ ███╗ ██████╗██████╗ ██╗ █████╗ ███████╗██╗ ██╗\n ████╗ ████║██╔════╝██╔══██╗ ██║ ██╔══██╗╚══███╔╝╚██╗ ██╔╝\n ██╔████╔██║██║ ██████╔╝█████╗██║ ███████║ ███╔╝ ╚████╔╝\n ██║╚██╔╝██║██║ ██╔═══╝ ╚════╝██║ ██╔══██║ ███╔╝ ╚██╔╝\n ██║ ╚═╝ ██║╚██████╗██║ ███████╗██║ ██║███████╗ ██║\n ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚══════╝╚═╝ ╚═╝╚══════╝ ╚═╝\\x1b[0m\n`;\n\nfunction formatTime(ms: number): string {\n return ms >= 1000 ? `${(ms / 1000).toFixed(1)}s` : `${ms}ms`;\n}\n\nexport async function runInit(): Promise<void> {\n console.log(BANNER);\n\n const servers = loadServersBackup();\n const serverNames = Object.keys(servers);\n\n if (serverNames.length === 0) {\n console.log(\" No MCP servers registered.\");\n console.log(\" Run \\x1b[36mmcp-lazy add --<agent>\\x1b[0m first to register your servers.\\n\");\n process.exit(1);\n }\n\n console.log(` Building tool cache from ${serverNames.length} server(s)...\\n`);\n\n const result = await discoverTools(servers, {\n onServerDone: (name, toolCount, elapsedMs) => {\n const dim = \"\\x1b[2m\";\n const green = \"\\x1b[32m\";\n const reset = \"\\x1b[0m\";\n console.log(` ${green}\\u2713${reset} ${name.padEnd(25)} ${String(toolCount).padStart(3)} tools ${dim}${formatTime(elapsedMs)}${reset}`);\n },\n onServerFailed: (name, error) => {\n const red = \"\\x1b[31m\";\n const dim = \"\\x1b[2m\";\n const reset = \"\\x1b[0m\";\n console.log(` ${red}\\u2717${reset} ${name.padEnd(25)} ${dim}${error}${reset}`);\n },\n });\n\n const successCount = result.results.filter(r => r.status === \"fulfilled\" && r.toolCount > 0).length;\n const failedCount = result.results.filter(r => r.status === \"rejected\").length;\n const skippedCount = result.results.filter(r => r.status === \"skipped\").length;\n const totalServers = serverNames.length - skippedCount;\n\n console.log(\"\");\n\n if (result.tools.length === 0) {\n console.log(\" No tools discovered from any server. Check your MCP configurations.\\n\");\n process.exit(1);\n }\n\n // Save cache\n const fingerprint = computeServerFingerprint(servers);\n saveToolCache(fingerprint, result.tools);\n\n const serverSummary = failedCount > 0\n ? `${successCount}/${totalServers} servers (${failedCount} failed)`\n : `${successCount} servers`;\n\n console.log(` Cache saved: ${result.tools.length} tools from ${serverSummary} in ${formatTime(result.totalElapsedMs)}`);\n console.log(\" \\x1b[32mReady!\\x1b[0m mcp-lazy serve will start instantly.\\n\");\n}\n","import { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { StdioClientTransport } from \"@modelcontextprotocol/sdk/client/stdio.js\";\nimport type { ServerConfig } from \"../utils/config.js\";\nimport { VERSION } from \"../version.js\";\n\ninterface LoadedServer {\n client: Client;\n transport: unknown;\n loadedAt: Date;\n}\n\nexport class ServerLoader {\n private servers = new Map<string, LoadedServer>();\n private serverConfigs: Record<string, ServerConfig>;\n private loading = new Map<string, Promise<Client>>();\n\n constructor(serverConfigs: Record<string, ServerConfig>) {\n this.serverConfigs = serverConfigs;\n }\n\n async getClient(serverName: string): Promise<Client> {\n // Return cached client\n const existing = this.servers.get(serverName);\n if (existing) {\n return existing.client;\n }\n\n // Deduplicate concurrent loads\n const pendingLoad = this.loading.get(serverName);\n if (pendingLoad) {\n return pendingLoad;\n }\n\n const loadPromise = this.loadServer(serverName);\n this.loading.set(serverName, loadPromise);\n\n try {\n const client = await loadPromise;\n return client;\n } finally {\n this.loading.delete(serverName);\n }\n }\n\n private async loadServer(serverName: string): Promise<Client> {\n const config = this.serverConfigs[serverName];\n if (!config) {\n throw new Error(`Unknown server: ${serverName}`);\n }\n\n try {\n return await this.attemptConnect(serverName, config);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (message.includes(\"timed out\")) {\n try {\n return await this.attemptConnect(serverName, config);\n } catch (retryError) {\n throw retryError;\n }\n }\n throw error;\n }\n }\n\n private async attemptConnect(serverName: string, config: ServerConfig): Promise<Client> {\n const timeoutMs = 30000;\n\n if (!config.command) {\n throw new Error(`Server ${serverName} has no command configured`);\n }\n\n const client = new Client({\n name: `mcp-lazy-proxy/${serverName}`,\n version: VERSION,\n });\n\n const env = { ...process.env, ...config.env } as Record<string, string>;\n const transport = new StdioClientTransport({\n command: config.command,\n args: config.args,\n env,\n });\n\n const connectPromise = client.connect(transport);\n const timeoutPromise = new Promise<never>((_, reject) =>\n setTimeout(() => reject(new Error(`Server ${serverName} timed out after ${timeoutMs}ms`)), timeoutMs)\n );\n\n await Promise.race([connectPromise, timeoutPromise]);\n\n this.servers.set(serverName, {\n client,\n transport: transport as unknown,\n loadedAt: new Date(),\n });\n\n return client;\n }\n\n getLoadedServers(): string[] {\n return [...this.servers.keys()];\n }\n\n isLoaded(serverName: string): boolean {\n return this.servers.has(serverName);\n }\n\n async closeServer(serverName: string): Promise<void> {\n const server = this.servers.get(serverName);\n if (server) {\n await server.client.close();\n this.servers.delete(serverName);\n }\n }\n\n async closeAll(): Promise<void> {\n const closePromises = [...this.servers.keys()].map((name) =>\n this.closeServer(name)\n );\n await Promise.allSettled(closePromises);\n }\n\n hasConfig(serverName: string): boolean {\n return serverName in this.serverConfigs;\n }\n}\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { z } from \"zod\";\nimport { ToolRegistry } from \"./registry.js\";\nimport { ServerLoader } from \"./loader.js\";\nimport { VERSION } from \"../version.js\";\n\nexport async function createProxyServer(\n registry: ToolRegistry,\n loader: ServerLoader\n): Promise<McpServer> {\n const server = new McpServer({\n name: \"mcp-lazy\",\n version: VERSION,\n });\n\n // Tool 1: mcp_search_tools\n server.tool(\n \"mcp_search_tools\",\n `Search available MCP tools by keyword.\nUse this BEFORE calling any MCP tool.\nReturns matching tool names, server names, and descriptions.\nExample: mcp_search_tools(\"query database\") → postgres-mcp.query_database`,\n {\n query: z.string().describe(\"What you want to do in natural language\"),\n limit: z.number().optional().default(5).describe(\"Max results to return (default: 5)\"),\n },\n async ({ query, limit }) => {\n const results = registry.search(query, limit);\n\n if (results.length === 0) {\n // Suggest similar tools\n const allServers = registry.getServerNames();\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n results: [],\n suggestion: `No tools found for \"${query}\". Available servers: ${allServers.join(\", \")}. Try different keywords.`,\n }),\n },\n ],\n };\n }\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({ results }),\n },\n ],\n };\n }\n );\n\n // Tool 2: mcp_execute_tool\n server.tool(\n \"mcp_execute_tool\",\n `Execute a specific MCP tool.\nUse tool_name and server_name from mcp_search_tools results.`,\n {\n tool_name: z.string().describe(\"Tool name from mcp_search_tools\"),\n server_name: z.string().describe(\"Server name from mcp_search_tools\"),\n arguments: z.record(z.unknown()).optional().describe(\"Tool arguments\"),\n },\n async ({ tool_name, server_name, arguments: args }) => {\n // Verify tool exists in registry\n const tool = registry.findTool(tool_name, server_name);\n if (!tool) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n error: `Tool \"${tool_name}\" not found in server \"${server_name}\". Use mcp_search_tools first.`,\n }),\n },\n ],\n isError: true,\n };\n }\n\n // Verify server config exists\n if (!loader.hasConfig(server_name)) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n error: `Server \"${server_name}\" is not configured.`,\n }),\n },\n ],\n isError: true,\n };\n }\n\n try {\n // Lazy-load server (cached after first call)\n const client = await loader.getClient(server_name);\n\n // Call the actual tool\n const result = await client.callTool({\n name: tool_name,\n arguments: args ?? {},\n });\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify(result),\n },\n ],\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n const alternatives = registry.search(tool_name, 3);\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n error: `Failed to execute ${tool_name} on ${server_name}: ${message}`,\n alternatives: alternatives.length > 0 ? alternatives : undefined,\n }),\n },\n ],\n isError: true,\n };\n }\n }\n );\n\n return server;\n}\n\nexport async function startProxyServer(\n registry: ToolRegistry,\n loader: ServerLoader\n): Promise<void> {\n const server = await createProxyServer(registry, loader);\n const transport = new StdioServerTransport();\n await server.connect(transport);\n\n // Graceful shutdown\n process.on(\"SIGINT\", async () => {\n await loader.closeAll();\n process.exit(0);\n });\n process.on(\"SIGTERM\", async () => {\n await loader.closeAll();\n process.exit(0);\n });\n}\n","#!/usr/bin/env node\n\nimport { Command } from \"commander\";\nimport { runAdd } from \"./cli/add.js\";\nimport { runDoctor } from \"./cli/doctor.js\";\nimport { VERSION } from \"./version.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"mcp-lazy\")\n .description(\"MCP lazy loading proxy - reduce context window token usage by 90%+\")\n .version(VERSION);\n\nprogram\n .command(\"add\")\n .description(\"Register mcp-lazy proxy with an agent\")\n .option(\"--cursor\", \"Register with Cursor\")\n .option(\"--opencode\", \"Register with Opencode\")\n .option(\"--antigravity\", \"Register with Antigravity\")\n .option(\"--codex\", \"Register with Codex\")\n .option(\"--all\", \"Register with all agents\")\n .action(async (options) => {\n await runAdd(options);\n });\n\nprogram\n .command(\"doctor\")\n .description(\"Check installation status and token savings\")\n .action(async () => {\n await runDoctor();\n });\n\nprogram\n .command(\"init\")\n .description(\"Pre-build tool cache by connecting to all servers\")\n .action(async () => {\n const { runInit } = await import(\"./cli/init.js\");\n await runInit();\n });\n\nprogram\n .command(\"serve\")\n .description(\"Start the mcp-lazy proxy server (stdio mode)\")\n .action(async () => {\n await runServe();\n });\n\nasync function runServe(): Promise<void> {\n const { loadServersBackup, computeServerFingerprint, loadToolCache, saveToolCache } = await import(\"./utils/config.js\");\n const { ToolRegistry } = await import(\"./proxy/registry.js\");\n const { ServerLoader } = await import(\"./proxy/loader.js\");\n const { startProxyServer } = await import(\"./proxy/server.js\");\n const { discoverTools } = await import(\"./utils/discovery.js\");\n\n // Load servers from ~/.mcp-lazy/servers.json\n const servers = loadServersBackup();\n const serverNames = Object.keys(servers);\n\n if (serverNames.length === 0) {\n console.error(\"No MCP servers found. Check your MCP configurations.\");\n process.exit(1);\n }\n\n // Build the tool registry by connecting to each server once\n const registry = new ToolRegistry();\n const startMs = Date.now();\n\n const fingerprint = computeServerFingerprint(servers);\n const cached = loadToolCache();\n\n if (cached && cached.fingerprint === fingerprint) {\n // Cache hit: load tools directly, skip all connections\n for (const entry of cached.tools) {\n registry.addTool(entry);\n }\n const elapsed = Date.now() - startMs;\n console.error(`mcp-lazy: loaded ${registry.getToolCount()} tools from cache in ${elapsed}ms`);\n } else {\n // Cache miss or config changed: connect to all servers in parallel\n const result = await discoverTools(servers);\n\n for (const entry of result.tools) {\n registry.addTool(entry);\n }\n\n const successCount = result.results.filter(r => r.status === \"fulfilled\" && r.toolCount > 0).length;\n\n for (const r of result.results) {\n if (r.status === \"rejected\") {\n console.error(`Warning: could not connect to ${r.serverName}: ${r.error}`);\n }\n }\n\n const elapsed = Date.now() - startMs;\n console.error(`mcp-lazy: discovered ${registry.getToolCount()} tools from ${successCount} servers in ${elapsed}ms`);\n\n // Save cache for next startup\n saveToolCache(fingerprint, registry.getAllTools());\n }\n\n if (registry.getToolCount() === 0) {\n console.error(\"No tools discovered from any server. Check your MCP configurations.\");\n process.exit(1);\n }\n\n // Create the loader for lazy re-connections during execution\n const loader = new ServerLoader(servers);\n\n // Start the proxy server (stdio)\n await startProxyServer(registry, loader);\n}\n\nprogram.parse();\n","import { existsSync, readFileSync, writeFileSync, mkdirSync } from \"node:fs\";\nimport { resolve, dirname } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { extractServersFromConfig, extractServersFromToml, extractServersFromOpencodeConfig, saveServersBackup, convertUrlToMcpRemote, type ServerConfig } from \"../utils/config.js\";\n\nexport interface AgentInfo {\n name: string;\n displayName: string;\n configPaths: string[];\n format?: \"json\" | \"toml\" | \"opencode\";\n note?: string;\n}\n\nfunction resolvePath(p: string): string {\n const home = homedir();\n const cwd = process.cwd();\n return p.startsWith(\"~\") ? resolve(home, p.slice(2)) : resolve(cwd, p);\n}\n\nexport const AGENTS: AgentInfo[] = [\n {\n name: \"cursor\",\n displayName: \"Cursor\",\n configPaths: [\"~/.cursor/mcp.json\"],\n },\n {\n name: \"opencode\",\n displayName: \"Opencode\",\n configPaths: [\"~/.config/opencode/config.json\"],\n format: \"opencode\",\n },\n {\n name: \"antigravity\",\n displayName: \"Antigravity\",\n configPaths: [\"~/.gemini/antigravity/mcp_config.json\"],\n },\n {\n name: \"codex\",\n displayName: \"Codex\",\n configPaths: [\"~/.codex/config.toml\"],\n format: \"toml\",\n },\n];\n\nexport function detectInstalledAgents(): AgentInfo[] {\n return AGENTS.filter((agent) =>\n agent.configPaths.some((p) => existsSync(resolvePath(p)))\n );\n}\n\nexport function getAgentByName(name: string): AgentInfo | undefined {\n return AGENTS.find((a) => a.name === name);\n}\n\nexport function findAgentConfig(agent: AgentInfo): string | null {\n for (const p of agent.configPaths) {\n const resolved = resolvePath(p);\n if (existsSync(resolved)) {\n return resolved;\n }\n }\n return null;\n}\n\nfunction generateProxyEntry(): Record<string, unknown> {\n return {\n command: \"npx\",\n args: [\"-y\", \"mcp-lazy\", \"serve\"],\n };\n}\n\nexport function registerProxy(\n agent: AgentInfo\n): { configPath: string; created: boolean; serverCount: number } {\n const existing = findAgentConfig(agent);\n const fallback = agent.configPaths[0];\n let targetPath = existing ?? resolvePath(fallback);\n\n let created = false;\n let serverCount = 0;\n\n if (agent.format === \"opencode\") {\n if (existsSync(targetPath)) {\n try {\n const fullConfig = JSON.parse(readFileSync(targetPath, \"utf-8\"));\n const mcpSection = fullConfig.mcp || {};\n\n const serversToBackup: Record<string, ServerConfig> = {};\n\n for (const [name, cfg] of Object.entries(mcpSection)) {\n if (name === \"mcp-lazy\") continue;\n const c = cfg as any;\n if (c.type === \"remote\" && c.url) {\n // Convert URL to mcp-remote\n serversToBackup[name] = convertUrlToMcpRemote(c.url, c.headers);\n } else if (c.type === \"local\" && Array.isArray(c.command) && c.command.length > 0) {\n // Stdio: normalize from opencode format\n serversToBackup[name] = {\n command: c.command[0],\n args: c.command.slice(1),\n ...(c.environment && { env: c.environment }),\n };\n }\n }\n\n serverCount = Object.keys(serversToBackup).length;\n if (serverCount > 0) {\n saveServersBackup(serversToBackup);\n }\n\n // Write: only mcp-lazy (preserve non-mcp keys)\n fullConfig.mcp = {\n \"mcp-lazy\": {\n type: \"local\",\n command: [\"npx\", \"-y\", \"mcp-lazy\", \"serve\"],\n },\n };\n writeFileSync(targetPath, JSON.stringify(fullConfig, null, 2) + \"\\n\");\n } catch {\n // If can't parse, write fresh\n const config = { mcp: { \"mcp-lazy\": { type: \"local\", command: [\"npx\", \"-y\", \"mcp-lazy\", \"serve\"] } } };\n writeFileSync(targetPath, JSON.stringify(config, null, 2) + \"\\n\");\n }\n } else {\n created = true;\n const dir = dirname(targetPath);\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n const config = { mcp: { \"mcp-lazy\": { type: \"local\", command: [\"npx\", \"-y\", \"mcp-lazy\", \"serve\"] } } };\n writeFileSync(targetPath, JSON.stringify(config, null, 2) + \"\\n\");\n }\n return { configPath: targetPath, created, serverCount };\n }\n\n if (agent.format === \"toml\") {\n if (!existsSync(targetPath)) {\n created = true;\n const dir = dirname(targetPath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n }\n\n const existingContent = existsSync(targetPath)\n ? readFileSync(targetPath, \"utf-8\")\n : \"\";\n\n // Extract all servers\n const allServers = extractServersFromToml(existingContent);\n const serversToBackup: Record<string, ServerConfig> = {};\n\n for (const [name, cfg] of Object.entries(allServers)) {\n if (cfg.command) {\n serversToBackup[name] = cfg;\n } else if (cfg.url) {\n // Convert URL to mcp-remote\n serversToBackup[name] = convertUrlToMcpRemote(cfg.url, cfg.headers);\n }\n }\n\n serverCount = Object.keys(serversToBackup).length;\n if (serverCount > 0) {\n saveServersBackup(serversToBackup);\n }\n\n // Strip ALL mcp_servers sections (including URL ones)\n let cleaned = existingContent.replace(\n /\\n?\\[mcp_servers\\.[^\\]]+\\](?:\\n(?!\\[)[^\\n]*)*/g,\n \"\"\n ).trimEnd();\n\n const tomlBlock =\n `\\n\\n[mcp_servers.mcp-lazy]\\n` +\n `command = \"npx\"\\n` +\n `args = [\"-y\", \"mcp-lazy\", \"serve\"]\\n`;\n\n writeFileSync(targetPath, cleaned + tomlBlock);\n\n return { configPath: targetPath, created, serverCount };\n }\n\n // JSON agents: extract ALL servers → convert URL to mcp-remote → backup ALL → write only mcp-lazy\n if (existsSync(targetPath)) {\n // Read raw config to get original field names\n let rawConfig: any = {};\n try {\n rawConfig = JSON.parse(readFileSync(targetPath, \"utf-8\"));\n } catch {}\n const rawServers = rawConfig.mcpServers ?? {};\n\n const serversToBackup: Record<string, ServerConfig> = {};\n\n // Extract normalized servers via Zod\n const normalizedServers = extractServersFromConfig(targetPath);\n\n for (const [name, serverCfg] of Object.entries(rawServers)) {\n if (name === \"mcp-lazy\") continue;\n const cfg = serverCfg as any;\n\n if (cfg.url || cfg.serverUrl) {\n // URL server → convert to mcp-remote stdio command\n const url = cfg.url || cfg.serverUrl;\n const headers = cfg.headers;\n serversToBackup[name] = convertUrlToMcpRemote(url, headers);\n } else if (cfg.command && normalizedServers[name]) {\n // Stdio server → use normalized version\n serversToBackup[name] = normalizedServers[name];\n }\n }\n\n serverCount = Object.keys(serversToBackup).length;\n if (serverCount > 0) {\n saveServersBackup(serversToBackup);\n }\n\n // Write config with ONLY mcp-lazy (no URL servers kept)\n const config = {\n mcpServers: {\n \"mcp-lazy\": generateProxyEntry(),\n },\n };\n\n writeFileSync(targetPath, JSON.stringify(config, null, 2) + \"\\n\");\n } else {\n created = true;\n const dir = dirname(targetPath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n const config = {\n mcpServers: {\n \"mcp-lazy\": generateProxyEntry(),\n },\n };\n\n writeFileSync(targetPath, JSON.stringify(config, null, 2) + \"\\n\");\n }\n\n return { configPath: targetPath, created, serverCount };\n}\n\nexport function isProxyRegistered(agent: AgentInfo): boolean {\n const configPath = findAgentConfig(agent);\n if (!configPath) return false;\n\n if (agent.format === \"opencode\") {\n try {\n const config = JSON.parse(readFileSync(configPath, \"utf-8\"));\n return !!(config.mcp && config.mcp[\"mcp-lazy\"]);\n } catch {\n return false;\n }\n }\n\n if (agent.format === \"toml\") {\n try {\n const content = readFileSync(configPath, \"utf-8\");\n return content.includes(\"[mcp_servers.mcp-lazy]\");\n } catch {\n return false;\n }\n }\n\n try {\n const config = JSON.parse(readFileSync(configPath, \"utf-8\"));\n return !!(config.mcpServers && config.mcpServers[\"mcp-lazy\"]);\n } catch {\n return false;\n }\n}\n","import {\n AGENTS,\n getAgentByName,\n registerProxy,\n type AgentInfo,\n} from \"../agents/index.js\";\n\nconst BANNER = `\n\\x1b[36m\\x1b[1m ███╗ ███╗ ██████╗██████╗ ██╗ █████╗ ███████╗██╗ ██╗\n ████╗ ████║██╔════╝██╔══██╗ ██║ ██╔══██╗╚══███╔╝╚██╗ ██╔╝\n ██╔████╔██║██║ ██████╔╝█████╗██║ ███████║ ███╔╝ ╚████╔╝\n ██║╚██╔╝██║██║ ██╔═══╝ ╚════╝██║ ██╔══██║ ███╔╝ ╚██╔╝\n ██║ ╚═╝ ██║╚██████╗██║ ███████╗██║ ██║███████╗ ██║\n ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚══════╝╚═╝ ╚═╝╚══════╝ ╚═╝\\x1b[0m\n`;\n\ninterface AddOptions {\n cursor?: boolean;\n opencode?: boolean;\n antigravity?: boolean;\n codex?: boolean;\n all?: boolean;\n}\n\nexport async function runAdd(options: AddOptions): Promise<void> {\n console.log(BANNER);\n\n // Determine which agents to register\n let targets: AgentInfo[] = [];\n\n if (options.all) {\n targets = [...AGENTS];\n } else {\n const flagMap: Record<string, boolean | undefined> = {\n cursor: options.cursor,\n opencode: options.opencode,\n antigravity: options.antigravity,\n codex: options.codex,\n };\n\n for (const [name, enabled] of Object.entries(flagMap)) {\n if (enabled) {\n const agent = getAgentByName(name);\n if (agent) {\n targets.push(agent);\n }\n }\n }\n }\n\n if (targets.length === 0) {\n console.log(\" No agent specified. Use one of:\");\n console.log(\" mcp-lazy add --cursor\");\n console.log(\" mcp-lazy add --opencode\");\n console.log(\" mcp-lazy add --antigravity\");\n console.log(\" mcp-lazy add --codex\");\n console.log(\" mcp-lazy add --all\\n\");\n process.exit(1);\n }\n\n console.log(\" Registering mcp-lazy proxy...\\n\");\n\n for (const agent of targets) {\n try {\n const { configPath, created, serverCount } = registerProxy(agent);\n const action = created ? \"created\" : \"updated\";\n const servers = serverCount > 0 ? ` (${serverCount} servers captured)` : \"\";\n console.log(` ✓ ${agent.displayName}: ${action} ${configPath}${servers}`);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n console.log(` ✗ ${agent.displayName}: failed - ${message}`);\n }\n }\n\n console.log(\"\\n Done! Restart your agents to activate mcp-lazy.\\n\");\n}\n","import { loadServersBackup } from \"../utils/config.js\";\nimport { AGENTS, isProxyRegistered } from \"../agents/index.js\";\n\nconst TOKENS_PER_TOOL = 650;\nconst PROXY_BASE_TOKENS = 350;\n\nexport async function runDoctor(): Promise<void> {\n let hasIssues = false;\n\n console.log(\"\\nmcp-lazy status check\\n\");\n\n // 1. Check Node.js version\n const nodeVersion = process.versions.node;\n const major = parseInt(nodeVersion.split(\".\")[0], 10);\n if (major >= 18) {\n console.log(` ✓ Node.js ${nodeVersion}`);\n } else {\n console.log(` ✗ Node.js ${nodeVersion} (requires >= 18)`);\n hasIssues = true;\n }\n\n // 2. Check servers backup\n const servers = loadServersBackup();\n const serverCount = Object.keys(servers).length;\n\n if (serverCount > 0) {\n const serverNames = Object.keys(servers);\n console.log(` ✓ ${serverCount} MCP server(s) registered`);\n for (const name of serverNames) {\n console.log(` - ${name}`);\n }\n } else {\n console.log(` ✗ No MCP servers registered -> run 'mcp-lazy add --<agent>'`);\n hasIssues = true;\n }\n\n // 3. Check agent registrations\n console.log(\"\");\n let registeredCount = 0;\n for (const agent of AGENTS) {\n const registered = isProxyRegistered(agent);\n if (registered) {\n console.log(` ✓ ${agent.displayName} registered`);\n registeredCount++;\n } else {\n console.log(` - ${agent.displayName} not registered -> mcp-lazy add --${agent.name}`);\n }\n }\n\n if (registeredCount === 0) {\n console.log(\"\\n No agents registered. Run 'mcp-lazy add --<agent>' to register.\");\n hasIssues = true;\n }\n\n // 4. Token savings estimation\n if (serverCount > 0) {\n const estimatedTools = serverCount * 15;\n const estimatedTokens = estimatedTools * TOKENS_PER_TOOL;\n const savings = estimatedTokens > 0\n ? Math.round(((estimatedTokens - PROXY_BASE_TOKENS) / estimatedTokens) * 100)\n : 0;\n\n console.log(`\\n Token savings estimate:`);\n console.log(` ${serverCount} server(s) registered`);\n console.log(` Without mcp-lazy: ~${estimatedTokens.toLocaleString()} tokens`);\n console.log(` With mcp-lazy: ${PROXY_BASE_TOKENS.toLocaleString()} tokens`);\n console.log(` Estimated savings: ${savings}%`);\n }\n\n console.log(\"\");\n if (!hasIssues) {\n console.log(\" All checks passed.\\n\");\n } else {\n console.log(\" Some issues found. See above for details.\\n\");\n }\n}\n"],"mappings":"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","names":["BANNER","Client","StdioClientTransport","z","existsSync","readFileSync","writeFileSync","mkdirSync","resolve","dirname","homedir","existsSync","readFileSync","writeFileSync","dirname","mkdirSync","runInit","loadServersBackup","computeServerFingerprint","loadToolCache","saveToolCache","ToolRegistry","ServerLoader","startProxyServer","discoverTools"]}
|
package/docs/README.ko.md
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
<pre>
|
|
2
|
+
███╗ ███╗ ██████╗██████╗ ██╗ █████╗ ███████╗██╗ ██╗
|
|
3
|
+
████╗ ████║██╔════╝██╔══██╗ ██║ ██╔══██╗╚══███╔╝╚██╗ ██╔╝
|
|
4
|
+
██╔████╔██║██║ ██████╔╝█████╗██║ ███████║ ███╔╝ ╚████╔╝
|
|
5
|
+
██║╚██╔╝██║██║ ██╔═══╝ ╚════╝██║ ██╔══██║ ███╔╝ ╚██╔╝
|
|
6
|
+
██║ ╚═╝ ██║╚██████╗██║ ███████╗██║ ██║███████╗ ██║
|
|
7
|
+
╚═╝ ╚═╝ ╚═════╝╚═╝ ╚══════╝╚═╝ ╚═╝╚══════╝ ╚═╝
|
|
8
|
+
</pre>
|
|
9
|
+
|
|
10
|
+
# mcp-lazy 🫠
|
|
2
11
|
|
|
3
12
|
[English](../README.md)
|
|
4
13
|
|
|
@@ -6,16 +15,37 @@
|
|
|
6
15
|
|
|
7
16
|
- MCP 서버들은 시작할 때 모든 툴 정의를 컨텍스트 윈도우에 로딩합니다 — 사용하기도 전에요. 서버가 5~10개면 컨텍스트 윈도우의 30~50%를 차지할 수 있습니다. **mcp-lazy**는 모든 MCP 서버를 하나의 경량 프록시로 묶어서, 필요할 때만 툴을 로딩합니다.
|
|
8
17
|
|
|
18
|
+
<center>
|
|
19
|
+
|
|
20
|
+
`시작 시 82개 툴이 로딩됨`
|
|
21
|
+

|
|
22
|
+
|
|
23
|
+
👇 `mcp-lazy 적용 후 단 2개`
|
|
24
|
+
|
|
25
|
+

|
|
26
|
+
|
|
27
|
+
</center>
|
|
28
|
+
|
|
9
29
|
## 빠른 시작
|
|
10
30
|
|
|
31
|
+
사용하는 에이전트에 맞게 하나를 선택하세요:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npx mcp-lazy add --cursor # Cursor
|
|
35
|
+
npx mcp-lazy add --codex # Codex
|
|
36
|
+
npx mcp-lazy add --antigravity # Antigravity
|
|
37
|
+
npx mcp-lazy add --opencode # Opencode
|
|
38
|
+
npx mcp-lazy add --all # 또는 한번에 전부 등록
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
그 다음 툴 캐시를 사전 구축합니다 (권장):
|
|
42
|
+
|
|
11
43
|
```bash
|
|
12
|
-
npx mcp-lazy
|
|
13
|
-
npx mcp-lazy add --codex
|
|
14
|
-
npx mcp-lazy add --antigravity
|
|
15
|
-
npx mcp-lazy add --all # 또는 한번에 전부 등록
|
|
44
|
+
npx mcp-lazy init
|
|
16
45
|
```
|
|
17
46
|
|
|
18
|
-
-
|
|
47
|
+
- `add` 명령어가 에이전트의 기존 MCP 설정을 읽어서 모든 서버 정의를 `~/.mcp-lazy/servers.json`에 저장하고, 에이전트 설정을 mcp-lazy 프록시 항목 하나로 교체합니다.
|
|
48
|
+
- `init`은 툴 캐시를 사전 구축하여 첫 에이전트 세션이 즉시 시작되도록 합니다. 실행하지 않으면 첫 세션에서 서버 접속에 시간이 소요됩니다.
|
|
19
49
|
|
|
20
50
|
> **Tip:** 새로운 MCP 서버를 설치했다면 `npx mcp-lazy add --<agent>`를 다시 실행하세요 — 추가 작업 없이 반영됩니다.
|
|
21
51
|
|
|
@@ -86,6 +116,27 @@ mcp-lazy 적용 후:
|
|
|
86
116
|
- `--cursor`, `--opencode`, `--antigravity`, `--codex` — 대상 에이전트
|
|
87
117
|
- `--all` — 모든 에이전트에 등록
|
|
88
118
|
|
|
119
|
+
### `npx mcp-lazy init`
|
|
120
|
+
|
|
121
|
+
등록된 모든 서버에 접속하여 툴 캐시를 사전 구축합니다:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
$ npx mcp-lazy init
|
|
125
|
+
|
|
126
|
+
mcp-lazy init — building tool cache...
|
|
127
|
+
|
|
128
|
+
✓ github-mcp 15 tools 342ms
|
|
129
|
+
✓ postgres-mcp 12 tools 518ms
|
|
130
|
+
✗ slack-mcp connection timeout
|
|
131
|
+
✓ filesystem 8 tools 120ms
|
|
132
|
+
|
|
133
|
+
Cache saved: 35 tools from 3/4 servers in 1.2s
|
|
134
|
+
Ready! mcp-lazy serve will start instantly.
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
- 모든 서버에 병렬로 접속하여 툴 인덱스를 `~/.mcp-lazy/tool-cache.json`에 저장합니다
|
|
138
|
+
- `add` 실행 후 이 명령어를 실행하면 첫 에이전트 세션이 즉시 시작됩니다
|
|
139
|
+
|
|
89
140
|
### `npx mcp-lazy doctor`
|
|
90
141
|
|
|
91
142
|
- 설치 상태를 진단합니다:
|
|
@@ -134,6 +185,13 @@ stdio: npx mcp-remote https://mcp.notion.com/sse
|
|
|
134
185
|
|
|
135
186
|
## FAQ
|
|
136
187
|
|
|
188
|
+
### Q: 최초 실행이 느립니다
|
|
189
|
+
|
|
190
|
+
- 첫 실행 시 mcp-lazy가 등록된 모든 MCP 서버에 접속하여 사용 가능한 툴을 수집하고 검색 인덱스를 구축합니다. 서버 수에 따라 10~30초 정도 소요될 수 있습니다.
|
|
191
|
+
- 이후에는 툴 인덱스가 `~/.mcp-lazy/tool-cache.json`에 캐시되어, 1초 이내로 시작됩니다.
|
|
192
|
+
- 서버 설정이 변경되면 캐시가 자동으로 갱신됩니다.
|
|
193
|
+
- `npx mcp-lazy init`을 설정 후 실행하면 캐시를 사전 구축하여 느린 첫 시작을 방지할 수 있습니다.
|
|
194
|
+
|
|
137
195
|
### Q: 설치 중 "Error: Unexpected error"가 발생합니다
|
|
138
196
|
|
|
139
197
|
- 설정 파일 디렉토리에 대한 읽기/쓰기 권한이 있는지 확인하세요. 예시:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mcp-lazy",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"description": "MCP lazy loading proxy for AI agents - reduce context window token usage by 90%+",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -38,14 +38,15 @@
|
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
40
40
|
"commander": "^13.1.0",
|
|
41
|
+
"mcp-lazy": "^0.1.6",
|
|
41
42
|
"zod": "^3.24.0"
|
|
42
43
|
},
|
|
43
44
|
"devDependencies": {
|
|
45
|
+
"@types/node": "^22.0.0",
|
|
44
46
|
"tsup": "^8.4.0",
|
|
45
47
|
"tsx": "^4.19.0",
|
|
46
48
|
"typescript": "^5.7.0",
|
|
47
|
-
"vitest": "^3.1.0"
|
|
48
|
-
"@types/node": "^22.0.0"
|
|
49
|
+
"vitest": "^3.1.0"
|
|
49
50
|
},
|
|
50
51
|
"engines": {
|
|
51
52
|
"node": ">=18.0.0"
|