openclaw-mcp-router 0.2.1 → 1.0.1
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/workflows/release.yml +5 -17
- package/README.md +95 -90
- package/openclaw.plugin.json +18 -4
- package/package.json +10 -4
- package/skills/mcp-router/SKILL.md +84 -0
- package/skills/mcp-router/references/workflows.md +184 -0
- package/src/chunker.ts +117 -0
- package/src/commands/add-server.ts +90 -0
- package/src/commands/disable-server.ts +33 -0
- package/src/commands/enable-server.ts +37 -0
- package/src/commands/list-servers.ts +106 -0
- package/src/commands/remove-server.ts +33 -0
- package/src/config.ts +105 -35
- package/src/constants.ts +21 -0
- package/src/embeddings.ts +11 -9
- package/src/index.ts +173 -31
- package/src/indexer.ts +160 -54
- package/src/mcp-client.ts +18 -8
- package/src/mcp-registry.ts +2 -1
- package/src/setup/config-writer.ts +184 -0
- package/src/setup/control-command.ts +467 -0
- package/src/setup/setup-command.ts +199 -0
- package/src/test/chunker.test.ts +100 -0
- package/src/test/config.test.ts +165 -14
- package/src/test/embeddings.test.ts +17 -17
- package/src/test/indexer.test.ts +361 -3
- package/src/test/tools/mcp-call-tool.test.ts +8 -7
- package/src/test/tools/mcp-search-tool.test.ts +93 -11
- package/src/tools/mcp-call-tool.ts +7 -6
- package/src/tools/mcp-search-tool.ts +21 -5
- package/src/vector-store.ts +41 -10
- package/tsconfig.json +1 -2
- package/CLAUDE.md +0 -52
|
@@ -5,7 +5,7 @@ on:
|
|
|
5
5
|
types: [published]
|
|
6
6
|
|
|
7
7
|
permissions:
|
|
8
|
-
contents:
|
|
8
|
+
contents: read
|
|
9
9
|
id-token: write # npm provenance (links published package back to this repo+commit)
|
|
10
10
|
|
|
11
11
|
jobs:
|
|
@@ -13,14 +13,10 @@ jobs:
|
|
|
13
13
|
runs-on: ubuntu-latest
|
|
14
14
|
steps:
|
|
15
15
|
- uses: actions/checkout@v4
|
|
16
|
-
with:
|
|
17
|
-
# Use a PAT so the version-bump commit can trigger other workflows if needed.
|
|
18
|
-
# Falls back to GITHUB_TOKEN (works fine, but commits won't trigger further CI).
|
|
19
|
-
token: ${{ secrets.PAT_TOKEN || secrets.GITHUB_TOKEN }}
|
|
20
16
|
|
|
21
17
|
- uses: actions/setup-node@v4
|
|
22
18
|
with:
|
|
23
|
-
node-version:
|
|
19
|
+
node-version: 24
|
|
24
20
|
registry-url: https://registry.npmjs.org
|
|
25
21
|
|
|
26
22
|
- name: Extract version from release tag
|
|
@@ -39,19 +35,11 @@ jobs:
|
|
|
39
35
|
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
|
40
36
|
echo "Resolved version: $VERSION"
|
|
41
37
|
|
|
42
|
-
- name: Bump package.json version
|
|
43
|
-
run: npm version "${{ steps.version.outputs.version }}" --no-git-tag-version
|
|
44
|
-
|
|
45
|
-
- name: Commit version bump
|
|
46
|
-
run: |
|
|
47
|
-
git config user.name "github-actions[bot]"
|
|
48
|
-
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
49
|
-
git add package.json package-lock.json 2>/dev/null || true
|
|
50
|
-
git commit -m "chore: bump version to ${{ steps.version.outputs.version }}" || echo "No changes to commit"
|
|
51
|
-
git push origin HEAD:${{ github.event.release.target_commitish }}
|
|
52
|
-
|
|
53
38
|
- run: npm ci
|
|
54
39
|
|
|
40
|
+
- name: Set package version from tag (publish only, no commit)
|
|
41
|
+
run: npm version "${{ steps.version.outputs.version }}" --no-git-tag-version
|
|
42
|
+
|
|
55
43
|
- name: Publish to npm
|
|
56
44
|
run: npm publish --provenance --access public
|
|
57
45
|
env:
|
package/README.md
CHANGED
|
@@ -1,124 +1,129 @@
|
|
|
1
|
-
#
|
|
1
|
+
# OpenClaw MCP Router 🚀
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**OpenClaw MCP Router** is a dynamic tool discovery layer for [OpenClaw](https://openclaw.ai). It uses semantic vector search to eliminate **Context Bloat** by routing only the necessary Model Context Protocol (MCP) tool schemas to your agent on-demand.
|
|
4
4
|
|
|
5
|
-
## The
|
|
5
|
+
## ⚡ The Problem: Context Window Exhaustion
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Modern MCP catalogs are growing. Loading every tool schema upfront is expensive and inefficient:
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
* **Token Waste:** 5 MCP servers with 50+ tools can burn **55k–134k tokens** before your agent even says "Hello."
|
|
10
|
+
* **Performance Hit:** Massive system prompts degrade reasoning accuracy (the "lost in the middle" phenomenon).
|
|
11
|
+
* **Cost:** High token usage leads to higher API costs for every turn of the conversation.
|
|
10
12
|
|
|
11
|
-
|
|
13
|
+
## 🛠️ The Solution: Semantic Tool Routing
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
- **`mcp_call(tool_name, params_json)`** — look up the owning MCP server, execute the call, return the result
|
|
15
|
+
Instead of a full schema dump, this plugin registers two lightweight "Meta-Tools":
|
|
15
16
|
|
|
16
|
-
|
|
17
|
+
1. **`mcp_search(query)`**: Uses **Ollama** and **LanceDB** to perform a semantic search. It returns only the top-N most relevant tool definitions (reducing overhead by ~95%).
|
|
18
|
+
2. **`mcp_call(tool_name, params)`**: Dynamically resolves the owning MCP server and executes the call.
|
|
17
19
|
|
|
18
|
-
|
|
20
|
+
> **Result:** Your agent "asks" for the tools it needs, keeping the context window clean and the reasoning sharp.
|
|
19
21
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 🚀 Quick Start
|
|
25
|
+
|
|
26
|
+
### 1. Prerequisites
|
|
27
|
+
|
|
28
|
+
Ensure you have **Ollama** running locally with an embedding model:
|
|
23
29
|
|
|
24
|
-
|
|
30
|
+
```bash
|
|
31
|
+
ollama pull embeddinggemma
|
|
25
32
|
|
|
26
|
-
```sh
|
|
27
|
-
ollama pull nomic-embed-text
|
|
28
|
-
ollama serve
|
|
29
33
|
```
|
|
30
34
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
tools:
|
|
37
|
-
alsoAllow:
|
|
38
|
-
- mcp_search
|
|
39
|
-
- mcp_call
|
|
40
|
-
|
|
41
|
-
plugins:
|
|
42
|
-
mcp-router:
|
|
43
|
-
enabled: true
|
|
44
|
-
config:
|
|
45
|
-
servers:
|
|
46
|
-
- name: filesystem
|
|
47
|
-
transport: stdio
|
|
48
|
-
command: npx
|
|
49
|
-
args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
|
|
50
|
-
- name: github
|
|
51
|
-
transport: sse
|
|
52
|
-
url: https://api.githubcopilot.com/mcp/
|
|
53
|
-
embedding:
|
|
54
|
-
provider: ollama
|
|
55
|
-
model: nomic-embed-text # or mxbai-embed-large, all-minilm
|
|
56
|
-
url: http://localhost:11434
|
|
57
|
-
search:
|
|
58
|
-
topK: 5 # tools returned per search (1–20)
|
|
59
|
-
minScore: 0.3 # minimum similarity threshold (0–1)
|
|
35
|
+
### 2. Installation
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
openclaw plugins install openclaw-mcp-router
|
|
39
|
+
|
|
60
40
|
```
|
|
61
41
|
|
|
62
|
-
|
|
42
|
+
### 3. Setup & Indexing
|
|
63
43
|
|
|
64
|
-
|
|
44
|
+
Run the interactive wizard to configure your servers and automatically update your `alsoAllow` permissions:
|
|
65
45
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
| `transport` | yes | `stdio`, `sse`, or `http` |
|
|
70
|
-
| `command` | stdio only | Executable to run |
|
|
71
|
-
| `args` | stdio only | Arguments array |
|
|
72
|
-
| `env` | no | Extra env vars merged over process.env; supports `${VAR}` expansion |
|
|
73
|
-
| `url` | sse/http only | Server endpoint URL |
|
|
46
|
+
```bash
|
|
47
|
+
openclaw openclaw-mcp-router setup
|
|
48
|
+
openclaw openclaw-mcp-router reindex
|
|
74
49
|
|
|
75
|
-
|
|
50
|
+
```
|
|
76
51
|
|
|
77
|
-
|
|
78
|
-
|-------|---------|-------------|
|
|
79
|
-
| `provider` | `ollama` | Only Ollama is supported |
|
|
80
|
-
| `model` | `nomic-embed-text` | Embedding model name |
|
|
81
|
-
| `url` | `http://localhost:11434` | Ollama base URL (must be localhost) |
|
|
52
|
+
---
|
|
82
53
|
|
|
83
|
-
|
|
54
|
+
## ⚙️ Configuration
|
|
84
55
|
|
|
85
|
-
|
|
86
|
-
|-------|---------|-------------|
|
|
87
|
-
| `path` | `~/.openclaw/mcp-router/lancedb` | LanceDB database directory |
|
|
56
|
+
The plugin is highly configurable via `~/.openclaw/openclaw.json`.
|
|
88
57
|
|
|
89
|
-
###
|
|
58
|
+
### Server Management
|
|
90
59
|
|
|
91
|
-
|
|
92
|
-
|-------|---------|-------------|
|
|
93
|
-
| `topK` | `5` | Max tools returned per search |
|
|
94
|
-
| `minScore` | `0.3` | Minimum similarity score (0–1) |
|
|
60
|
+
You can manage servers via the **Interactive TUI**:
|
|
95
61
|
|
|
96
|
-
|
|
62
|
+
```bash
|
|
63
|
+
openclaw openclaw-mcp-router control
|
|
97
64
|
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Manual Schema Example
|
|
68
|
+
|
|
69
|
+
For power users, add servers directly to your `plugins.entries`:
|
|
70
|
+
|
|
71
|
+
| Key | Description | Default |
|
|
72
|
+
| --- | --- | --- |
|
|
73
|
+
| `topK` | Number of tools returned per search | `5` |
|
|
74
|
+
| `minScore` | Similarity threshold (0.0 - 1.0) | `0.3` |
|
|
75
|
+
| `maxRetries` | Connection attempts for slow servers | `3` |
|
|
76
|
+
|
|
77
|
+
```json5
|
|
78
|
+
// ~/.openclaw/openclaw.json
|
|
79
|
+
{
|
|
80
|
+
"plugins": {
|
|
81
|
+
"entries": {
|
|
82
|
+
"openclaw-mcp-router": {
|
|
83
|
+
"enabled": true,
|
|
84
|
+
"config": {
|
|
85
|
+
"servers": [{ "name": "filesystem", "transport": "stdio", "command": "npx", "args": ["..."] }],
|
|
86
|
+
"embedding": { "provider": "ollama", "model": "embeddinggemma" }
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
101
92
|
|
|
102
|
-
# Show indexed tool count
|
|
103
|
-
openclaw mcp-router stats
|
|
104
93
|
```
|
|
105
94
|
|
|
106
|
-
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## 🧠 How It Works: Under the Hood
|
|
98
|
+
|
|
99
|
+
1. **Indexing:** During `reindex`, the router connects to all configured MCP servers, fetches their manifests, and generates vector embeddings for every tool description.
|
|
100
|
+
2. **Storage:** These embeddings are stored in a local **LanceDB** instance for sub-millisecond retrieval.
|
|
101
|
+
3. **Runtime Discovery:** * Agent detects a task (e.g., "Analyze this CSV").
|
|
102
|
+
* Agent calls `mcp_search("read or analyze csv files")`.
|
|
103
|
+
* Router returns the `filesystem` tool schema.
|
|
104
|
+
* Agent executes the tool via `mcp_call`.
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## 📈 Performance & Benchmarks
|
|
111
|
+
|
|
112
|
+
Based on the [Anthropic Tool Search](https://www.anthropic.com/engineering/advanced-tool-use) pattern, dynamic routing can improve tool selection accuracy significantly:
|
|
113
|
+
|
|
114
|
+
* **Standard Loading:** ~49% Accuracy (Large catalogs)
|
|
115
|
+
* **Dynamic Routing:** **~88% Accuracy** (Opus 4.5 benchmarks)
|
|
107
116
|
|
|
108
|
-
|
|
109
|
-
2. When the agent needs to use an MCP capability, it calls `mcp_search("what I want to do")` to find relevant tools.
|
|
110
|
-
3. The agent then calls `mcp_call("tool_name", '{"param": "value"}')` to execute the chosen tool.
|
|
117
|
+
---
|
|
111
118
|
|
|
112
|
-
##
|
|
119
|
+
## 🤝 Contributing
|
|
113
120
|
|
|
114
|
-
|
|
115
|
-
|-------|------|-------|
|
|
116
|
-
| `nomic-embed-text` | 768 | Good balance, recommended default |
|
|
117
|
-
| `mxbai-embed-large` | 1024 | Higher quality, larger footprint |
|
|
118
|
-
| `all-minilm` | 384 | Fast and lightweight |
|
|
121
|
+
We are looking to implement **Hybrid Search (BM25)** and **LLM-based Reranking**. If you're interested in improving LLM orchestration efficiency, we'd love your help!
|
|
119
122
|
|
|
120
|
-
|
|
123
|
+
1. Fork the repo.
|
|
124
|
+
2. Create your feature branch.
|
|
125
|
+
3. Submit a PR.
|
|
121
126
|
|
|
122
|
-
## License
|
|
127
|
+
## 📄 License
|
|
123
128
|
|
|
124
|
-
MIT
|
|
129
|
+
Released under the [MIT License](https://www.google.com/search?q=LICENSE).
|
package/openclaw.plugin.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"id": "mcp-router",
|
|
2
|
+
"id": "openclaw-mcp-router",
|
|
3
3
|
"name": "MCP Router",
|
|
4
4
|
"description": "Semantic search across MCP tool catalogs. Reduces context bloat from ~77k→8.7k tokens by dynamically surfacing only relevant tools.",
|
|
5
5
|
"configSchema": {
|
|
@@ -18,13 +18,14 @@
|
|
|
18
18
|
"url": { "type": "string" },
|
|
19
19
|
"serverUrl": { "type": "string" },
|
|
20
20
|
"type": { "type": "string", "enum": ["stdio", "sse", "http"] },
|
|
21
|
-
"headers": { "type": "object", "additionalProperties": { "type": "string" } }
|
|
21
|
+
"headers": { "type": "object", "additionalProperties": { "type": "string" } },
|
|
22
|
+
"timeout": { "type": "number", "description": "Per-server connect timeout in ms; overrides indexer.connectTimeout" }
|
|
22
23
|
}
|
|
23
24
|
}
|
|
24
25
|
},
|
|
25
26
|
"mcpServersFile": {
|
|
26
27
|
"type": "string",
|
|
27
|
-
"description": "Path to a .mcp.json file. Default: ~/.openclaw/.mcp.json"
|
|
28
|
+
"description": "Path to a .mcp.json file. Default: ~/.openclaw/openclaw-mcp-router/.mcp.json"
|
|
28
29
|
},
|
|
29
30
|
"servers": {
|
|
30
31
|
"type": "array",
|
|
@@ -39,10 +40,23 @@
|
|
|
39
40
|
"args": { "type": "array", "items": { "type": "string" } },
|
|
40
41
|
"env": { "type": "object", "additionalProperties": { "type": "string" } },
|
|
41
42
|
"url": { "type": "string" },
|
|
42
|
-
"headers": { "type": "object", "additionalProperties": { "type": "string" } }
|
|
43
|
+
"headers": { "type": "object", "additionalProperties": { "type": "string" } },
|
|
44
|
+
"timeout": { "type": "number", "description": "Per-server connect timeout in ms; overrides indexer.connectTimeout" }
|
|
43
45
|
}
|
|
44
46
|
}
|
|
45
47
|
},
|
|
48
|
+
"indexer": {
|
|
49
|
+
"type": "object",
|
|
50
|
+
"description": "Indexer retry and timeout settings",
|
|
51
|
+
"properties": {
|
|
52
|
+
"connectTimeout": { "type": "number", "description": "Per-server default connect timeout in ms (default: 60000)" },
|
|
53
|
+
"maxRetries": { "type": "number", "minimum": 0, "description": "Retry attempts per server, 0 = no retry (default: 3)" },
|
|
54
|
+
"initialRetryDelay": { "type": "number", "description": "Initial backoff delay in ms (default: 2000)" },
|
|
55
|
+
"maxRetryDelay": { "type": "number", "description": "Max backoff cap in ms (default: 30000)" },
|
|
56
|
+
"maxChunkChars": { "type": "number", "minimum": 0, "description": "Max chars per chunk for long tool descriptions. 0 = disable chunking (default: 500)" },
|
|
57
|
+
"overlapChars": { "type": "number", "minimum": 0, "description": "Overlap chars between adjacent chunks (default: 100)" }
|
|
58
|
+
}
|
|
59
|
+
},
|
|
46
60
|
"embedding": {
|
|
47
61
|
"type": "object",
|
|
48
62
|
"properties": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openclaw-mcp-router",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Dynamic MCP tool router for OpenClaw — semantic search over large MCP catalogs to eliminate context bloat",
|
|
6
6
|
"type": "module",
|
|
@@ -18,15 +18,18 @@
|
|
|
18
18
|
"ollama"
|
|
19
19
|
],
|
|
20
20
|
"dependencies": {
|
|
21
|
+
"@clack/prompts": "^1.0.1",
|
|
21
22
|
"@lancedb/lancedb": "^0.26.2",
|
|
22
23
|
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
23
|
-
"@sinclair/typebox": "^0.34.48"
|
|
24
|
+
"@sinclair/typebox": "^0.34.48",
|
|
25
|
+
"json5": "^2.2.3",
|
|
26
|
+
"open": "^11.0.0"
|
|
24
27
|
},
|
|
25
28
|
"peerDependencies": {
|
|
26
|
-
"openclaw": "^2026.2.
|
|
29
|
+
"openclaw": "^2026.2.23"
|
|
27
30
|
},
|
|
28
31
|
"devDependencies": {
|
|
29
|
-
"openclaw": "^2026.2.
|
|
32
|
+
"openclaw": "^2026.2.23",
|
|
30
33
|
"typescript": "^5.7.0",
|
|
31
34
|
"vitest": "^3.0.0"
|
|
32
35
|
},
|
|
@@ -37,6 +40,9 @@
|
|
|
37
40
|
"openclaw": {
|
|
38
41
|
"extensions": [
|
|
39
42
|
"./src/index.ts"
|
|
43
|
+
],
|
|
44
|
+
"skills": [
|
|
45
|
+
"./skills"
|
|
40
46
|
]
|
|
41
47
|
}
|
|
42
48
|
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mcp-router
|
|
3
|
+
description: Discover and route tasks to configured MCP tools using mcp_search + mcp_call. Use when a task needs external capabilities (APIs, SaaS, databases, web, files, messaging, infra) and the best tool is not already known in-session, especially before falling back to manual shell/curl/web workflows.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# MCP Router
|
|
7
|
+
|
|
8
|
+
Use MCP as the first integration layer for external capabilities.
|
|
9
|
+
|
|
10
|
+
## Core Rule
|
|
11
|
+
|
|
12
|
+
Before manual API calls, curl scripts, or ad-hoc web work, run:
|
|
13
|
+
|
|
14
|
+
- `mcp_search("<action-oriented intent>")`
|
|
15
|
+
|
|
16
|
+
If a relevant tool exists, use it with `mcp_call`.
|
|
17
|
+
|
|
18
|
+
## Fast Workflow
|
|
19
|
+
|
|
20
|
+
1. **Search capability**
|
|
21
|
+
- Use an action-oriented query: `"create github pull request"`, `"query postgres"`, `"send slack message"`.
|
|
22
|
+
2. **Select tool**
|
|
23
|
+
- Prefer best intent match + feasible required params.
|
|
24
|
+
3. **Read schema**
|
|
25
|
+
- Identify required fields, types, enums, nested structure.
|
|
26
|
+
4. **Call tool**
|
|
27
|
+
- `mcp_call("exact_tool_name", "{...valid JSON...}")`
|
|
28
|
+
5. **Recover on failure**
|
|
29
|
+
- Fix schema/type mismatch or re-search with rewritten query.
|
|
30
|
+
|
|
31
|
+
## Query Rewrite Ladder (Deterministic)
|
|
32
|
+
|
|
33
|
+
If search quality is poor, retry in this order:
|
|
34
|
+
|
|
35
|
+
1. **Action only**: `"read file"`
|
|
36
|
+
2. **Action + system**: `"read file from s3"`, `"github create issue"`
|
|
37
|
+
3. **Verb swap**: create/open, read/fetch/get, list/enumerate
|
|
38
|
+
4. **Scope adjust**: broaden then narrow
|
|
39
|
+
|
|
40
|
+
Stop once you have a high-confidence tool.
|
|
41
|
+
|
|
42
|
+
## Tool Selection Rules
|
|
43
|
+
|
|
44
|
+
When multiple tools match, rank by:
|
|
45
|
+
|
|
46
|
+
1. Intent fit (description matches requested outcome)
|
|
47
|
+
2. Required-input fit (you can provide required params now)
|
|
48
|
+
3. Simplicity (fewer fragile/optional parameters)
|
|
49
|
+
4. Score/order from search results (tie-breaker)
|
|
50
|
+
|
|
51
|
+
## `mcp_call` Parameter Checklist
|
|
52
|
+
|
|
53
|
+
`params_json` must be a **JSON string**.
|
|
54
|
+
|
|
55
|
+
- Include all required fields.
|
|
56
|
+
- Match exact types (`42` vs `"42"`, `true` vs `"true"`).
|
|
57
|
+
- Respect enums and nested object shapes.
|
|
58
|
+
- Do not add unsupported keys unless schema allows them.
|
|
59
|
+
|
|
60
|
+
Examples:
|
|
61
|
+
|
|
62
|
+
```text
|
|
63
|
+
✅ mcp_call("filesystem::read_file", '{"path":"/tmp/a.txt"}')
|
|
64
|
+
❌ mcp_call("filesystem::read_file", {"path":"/tmp/a.txt"})
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
```text
|
|
68
|
+
✅ mcp_call("db::query", '{"sql":"select * from t where id=$1","params":[123]}')
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Error Handling
|
|
72
|
+
|
|
73
|
+
- **Missing required / invalid type**: re-read schema and correct `params_json`.
|
|
74
|
+
- **Unknown tool name**: re-run `mcp_search` and use exact returned name.
|
|
75
|
+
- **Server-side error**: report clearly; retry only with changed inputs.
|
|
76
|
+
- **No relevant tools**: use native fallback tools/workflow.
|
|
77
|
+
|
|
78
|
+
## Practical Boundaries
|
|
79
|
+
|
|
80
|
+
- Reuse known tool names in the same task; avoid unnecessary re-search.
|
|
81
|
+
- Re-search when intent changes materially.
|
|
82
|
+
- Do not loop retries blindly; each retry must change query or params.
|
|
83
|
+
|
|
84
|
+
For full examples, see [references/workflows.md](references/workflows.md).
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# Complete Workflow Examples
|
|
2
|
+
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
## Example 0: Check MCP before web search
|
|
6
|
+
|
|
7
|
+
**Goal:** Research a topic — but before using a built-in web search, check if a configured MCP server already handles this.
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
mcp_search("search the web")
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
**Tool card returned:**
|
|
14
|
+
```
|
|
15
|
+
Tool: brave::web_search
|
|
16
|
+
Description: Search the web using the Brave Search API.
|
|
17
|
+
Input Schema:
|
|
18
|
+
- query (string, required): The search query
|
|
19
|
+
- count (number, optional): Number of results (default: 10)
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**Call:**
|
|
23
|
+
```
|
|
24
|
+
mcp_call("brave::web_search", '{"query": "MCP server authentication patterns", "count": 5}')
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
If no web-search tool appears, fall back to whichever search capability is natively available.
|
|
28
|
+
|
|
29
|
+
**The pattern applies everywhere:**
|
|
30
|
+
- Need to fetch a URL? → `mcp_search("fetch a webpage")` before using curl
|
|
31
|
+
- Need to query a DB? → `mcp_search("run a SQL query")` before writing a connection script
|
|
32
|
+
- Need to post to Slack? → `mcp_search("send a Slack message")` before building an API request
|
|
33
|
+
- Need to read a file? → `mcp_search("read a local file")` before opening a shell
|
|
34
|
+
|
|
35
|
+
The configured MCP catalog is the toolbox. Exhaust it before doing things the hard way.
|
|
36
|
+
|
|
37
|
+
These end-to-end examples show the full search → read tool card → call sequence with realistic inputs.
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Example 1: Read a local file
|
|
42
|
+
|
|
43
|
+
**Goal:** Read the contents of `/tmp/report.txt`.
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
mcp_search("read a local file")
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**Tool card returned:**
|
|
50
|
+
```
|
|
51
|
+
Tool: filesystem::read_file
|
|
52
|
+
Description: Read the complete contents of a file from the local filesystem.
|
|
53
|
+
Input Schema:
|
|
54
|
+
- path (string, required): Absolute path to the file
|
|
55
|
+
- encoding (string, optional): File encoding (default: "utf-8")
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Call:**
|
|
59
|
+
```
|
|
60
|
+
mcp_call("filesystem::read_file", '{"path": "/tmp/report.txt"}')
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Example 2: Create a GitHub pull request
|
|
66
|
+
|
|
67
|
+
**Goal:** Open a PR from branch `feature/add-auth` to `main`.
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
mcp_search("create a GitHub pull request")
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**Tool card returned:**
|
|
74
|
+
```
|
|
75
|
+
Tool: github::create_pull_request
|
|
76
|
+
Description: Creates a new pull request in a GitHub repository.
|
|
77
|
+
Input Schema:
|
|
78
|
+
- owner (string, required): Repository owner (user or org)
|
|
79
|
+
- repo (string, required): Repository name
|
|
80
|
+
- title (string, required): PR title
|
|
81
|
+
- head (string, required): Branch containing the changes
|
|
82
|
+
- base (string, required): Branch to merge into
|
|
83
|
+
- body (string, optional): PR description in Markdown
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**Call:**
|
|
87
|
+
```
|
|
88
|
+
mcp_call("github::create_pull_request", '{
|
|
89
|
+
"owner": "acme-corp",
|
|
90
|
+
"repo": "backend",
|
|
91
|
+
"title": "Add JWT authentication",
|
|
92
|
+
"head": "feature/add-auth",
|
|
93
|
+
"base": "main",
|
|
94
|
+
"body": "Implements JWT-based auth as described in issue #42."
|
|
95
|
+
}')
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## Example 3: Query a database
|
|
101
|
+
|
|
102
|
+
**Goal:** Count active users in a Postgres database.
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
mcp_search("execute a SQL query against a Postgres database")
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**Tool card returned:**
|
|
109
|
+
```
|
|
110
|
+
Tool: postgres::query
|
|
111
|
+
Description: Execute a read-only SQL query against the configured Postgres database.
|
|
112
|
+
Input Schema:
|
|
113
|
+
- sql (string, required): SQL statement to execute
|
|
114
|
+
- params (array, optional): Positional parameters for parameterized queries
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
**Call:**
|
|
118
|
+
```
|
|
119
|
+
mcp_call("postgres::query", '{"sql": "SELECT COUNT(*) FROM users WHERE active = true"}')
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## Example 4: Multi-step workflow (search once, call multiple times)
|
|
125
|
+
|
|
126
|
+
**Goal:** List files in a directory, then read one of them.
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
mcp_search("list files in a directory")
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
**Tool card returned:**
|
|
133
|
+
```
|
|
134
|
+
Tool: filesystem::list_directory
|
|
135
|
+
Description: List the files and subdirectories in a given directory.
|
|
136
|
+
Input Schema:
|
|
137
|
+
- path (string, required): Absolute path to the directory
|
|
138
|
+
- recursive (boolean, optional): Include subdirectories (default: false)
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**Call 1 — list:**
|
|
142
|
+
```
|
|
143
|
+
mcp_call("filesystem::list_directory", '{"path": "/tmp/project"}')
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
**Result:** `["README.md", "config.json", "src/"]`
|
|
147
|
+
|
|
148
|
+
**Call 2 — read (reuse known tool name `filesystem::read_file` from Example 1):**
|
|
149
|
+
```
|
|
150
|
+
mcp_call("filesystem::read_file", '{"path": "/tmp/project/config.json"}')
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
No second `mcp_search` needed — once a tool name is known, reuse it directly.
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Example 5: Handling a failed search
|
|
158
|
+
|
|
159
|
+
**Goal:** Get the current weather for a city, but the first query returns nothing.
|
|
160
|
+
|
|
161
|
+
```
|
|
162
|
+
mcp_search("weather")
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
**Result:** No matches.
|
|
166
|
+
|
|
167
|
+
**Rephrase with action verb + domain:**
|
|
168
|
+
```
|
|
169
|
+
mcp_search("get current weather conditions for a city")
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
**Tool card returned:**
|
|
173
|
+
```
|
|
174
|
+
Tool: weather-api::current
|
|
175
|
+
Description: Fetches current weather conditions for a given city or coordinates.
|
|
176
|
+
Input Schema:
|
|
177
|
+
- city (string, required): City name or "lat,lon" coordinates
|
|
178
|
+
- units (string, optional): "metric" or "imperial" (default: "metric")
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
**Call:**
|
|
182
|
+
```
|
|
183
|
+
mcp_call("weather-api::current", '{"city": "San Francisco", "units": "imperial"}')
|
|
184
|
+
```
|