mcp-tool-search 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Kaleb Teeter
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,215 @@
1
+ # MCP Tool Search
2
+
3
+ [![npm version](https://img.shields.io/npm/v/mcp-tool-search.svg)](https://www.npmjs.com/package/mcp-tool-search)
4
+ [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
5
+ [![Node.js 20+](https://img.shields.io/badge/node-%3E%3D20.0.0-brightgreen.svg)](https://nodejs.org/)
6
+ [![Tests](https://img.shields.io/badge/tests-36%2F36-brightgreen.svg)](src/__tests__)
7
+
8
+ **Reduce MCP tool-definition context overhead by ~85–96%.**
9
+
10
+ MCP Tool Search is a proxy server that replaces dozens of MCP tool schemas in your model's context window with just 4 lightweight tools. Instead of loading every tool definition upfront, the model searches for tools on-demand and calls them through the proxy.
11
+
12
+ ```
13
+ Before: 50 tool schemas loaded → ~10,000 context tokens consumed every turn
14
+ After: 4 proxy tools loaded → ~600 context tokens (constant)
15
+ ```
16
+
17
+ ## Problem
18
+
19
+ Every MCP server you add dumps its full tool schemas into the model's context window. With 5+ servers and 40+ tools, that's **8,000–20,000+ tokens** of schema definitions the model must process on every single turn — even when it doesn't use any of them.
20
+
21
+ ## Solution
22
+
23
+ MCP Tool Search sits between your MCP client and your backend servers:
24
+
25
+ 1. **Catalog Builder** pre-scans all your MCP servers and snapshots their tool definitions to a local JSON file
26
+ 2. **Proxy Server** exposes only 4 tools — the model searches, inspects, and calls tools through the proxy
27
+ 3. **Lazy Connections** — backend servers are spawned on first use and kept alive for 5 minutes
28
+
29
+ ```
30
+ MCP Client ←→ MCP Tool Search Proxy ←→ Backend MCP Servers
31
+ ↓ (lazily spawned)
32
+ catalog.json Context7, GitHub, etc.
33
+ (pre-built snapshot)
34
+ ```
35
+
36
+ ## The 4 Proxy Tools
37
+
38
+ | Tool | Purpose |
39
+ |------|---------|
40
+ | `search_tools` | Fuzzy-search across all backend tools by keyword or capability |
41
+ | `get_tool_schema` | Retrieve the full input schema for a specific tool |
42
+ | `call_tool` | Execute a tool on its backend server through the proxy |
43
+ | `list_servers` | List all cataloged servers and their connection status |
44
+
45
+ ## Quick Start
46
+
47
+ ```bash
48
+ npx mcp-tool-search --help
49
+ # Or: npm install -g mcp-tool-search && mcp-build-catalog && mcp-tool-search
50
+ ```
51
+
52
+ ## Installation
53
+
54
+ ### Option A: npm (recommended)
55
+
56
+ ```bash
57
+ npm install -g mcp-tool-search
58
+ ```
59
+
60
+ ### Option B: From source
61
+
62
+ ```bash
63
+ git clone https://github.com/kteeter0405/mcp-tool-search.git
64
+ cd mcp-tool-search
65
+ npm install
66
+ npm run build
67
+ ```
68
+
69
+ ## Setup
70
+
71
+ ### 1. Configure backend servers
72
+
73
+ MCP Tool Search reads your MCP client's server configuration to discover backend tools. It uses the same `.mcp.json` format as Claude Code.
74
+
75
+ ### 2. Build the tool catalog
76
+
77
+ ```bash
78
+ # If installed globally:
79
+ mcp-build-catalog
80
+
81
+ # If from source:
82
+ npm run catalog
83
+ ```
84
+
85
+ This connects to each configured MCP server, snapshots their tool definitions, and writes `catalog.json`. The proxy itself is automatically excluded from the catalog.
86
+
87
+ ### 3. Add the proxy to your MCP client
88
+
89
+ Add to your `.mcp.json` (or equivalent config):
90
+
91
+ ```json
92
+ {
93
+ "mcpServers": {
94
+ "mcp-tool-search": {
95
+ "command": "npx",
96
+ "args": ["-y", "mcp-tool-search"]
97
+ }
98
+ }
99
+ }
100
+ ```
101
+
102
+ Or if installed from source:
103
+
104
+ ```json
105
+ {
106
+ "mcpServers": {
107
+ "mcp-tool-search": {
108
+ "command": "node",
109
+ "args": ["/path/to/mcp-tool-search/dist/index.js"]
110
+ }
111
+ }
112
+ }
113
+ ```
114
+
115
+ ### 4. Disable direct backend servers
116
+
117
+ Remove or disable your other MCP server entries in `.mcp.json` — the proxy handles all tool calls to them now.
118
+
119
+ ## Environment Variables
120
+
121
+ | Variable | Default | Purpose |
122
+ |----------|---------|---------|
123
+ | `MCP_TOOL_SEARCH_CATALOG` | `./catalog.json` | Path to the catalog file |
124
+ | `MCP_TOOL_SEARCH_METRICS` | *(none)* | Path to write JSON metrics (for monitoring dashboards) |
125
+
126
+ ## Token Savings
127
+
128
+ The proxy's token footprint is **constant** — 4 tools regardless of how many backend servers exist.
129
+
130
+ | Backend Tools | Direct Tokens | Proxy Tokens | Savings |
131
+ |---|---|---|---|
132
+ | 10 | ~2,000 | ~600 | 70% |
133
+ | 25 | ~5,000 | ~600 | 88% |
134
+ | 50 | ~10,000 | ~600 | 94% |
135
+ | 100 | ~20,000 | ~600 | 97% |
136
+ | 200 | ~40,000 | ~600 | 99% |
137
+
138
+ See [BENCHMARKS.md](BENCHMARKS.md) for detailed methodology and measurements.
139
+
140
+ ## Security
141
+
142
+ MCP Tool Search uses an **allowlist-based environment filter** when spawning backend servers. Only explicitly safe environment variables (PATH, HOME, NODE_PATH, etc.) are forwarded to child processes. API keys, tokens, and secrets from your shell environment are **never** leaked to backend servers unless explicitly configured in the catalog's per-server `env` block.
143
+
144
+ Additional security measures:
145
+
146
+ - **Connection cap**: Max 20 concurrent server connections (oldest idle connection evicted when limit reached)
147
+ - **Connect timeout**: 15-second timeout on server spawn
148
+ - **Idle cleanup**: Connections auto-close after 5 minutes of inactivity
149
+ - **No shell execution**: Server commands passed as arrays to `child_process.spawn()`, never through shell interpretation
150
+ - **TypeScript strict mode**: Full type safety with no `any` casts in core logic
151
+ - **Minimal dependencies**: Only 2 runtime deps (`@modelcontextprotocol/sdk`, `zod`)
152
+
153
+ > **Note:** `catalog.json` stores per-server env vars from your MCP config (including API tokens that backend servers need to function). Treat this file as sensitive — it is excluded from git (`.gitignore`) and npm publishing (`.npmignore` + `"files"` allowlist) by default. Do not share or commit it.
154
+
155
+ ## Trade-offs
156
+
157
+ - **Latency**: Each tool call requires a search + schema lookup step (~2 extra LLM turns for first use of a tool)
158
+ - **Discovery**: The model must search for tools instead of seeing them all upfront — minor overhead for small catalogs
159
+ - **Connection startup**: Servers are lazily spawned, so first calls to a new server have connection overhead
160
+
161
+ ### When to use the proxy
162
+
163
+ - **Use it** when you have 5+ MCP servers or 20+ total tools
164
+ - **Skip it** when you have 1–2 servers with few tools
165
+
166
+ ## Compatibility
167
+
168
+ Tested with:
169
+
170
+ - [Claude Code](https://docs.anthropic.com/en/docs/claude-code) (primary target)
171
+ - [Claude Desktop](https://claude.ai/download)
172
+ - [Cursor](https://cursor.sh/)
173
+ - [Windsurf](https://codeium.com/windsurf)
174
+
175
+ Should work with any MCP client that supports the stdio transport.
176
+
177
+ ## Project Structure
178
+
179
+ ```
180
+ mcp-tool-search/
181
+ ├── src/
182
+ │ ├── types.ts # Shared type definitions
183
+ │ ├── catalog.ts # Catalog loader + fuzzy search engine
184
+ │ ├── pool.ts # Lazy server connection pool with timeouts
185
+ │ ├── index.ts # Main proxy MCP server
186
+ │ └── build-catalog.ts # Catalog builder CLI
187
+ ├── dist/ # Compiled JavaScript (after build)
188
+ ├── catalog.json # Generated tool catalog (git-ignored)
189
+ ├── package.json
190
+ ├── tsconfig.json
191
+ └── README.md
192
+ ```
193
+
194
+ ## Development
195
+
196
+ ```bash
197
+ # Install dependencies
198
+ npm install
199
+
200
+ # Build TypeScript
201
+ npm run build
202
+
203
+ # Run tests
204
+ npm test
205
+
206
+ # Watch mode
207
+ npm run dev
208
+
209
+ # Rebuild catalog
210
+ npm run catalog
211
+ ```
212
+
213
+ ## License
214
+
215
+ [MIT](LICENSE) — Copyright (c) 2026 Kaleb Teeter
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * MCP Tool Search — Catalog Builder
4
+ *
5
+ * Connects to each MCP server defined in Claude Code's settings,
6
+ * discovers all available tools, and saves them to catalog.json.
7
+ *
8
+ * Usage: npm run catalog
9
+ *
10
+ * The catalog is a snapshot — rebuild it when you add/remove MCP servers.
11
+ */
12
+ export {};
13
+ //# sourceMappingURL=build-catalog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-catalog.d.ts","sourceRoot":"","sources":["../src/build-catalog.ts"],"names":[],"mappings":";AACA;;;;;;;;;GASG"}
@@ -0,0 +1,183 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * MCP Tool Search — Catalog Builder
4
+ *
5
+ * Connects to each MCP server defined in Claude Code's settings,
6
+ * discovers all available tools, and saves them to catalog.json.
7
+ *
8
+ * Usage: npm run catalog
9
+ *
10
+ * The catalog is a snapshot — rebuild it when you add/remove MCP servers.
11
+ */
12
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
13
+ import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
14
+ import { readFile, writeFile } from "node:fs/promises";
15
+ import { resolve, dirname } from "node:path";
16
+ import { fileURLToPath } from "node:url";
17
+ import { existsSync } from "node:fs";
18
+ import { homedir } from "node:os";
19
+ import { resolveCommand, buildSafeEnv } from "./utils.js";
20
+ const __dirname = dirname(fileURLToPath(import.meta.url));
21
+ const OUTPUT_PATH = resolve(__dirname, "..", "catalog.json");
22
+ // Timeout for connecting to each server (ms)
23
+ const CONNECT_TIMEOUT = 15_000;
24
+ /** Find and load MCP server configs from Claude settings */
25
+ async function loadMcpConfigs() {
26
+ // Check multiple possible config locations
27
+ const candidates = [
28
+ // Claude Code project-level
29
+ resolve(process.cwd(), ".mcp.json"),
30
+ // Claude Code user-level
31
+ resolve(homedir(), ".claude", "settings.json"),
32
+ // Claude Desktop
33
+ resolve(homedir(), "AppData", "Roaming", "Claude", "claude_desktop_config.json"),
34
+ // macOS Claude Desktop
35
+ resolve(homedir(), "Library", "Application Support", "Claude", "claude_desktop_config.json"),
36
+ ];
37
+ const allConfigs = {};
38
+ for (const path of candidates) {
39
+ if (!existsSync(path))
40
+ continue;
41
+ try {
42
+ const raw = JSON.parse(await readFile(path, "utf-8"));
43
+ // .mcp.json format: { "mcpServers": { ... } }
44
+ // settings.json format: { "mcpServers": { ... } }
45
+ // claude_desktop_config.json format: { "mcpServers": { ... } }
46
+ const servers = raw.mcpServers || raw.MCP_SERVERS || {};
47
+ for (const [name, config] of Object.entries(servers)) {
48
+ // Fix 1: Skip disabled servers
49
+ if (config.disabled === true) {
50
+ process.stderr.write(` Skipped: ${name} (disabled)\n`);
51
+ continue;
52
+ }
53
+ if (!allConfigs[name]) {
54
+ allConfigs[name] = config;
55
+ process.stderr.write(` Found: ${name} (from ${path})\n`);
56
+ }
57
+ }
58
+ }
59
+ catch (err) {
60
+ process.stderr.write(` Warning: Could not parse ${path}: ${err}\n`);
61
+ }
62
+ }
63
+ return allConfigs;
64
+ }
65
+ /** Connect to a server and discover its tools */
66
+ async function discoverTools(name, config) {
67
+ const transport = new StdioClientTransport({
68
+ command: resolveCommand(config.command),
69
+ args: config.args || [],
70
+ env: buildSafeEnv(config.env),
71
+ });
72
+ const client = new Client({ name: "mcp-catalog-builder", version: "2.0.0" }, { capabilities: {} });
73
+ try {
74
+ // Connect with timeout
75
+ await Promise.race([
76
+ client.connect(transport),
77
+ new Promise((_, reject) => setTimeout(() => reject(new Error("Connection timeout")), CONNECT_TIMEOUT)),
78
+ ]);
79
+ // List all tools
80
+ const response = await client.listTools();
81
+ const tools = (response.tools || []).map((t) => ({
82
+ name: t.name,
83
+ description: t.description || "",
84
+ inputSchema: t.inputSchema || {},
85
+ }));
86
+ await client.close();
87
+ return {
88
+ command: config.command,
89
+ args: config.args || [],
90
+ env: config.env,
91
+ tools,
92
+ };
93
+ }
94
+ catch (err) {
95
+ process.stderr.write(` ✗ ${name}: ${err.message}\n`);
96
+ try {
97
+ await client.close();
98
+ }
99
+ catch {
100
+ // Ignore
101
+ }
102
+ return null;
103
+ }
104
+ }
105
+ async function main() {
106
+ process.stderr.write("╔══════════════════════════════════════╗\n");
107
+ process.stderr.write("║ MCP Tool Search — Catalog Builder ║\n");
108
+ process.stderr.write("╚══════════════════════════════════════╝\n\n");
109
+ // Step 1: Find MCP server configs
110
+ process.stderr.write("[1/3] Scanning for MCP server configurations...\n");
111
+ const configs = await loadMcpConfigs();
112
+ const serverNames = Object.keys(configs);
113
+ if (serverNames.length === 0) {
114
+ process.stderr.write("\nNo MCP servers found. Make sure you have:\n" +
115
+ " - .mcp.json in your project root, OR\n" +
116
+ " - ~/.claude/settings.json with mcpServers, OR\n" +
117
+ " - Claude Desktop config with mcpServers\n");
118
+ process.exit(1);
119
+ }
120
+ // Fix 3: Parse --only and --skip CLI flags to filter servers
121
+ const onlyArg = process.argv.find((a) => a.startsWith("--only="));
122
+ const skipArg = process.argv.find((a) => a.startsWith("--skip="));
123
+ if (onlyArg && skipArg) {
124
+ process.stderr.write("\nError: Cannot use --only and --skip together. Pick one.\n");
125
+ process.exit(1);
126
+ }
127
+ // Self-skip: never try to spawn ourselves during catalog build
128
+ let filteredNames = serverNames.filter((n) => n !== "mcp-tool-search");
129
+ if (onlyArg) {
130
+ const onlySet = new Set(onlyArg.replace("--only=", "").split(",").map((s) => s.trim()));
131
+ filteredNames = filteredNames.filter((n) => onlySet.has(n));
132
+ process.stderr.write(` --only filter: ${filteredNames.length}/${serverNames.length} servers selected\n`);
133
+ }
134
+ if (skipArg) {
135
+ const skipSet = new Set(skipArg.replace("--skip=", "").split(",").map((s) => s.trim()));
136
+ filteredNames = filteredNames.filter((n) => !skipSet.has(n));
137
+ process.stderr.write(` --skip filter: ${filteredNames.length}/${serverNames.length} servers selected\n`);
138
+ }
139
+ process.stderr.write(`\nFound ${filteredNames.length} servers.\n\n`);
140
+ // Step 2: Connect and discover tools
141
+ process.stderr.write("[2/3] Discovering tools from each server...\n");
142
+ const catalog = {
143
+ version: "2.0.0",
144
+ generated: new Date().toISOString(),
145
+ servers: {},
146
+ };
147
+ let totalTools = 0;
148
+ let failedServers = 0;
149
+ // Parallel discovery — all servers spawn simultaneously
150
+ const discoveryResults = await Promise.allSettled(filteredNames.map(async (name) => {
151
+ process.stderr.write(` → ${name}...\n`);
152
+ const server = await discoverTools(name, configs[name]);
153
+ return { name, server };
154
+ }));
155
+ for (const result of discoveryResults) {
156
+ if (result.status === "fulfilled" && result.value.server) {
157
+ catalog.servers[result.value.name] = result.value.server;
158
+ totalTools += result.value.server.tools.length;
159
+ process.stderr.write(` ✓ ${result.value.name}: ${result.value.server.tools.length} tools\n`);
160
+ }
161
+ else if (result.status === "rejected") {
162
+ failedServers++;
163
+ process.stderr.write(` ✗ ${result.reason}\n`);
164
+ }
165
+ else if (result.status === "fulfilled" && !result.value.server) {
166
+ failedServers++;
167
+ }
168
+ }
169
+ // Step 3: Save catalog
170
+ process.stderr.write(`\n[3/3] Saving catalog to ${OUTPUT_PATH}...\n`);
171
+ await writeFile(OUTPUT_PATH, JSON.stringify(catalog, null, 2), "utf-8");
172
+ process.stderr.write("\n══════════════════════════════════════\n");
173
+ process.stderr.write(` Catalog built: ${Object.keys(catalog.servers).length} servers, ${totalTools} tools\n`);
174
+ if (failedServers > 0) {
175
+ process.stderr.write(` ⚠ ${failedServers} server(s) failed to connect\n`);
176
+ }
177
+ process.stderr.write("══════════════════════════════════════\n");
178
+ }
179
+ main().catch((err) => {
180
+ process.stderr.write(`Fatal: ${err}\n`);
181
+ process.exit(1);
182
+ });
183
+ //# sourceMappingURL=build-catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-catalog.js","sourceRoot":"","sources":["../src/build-catalog.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * MCP Tool Search — Catalog Manager
3
+ *
4
+ * Loads the tool catalog (catalog.json) and provides fuzzy search.
5
+ * The catalog is pre-built by build-catalog.ts which connects to
6
+ * each backend MCP server and snapshots its tool definitions.
7
+ */
8
+ import type { CatalogData, CatalogServer, SearchResult } from "./types.js";
9
+ export declare class Catalog {
10
+ private readonly path;
11
+ private data;
12
+ private searchIndex;
13
+ constructor(path: string);
14
+ /** Load catalog from disk */
15
+ load(): Promise<void>;
16
+ /** Load catalog from data directly (for testing without filesystem) */
17
+ loadFromData(data: CatalogData): void;
18
+ /** Validate catalog shape to prevent cryptic runtime crashes */
19
+ private validateCatalog;
20
+ /** Build search index from catalog data */
21
+ private buildIndex;
22
+ /** Tokenize a string for fuzzy matching — splits on spaces, underscores, and hyphens */
23
+ private tokenize;
24
+ /** Fuzzy search across all tools */
25
+ search(query: string, maxResults?: number): SearchResult[];
26
+ /** Get a specific server's config */
27
+ getServer(name: string): CatalogServer | undefined;
28
+ /** Get a specific tool's full schema */
29
+ getToolSchema(serverName: string, toolName: string): Record<string, unknown> | undefined;
30
+ /** Total number of servers in catalog */
31
+ get totalServers(): number;
32
+ /** Total number of tools across all servers */
33
+ get totalTools(): number;
34
+ /** List all server names */
35
+ get serverNames(): string[];
36
+ /** Get tool count per server */
37
+ serverToolCounts(): Record<string, number>;
38
+ }
39
+ //# sourceMappingURL=catalog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAsC3E,qBAAa,OAAO;IASN,OAAO,CAAC,QAAQ,CAAC,IAAI;IARjC,OAAO,CAAC,IAAI,CAA4B;IACxC,OAAO,CAAC,WAAW,CAKX;gBAEqB,IAAI,EAAE,MAAM;IAEzC,6BAA6B;IACvB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ3B,uEAAuE;IACvE,YAAY,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI;IAMrC,gEAAgE;IAChE,OAAO,CAAC,eAAe;IAwBvB,2CAA2C;IAC3C,OAAO,CAAC,UAAU;IAmBlB,wFAAwF;IACxF,OAAO,CAAC,QAAQ;IAQhB,oCAAoC;IACpC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,GAAE,MAAW,GAAG,YAAY,EAAE;IAkE9D,qCAAqC;IACrC,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAIlD,wCAAwC;IACxC,aAAa,CACX,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,GACf,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS;IAOtC,yCAAyC;IACzC,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED,+CAA+C;IAC/C,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED,4BAA4B;IAC5B,IAAI,WAAW,IAAI,MAAM,EAAE,CAE1B;IAED,gCAAgC;IAChC,gBAAgB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;CAQ3C"}