openclaw-mcp-router 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/topics.txt +10 -0
- package/README.md +22 -2
- package/package.json +12 -4
- package/src/indexer.ts +5 -0
- package/src/test/indexer.test.ts +5 -0
package/README.md
CHANGED
|
@@ -1,16 +1,21 @@
|
|
|
1
1
|
# OpenClaw MCP Router 🚀
|
|
2
2
|
|
|
3
|
-
OpenClaw MCP Router is
|
|
3
|
+
**OpenClaw MCP Router** is a dynamic **MCP (Model Context Protocol) tool router** for OpenClaw. It uses semantic search to discover the right MCP tools at runtime, so agents avoid loading huge tool catalogs into the system prompt.
|
|
4
|
+
|
|
4
5
|
|
|
5
6
|
Instead of injecting every MCP schema up front, it provides two lightweight meta-tools:
|
|
6
7
|
|
|
7
8
|
- `mcp_search` → discover the right tool at runtime
|
|
8
9
|
- `mcp_call` → execute as JSON fallback
|
|
9
10
|
|
|
10
|
-
This cuts context bloat
|
|
11
|
+
This cuts context bloat, improves tool selection quality, and reduces token cost on large MCP server inventories.
|
|
11
12
|
|
|
12
13
|
---
|
|
13
14
|
|
|
15
|
+
## Keywords
|
|
16
|
+
|
|
17
|
+
OpenClaw plugin, MCP router, Model Context Protocol, tool discovery, semantic tool search, AI agent tooling, LanceDB, Ollama embeddings.
|
|
18
|
+
|
|
14
19
|
## Why this exists
|
|
15
20
|
|
|
16
21
|
Large MCP catalogs are expensive in prompt space.
|
|
@@ -60,6 +65,13 @@ Router is now optimized for a CLI-first workflow:
|
|
|
60
65
|
|
|
61
66
|
---
|
|
62
67
|
|
|
68
|
+
## Use cases
|
|
69
|
+
|
|
70
|
+
- Route large MCP tool catalogs without prompt bloat
|
|
71
|
+
- Improve tool selection for coding and automation agents
|
|
72
|
+
- Keep system prompts small while preserving broad MCP capability
|
|
73
|
+
- Enable CLI-first MCP execution with JSON fallback
|
|
74
|
+
|
|
63
75
|
## Quick start
|
|
64
76
|
|
|
65
77
|
### Prerequisites
|
|
@@ -158,3 +170,11 @@ PR hygiene:
|
|
|
158
170
|
## License
|
|
159
171
|
|
|
160
172
|
MIT
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
## GitHub SEO checklist
|
|
176
|
+
|
|
177
|
+
- Set repo description to include: `OpenClaw`, `MCP`, `Model Context Protocol`, `semantic search`
|
|
178
|
+
- Add GitHub topics (see `.github/topics.txt`)
|
|
179
|
+
- Pin this repository on your profile if it's a flagship plugin
|
|
180
|
+
- Link this repo from related blog posts, docs, and demos
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openclaw-mcp-router",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"private": false,
|
|
5
|
-
"description": "
|
|
5
|
+
"description": "OpenClaw MCP router plugin for Model Context Protocol (MCP): semantic tool search and dynamic tool calling to reduce prompt bloat",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"repository": {
|
|
@@ -11,9 +11,13 @@
|
|
|
11
11
|
},
|
|
12
12
|
"keywords": [
|
|
13
13
|
"openclaw",
|
|
14
|
+
"openclaw-plugin",
|
|
14
15
|
"mcp",
|
|
15
|
-
"
|
|
16
|
-
"
|
|
16
|
+
"model-context-protocol",
|
|
17
|
+
"mcp-router",
|
|
18
|
+
"tool-discovery",
|
|
19
|
+
"semantic-search",
|
|
20
|
+
"ai-agents",
|
|
17
21
|
"lancedb",
|
|
18
22
|
"ollama"
|
|
19
23
|
],
|
|
@@ -44,5 +48,9 @@
|
|
|
44
48
|
"skills": [
|
|
45
49
|
"./skills"
|
|
46
50
|
]
|
|
51
|
+
},
|
|
52
|
+
"homepage": "https://github.com/lunarmoon26/openclaw-mcp-router#readme",
|
|
53
|
+
"bugs": {
|
|
54
|
+
"url": "https://github.com/lunarmoon26/openclaw-mcp-router/issues"
|
|
47
55
|
}
|
|
48
56
|
}
|
package/src/indexer.ts
CHANGED
|
@@ -177,6 +177,11 @@ async function indexServer(params: {
|
|
|
177
177
|
await client.connect({ signal, timeout: connectTimeout });
|
|
178
178
|
const tools = await client.listTools();
|
|
179
179
|
|
|
180
|
+
// Clear all existing rows for this server before re-adding the fresh tool list.
|
|
181
|
+
// This prevents stale entries when tools are removed, renamed, or change between
|
|
182
|
+
// single-chunk and multi-chunk representations across reindexes.
|
|
183
|
+
await store.deleteServer(serverCfg.name);
|
|
184
|
+
|
|
180
185
|
// Optional: best-effort generation of per-server CLI wrapper via mcporter.
|
|
181
186
|
// Indexing continues even if generation fails.
|
|
182
187
|
if (cfg.indexer.generateCliArtifacts) {
|
package/src/test/indexer.test.ts
CHANGED
|
@@ -71,6 +71,7 @@ describe("runIndexer", () => {
|
|
|
71
71
|
|
|
72
72
|
expect(result.indexed).toBe(2);
|
|
73
73
|
expect(result.failed).toBe(0);
|
|
74
|
+
expect(store.deleteServer).toHaveBeenCalledWith("fs");
|
|
74
75
|
expect(store.upsertTool).toHaveBeenCalledTimes(2);
|
|
75
76
|
expect(registry.registerToolOwner).toHaveBeenCalledWith("read_file", "fs");
|
|
76
77
|
expect(registry.registerToolOwner).toHaveBeenCalledWith("list_dir", "fs");
|
|
@@ -155,6 +156,8 @@ describe("runIndexer", () => {
|
|
|
155
156
|
|
|
156
157
|
// 1 tool per server × 2 servers
|
|
157
158
|
expect(result.indexed).toBe(2);
|
|
159
|
+
expect(store.deleteServer).toHaveBeenCalledWith("server1");
|
|
160
|
+
expect(store.deleteServer).toHaveBeenCalledWith("server2");
|
|
158
161
|
});
|
|
159
162
|
|
|
160
163
|
// ── Retry behavior ──
|
|
@@ -396,6 +399,7 @@ describe("runIndexer", () => {
|
|
|
396
399
|
});
|
|
397
400
|
|
|
398
401
|
expect(result.indexed).toBe(1); // counts tools, not chunks
|
|
402
|
+
expect(store.deleteServer).toHaveBeenCalledWith("fs");
|
|
399
403
|
expect(store.upsertTool).not.toHaveBeenCalled();
|
|
400
404
|
expect(store.deleteToolChunks).toHaveBeenCalledWith("fs", "big_tool");
|
|
401
405
|
expect(store.addToolEntries).toHaveBeenCalledTimes(1);
|
|
@@ -446,6 +450,7 @@ describe("runIndexer", () => {
|
|
|
446
450
|
});
|
|
447
451
|
|
|
448
452
|
expect(result.indexed).toBe(1);
|
|
453
|
+
expect(store.deleteServer).toHaveBeenCalledWith("fs");
|
|
449
454
|
// Should use single upsertTool even for long description
|
|
450
455
|
expect(store.upsertTool).toHaveBeenCalledTimes(1);
|
|
451
456
|
expect(store.deleteToolChunks).not.toHaveBeenCalled();
|