@darkiceinteractive/mcp-conductor 1.0.0 → 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/README.md +263 -432
- package/dist/bridge/http-server.d.ts.map +1 -1
- package/dist/bridge/http-server.js +25 -5
- package/dist/bridge/http-server.js.map +1 -1
- package/dist/bridge/index.d.ts +4 -1
- package/dist/bridge/index.d.ts.map +1 -1
- package/dist/bridge/index.js +4 -1
- package/dist/bridge/index.js.map +1 -1
- package/dist/config/defaults.d.ts +48 -2
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +51 -3
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/index.d.ts +3 -1
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +3 -1
- package/dist/config/index.js.map +1 -1
- package/dist/config/loader.d.ts +3 -0
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/config/loader.js +29 -6
- package/dist/config/loader.js.map +1 -1
- package/dist/config/schema.d.ts +2 -0
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/hub/index.d.ts +3 -1
- package/dist/hub/index.d.ts.map +1 -1
- package/dist/hub/index.js +3 -1
- package/dist/hub/index.js.map +1 -1
- package/dist/hub/mcp-hub.d.ts +1 -0
- package/dist/hub/mcp-hub.d.ts.map +1 -1
- package/dist/hub/mcp-hub.js +47 -14
- package/dist/hub/mcp-hub.js.map +1 -1
- package/dist/index.d.ts +21 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +59 -7
- package/dist/index.js.map +1 -1
- package/dist/metrics/index.d.ts +3 -1
- package/dist/metrics/index.d.ts.map +1 -1
- package/dist/metrics/index.js +3 -1
- package/dist/metrics/index.js.map +1 -1
- package/dist/metrics/metrics-collector.d.ts.map +1 -1
- package/dist/metrics/metrics-collector.js +1 -1
- package/dist/metrics/metrics-collector.js.map +1 -1
- package/dist/modes/index.d.ts +3 -1
- package/dist/modes/index.d.ts.map +1 -1
- package/dist/modes/index.js +3 -1
- package/dist/modes/index.js.map +1 -1
- package/dist/runtime/executor.d.ts +24 -1
- package/dist/runtime/executor.d.ts.map +1 -1
- package/dist/runtime/executor.js +175 -13
- package/dist/runtime/executor.js.map +1 -1
- package/dist/runtime/index.d.ts +3 -1
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/index.js +3 -1
- package/dist/runtime/index.js.map +1 -1
- package/dist/server/index.d.ts +3 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +3 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/mcp-server.d.ts.map +1 -1
- package/dist/server/mcp-server.js +56 -1
- package/dist/server/mcp-server.js.map +1 -1
- package/dist/skills/index.d.ts +3 -1
- package/dist/skills/index.d.ts.map +1 -1
- package/dist/skills/index.js +3 -1
- package/dist/skills/index.js.map +1 -1
- package/dist/streaming/execution-stream.d.ts.map +1 -1
- package/dist/streaming/execution-stream.js +22 -5
- package/dist/streaming/execution-stream.js.map +1 -1
- package/dist/streaming/index.d.ts +3 -1
- package/dist/streaming/index.d.ts.map +1 -1
- package/dist/streaming/index.js +3 -1
- package/dist/streaming/index.js.map +1 -1
- package/dist/utils/env.d.ts +20 -0
- package/dist/utils/env.d.ts.map +1 -0
- package/dist/utils/env.js +33 -0
- package/dist/utils/env.js.map +1 -0
- package/dist/utils/errors.d.ts +17 -1
- package/dist/utils/errors.d.ts.map +1 -1
- package/dist/utils/errors.js +16 -1
- package/dist/utils/errors.js.map +1 -1
- package/dist/utils/index.d.ts +4 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +4 -1
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/logger.d.ts +8 -1
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +8 -1
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/rate-limiter.d.ts.map +1 -1
- package/dist/utils/rate-limiter.js +6 -0
- package/dist/utils/rate-limiter.js.map +1 -1
- package/dist/version.d.ts +4 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +4 -0
- package/dist/version.js.map +1 -0
- package/dist/watcher/index.d.ts +3 -1
- package/dist/watcher/index.d.ts.map +1 -1
- package/dist/watcher/index.js +3 -1
- package/dist/watcher/index.js.map +1 -1
- package/package.json +3 -4
- package/dist/bin/cli.d.ts +0 -8
- package/dist/bin/cli.d.ts.map +0 -1
- package/dist/bin/cli.js +0 -940
- package/dist/bin/cli.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,558 +1,389 @@
|
|
|
1
1
|
# MCP Conductor
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**97% fewer tokens. Parallel execution. One `npx` command.**
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
5
|
+
[](https://www.npmjs.com/package/@darkiceinteractive/mcp-conductor)
|
|
6
|
+
[](https://www.npmjs.com/package/@darkiceinteractive/mcp-conductor)
|
|
7
|
+
[](https://github.com/darkiceinteractive/mcp-conductor/actions/workflows/ci.yml)
|
|
8
|
+
[](https://opensource.org/licenses/MIT)
|
|
9
|
+
[](https://deno.land)
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
MCP Conductor is a single MCP server that orchestrates all your other MCP servers through a sandboxed Deno runtime. Instead of Claude making direct tool calls (and dumping every intermediate result into your context window), Claude writes TypeScript code that runs in an isolated sandbox. Only the final result comes back.
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
## Installation
|
|
17
|
-
|
|
18
|
-
### Quick Start (npm - Recommended)
|
|
19
|
-
|
|
20
|
-
Add to your Claude Desktop configuration:
|
|
21
|
-
|
|
22
|
-
**macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
23
|
-
**Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
|
|
24
|
-
|
|
25
|
-
```json
|
|
26
|
-
{
|
|
27
|
-
"mcpServers": {
|
|
28
|
-
"mcp-conductor": {
|
|
29
|
-
"command": "npx",
|
|
30
|
-
"args": ["-y", "@darkiceinteractive/mcp-conductor"]
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
13
|
+
```
|
|
14
|
+
Before: 45,000 tokens → Claude context window → 45,000 tokens billed
|
|
15
|
+
After: 45,000 tokens → Deno sandbox → 800 tokens → Claude context window
|
|
34
16
|
```
|
|
35
17
|
|
|
36
|
-
|
|
18
|
+
**Average measured reduction: 94.3%. Peak: 97.8%.**
|
|
37
19
|
|
|
38
|
-
|
|
20
|
+
---
|
|
39
21
|
|
|
40
|
-
|
|
22
|
+
## Quick Start
|
|
41
23
|
|
|
42
|
-
|
|
24
|
+
### 1. Install Deno
|
|
43
25
|
|
|
44
26
|
```bash
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
npm run setup
|
|
48
|
-
node dist/bin/cli.js enable-exclusive
|
|
49
|
-
```
|
|
27
|
+
# macOS
|
|
28
|
+
brew install deno
|
|
50
29
|
|
|
51
|
-
|
|
30
|
+
# Linux
|
|
31
|
+
curl -fsSL https://deno.land/install.sh | sh
|
|
52
32
|
|
|
53
|
-
|
|
33
|
+
# Windows
|
|
34
|
+
winget install DenoLand.Deno
|
|
35
|
+
```
|
|
54
36
|
|
|
55
|
-
|
|
37
|
+
### 2. Add to Your AI Tool
|
|
56
38
|
|
|
57
|
-
**
|
|
58
|
-
**Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
|
|
39
|
+
**Claude Code** (`~/.claude/settings.json`), **Claude Desktop**, **Gemini CLI** (`~/.gemini/settings.json`), **Kimi CLI** (`~/.kimi/mcp.json`), **Cursor** (`.cursor/mcp.json`), **Windsurf** (`~/.codeium/windsurf/mcp_config.json`), **Cline**, or **VS Code** (`.vscode/mcp.json`):
|
|
59
40
|
|
|
60
41
|
```json
|
|
61
42
|
{
|
|
62
43
|
"mcpServers": {
|
|
63
44
|
"mcp-conductor": {
|
|
64
|
-
"command": "
|
|
65
|
-
"args": ["/
|
|
45
|
+
"command": "npx",
|
|
46
|
+
"args": ["-y", "@darkiceinteractive/mcp-conductor"]
|
|
66
47
|
}
|
|
67
48
|
}
|
|
68
49
|
}
|
|
69
50
|
```
|
|
70
51
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
Or use the CLI to add it automatically:
|
|
52
|
+
**OpenAI Codex** (`~/.codex/config.toml`):
|
|
74
53
|
|
|
75
|
-
```
|
|
76
|
-
|
|
54
|
+
```toml
|
|
55
|
+
[mcp_servers.mcp-conductor]
|
|
56
|
+
command = "npx"
|
|
57
|
+
args = ["-y", "@darkiceinteractive/mcp-conductor"]
|
|
77
58
|
```
|
|
78
59
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
Restart Claude Desktop to load the new server. You should see "mcp-conductor" in the MCP servers list.
|
|
82
|
-
|
|
83
|
-
## Usage
|
|
84
|
-
|
|
85
|
-
In Claude, you can now use the `execute_code` tool:
|
|
86
|
-
|
|
87
|
-
```typescript
|
|
88
|
-
// List files and count by type
|
|
89
|
-
const fs = mcp.server('filesystem');
|
|
90
|
-
const files = await fs.call('list_directory', { path: '/project/src' });
|
|
91
|
-
const counts = { ts: 0, js: 0, other: 0 };
|
|
92
|
-
for (const f of files.entries) {
|
|
93
|
-
if (f.name.endsWith('.ts')) counts.ts++;
|
|
94
|
-
else if (f.name.endsWith('.js')) counts.js++;
|
|
95
|
-
else counts.other++;
|
|
96
|
-
}
|
|
97
|
-
return counts;
|
|
98
|
-
```
|
|
60
|
+
> **Note:** VS Code uses `"servers"` instead of `"mcpServers"` and requires `"type": "stdio"`. See the [full multi-platform guide](./docs/guide/mcp-clients.md) for exact config per platform.
|
|
99
61
|
|
|
100
|
-
|
|
62
|
+
### 3. Restart Your AI Tool
|
|
101
63
|
|
|
102
|
-
|
|
64
|
+
That's it. Ask your AI to list MCP servers — you should see `mcp-conductor` with its tools.
|
|
103
65
|
|
|
104
|
-
|
|
105
|
-
# Check system requirements
|
|
106
|
-
node dist/bin/cli.js check
|
|
66
|
+
---
|
|
107
67
|
|
|
108
|
-
|
|
109
|
-
node dist/bin/cli.js status
|
|
68
|
+
## What This Solves
|
|
110
69
|
|
|
111
|
-
|
|
112
|
-
node dist/bin/cli.js init [--dry-run]
|
|
70
|
+
When Claude calls MCP tools directly, every response lands in the context window — raw JSON, file metadata, pagination objects, fields you never asked for. A single GitHub `list_issues` call can return 40,000+ tokens. If you're making 10 calls per task, that's 400,000 tokens before Claude has written a single line of code.
|
|
113
71
|
|
|
114
|
-
|
|
115
|
-
node dist/bin/cli.js serve [options]
|
|
116
|
-
```
|
|
72
|
+
MCP Conductor flips the model: Claude writes TypeScript code that *processes* the tool responses inside a Deno sandbox. The sandbox can call any connected MCP server, filter and aggregate the results, and return only the compact summary. Your context window stays small. Your costs stay low.
|
|
117
73
|
|
|
118
|
-
|
|
74
|
+
```typescript
|
|
75
|
+
// This runs inside the Deno sandbox — not in Claude's context window
|
|
76
|
+
const [issues, files] = await mcp.batch([
|
|
77
|
+
() => mcp.server('github').call('list_issues', { owner: 'myorg', repo: 'myrepo', state: 'open' }),
|
|
78
|
+
() => mcp.server('filesystem').call('list_directory', { path: '/src' })
|
|
79
|
+
]);
|
|
119
80
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
--verbose # Enable debug logging
|
|
81
|
+
return {
|
|
82
|
+
openBugs: issues.filter(i => i.labels.some(l => l.name === 'bug')).length,
|
|
83
|
+
tsFiles: files.filter(f => f.name.endsWith('.ts')).length
|
|
84
|
+
};
|
|
85
|
+
// Returns: {"openBugs": 12, "tsFiles": 47} ← under 100 tokens
|
|
126
86
|
```
|
|
127
87
|
|
|
128
|
-
|
|
88
|
+
---
|
|
129
89
|
|
|
130
|
-
|
|
90
|
+
## How It Works
|
|
131
91
|
|
|
132
|
-
Exclusive mode ensures Claude ONLY sees mcp-conductor, forcing all MCP operations through `execute_code` for maximum token savings.
|
|
133
|
-
|
|
134
|
-
```bash
|
|
135
|
-
# Enable exclusive mode (recommended)
|
|
136
|
-
# Migrates servers from Claude config to ~/.mcp-conductor.json
|
|
137
|
-
node dist/bin/cli.js enable-exclusive [--dry-run]
|
|
138
|
-
|
|
139
|
-
# Disable exclusive mode
|
|
140
|
-
# Restores servers back to Claude config
|
|
141
|
-
node dist/bin/cli.js disable-exclusive [--dry-run]
|
|
142
|
-
|
|
143
|
-
# View current configuration status
|
|
144
|
-
node dist/bin/cli.js config show
|
|
145
|
-
|
|
146
|
-
# List servers in conductor config
|
|
147
|
-
node dist/bin/cli.js config servers
|
|
148
|
-
|
|
149
|
-
# Add a server to conductor config
|
|
150
|
-
node dist/bin/cli.js config add <name> <command> [args...]
|
|
151
|
-
|
|
152
|
-
# Remove a server from conductor config
|
|
153
|
-
node dist/bin/cli.js config remove <name>
|
|
154
92
|
```
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
node dist/bin/cli.js permissions list
|
|
163
|
-
|
|
164
|
-
# Discover all available MCP tools and show new permissions needed
|
|
165
|
-
node dist/bin/cli.js permissions discover --new-only
|
|
166
|
-
|
|
167
|
-
# Show as JSON (for manual copying)
|
|
168
|
-
node dist/bin/cli.js permissions discover --json
|
|
169
|
-
|
|
170
|
-
# Preview what would be added to settings
|
|
171
|
-
node dist/bin/cli.js permissions add --dry-run
|
|
172
|
-
|
|
173
|
-
# Add all new permissions to user settings (~/.claude/settings.json)
|
|
174
|
-
node dist/bin/cli.js permissions add
|
|
175
|
-
|
|
176
|
-
# Add to project settings instead (.claude/settings.json)
|
|
177
|
-
node dist/bin/cli.js permissions add --scope project
|
|
93
|
+
Claude
|
|
94
|
+
└── execute_code (writes TypeScript)
|
|
95
|
+
└── Deno Sandbox (50ms startup, <50MB RAM)
|
|
96
|
+
├── mcp.server('github').call(...) ← your MCP servers
|
|
97
|
+
├── mcp.server('filesystem').call(...) ← hidden from Claude
|
|
98
|
+
└── mcp.server('brave-search').call(...)
|
|
99
|
+
└── return { compact: "summary" } → back to Claude
|
|
178
100
|
```
|
|
179
101
|
|
|
180
|
-
|
|
102
|
+
The Deno sandbox runs with minimal permissions:
|
|
103
|
+
- Network: localhost bridge only
|
|
104
|
+
- No filesystem access (MCP handles that)
|
|
105
|
+
- No environment variable access
|
|
106
|
+
- No subprocess spawning
|
|
181
107
|
|
|
182
|
-
|
|
108
|
+
**Why Deno?** 50ms cold start vs 500ms–2s for Docker, under 50MB vs 200MB+ memory overhead, TypeScript natively, granular permission model.
|
|
183
109
|
|
|
184
|
-
|
|
110
|
+
---
|
|
185
111
|
|
|
186
|
-
|
|
187
|
-
# Install CLAUDE.md to a project directory
|
|
188
|
-
node dist/bin/cli.js install-instructions --dir /path/to/project
|
|
112
|
+
## Adding Your Servers
|
|
189
113
|
|
|
190
|
-
|
|
191
|
-
node dist/bin/cli.js install-instructions --append
|
|
114
|
+
Create `~/.mcp-conductor.json` to register backend servers:
|
|
192
115
|
|
|
193
|
-
|
|
194
|
-
|
|
116
|
+
```json
|
|
117
|
+
{
|
|
118
|
+
"exclusive": true,
|
|
119
|
+
"servers": {
|
|
120
|
+
"filesystem": {
|
|
121
|
+
"command": "npx",
|
|
122
|
+
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/yourname"],
|
|
123
|
+
"env": {}
|
|
124
|
+
},
|
|
125
|
+
"github": {
|
|
126
|
+
"command": "npx",
|
|
127
|
+
"args": ["-y", "@modelcontextprotocol/server-github"],
|
|
128
|
+
"env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "your-token" }
|
|
129
|
+
},
|
|
130
|
+
"brave-search": {
|
|
131
|
+
"command": "npx",
|
|
132
|
+
"args": ["-y", "@brave/brave-search-mcp-server", "--transport", "stdio"],
|
|
133
|
+
"env": { "BRAVE_API_KEY": "your-key" },
|
|
134
|
+
"rateLimit": {
|
|
135
|
+
"requestsPerSecond": 20,
|
|
136
|
+
"burstSize": 20,
|
|
137
|
+
"onLimitExceeded": "queue",
|
|
138
|
+
"maxQueueTimeMs": 30000
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
"memory": {
|
|
142
|
+
"command": "npx",
|
|
143
|
+
"args": ["-y", "@modelcontextprotocol/server-memory"],
|
|
144
|
+
"env": {}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
195
148
|
```
|
|
196
149
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
## MCP Tools
|
|
150
|
+
Set `"exclusive": true` to route *all* MCP calls through the sandbox. This is the recommended setting for maximum token savings — Claude cannot bypass the conductor.
|
|
200
151
|
|
|
201
|
-
|
|
152
|
+
**Hot reload:** Edit the file and save. Changes apply in ~500ms, no restart needed.
|
|
202
153
|
|
|
203
|
-
|
|
154
|
+
---
|
|
204
155
|
|
|
205
|
-
|
|
206
|
-
// Access MCP servers
|
|
207
|
-
const github = mcp.server('github');
|
|
208
|
-
const result = await github.call('search_repos', { query: 'ai' });
|
|
209
|
-
|
|
210
|
-
// Or use attribute-style access
|
|
211
|
-
const result = await mcp.github.call('search_repos', { query: 'ai' });
|
|
156
|
+
## The `mcp` API
|
|
212
157
|
|
|
213
|
-
|
|
214
|
-
const tools = await mcp.searchTools('file');
|
|
158
|
+
Inside `execute_code`, you have access to the `mcp` object:
|
|
215
159
|
|
|
216
|
-
|
|
217
|
-
|
|
160
|
+
```typescript
|
|
161
|
+
// Call a server tool
|
|
162
|
+
const result = await mcp.server('github').call('list_issues', { owner: 'org', repo: 'repo' });
|
|
163
|
+
|
|
164
|
+
// Parallel execution — executes all calls simultaneously
|
|
165
|
+
const [issues, files, searches] = await mcp.batch([
|
|
166
|
+
() => mcp.server('github').call('list_issues', { owner: 'org', repo: 'repo' }),
|
|
167
|
+
() => mcp.server('filesystem').call('list_directory', { path: '/src' }),
|
|
168
|
+
() => mcp.server('brave-search').call('search', { q: 'topic', count: 5 })
|
|
169
|
+
]);
|
|
218
170
|
|
|
219
|
-
//
|
|
220
|
-
mcp.
|
|
171
|
+
// Batch web searches (handles rate limits automatically)
|
|
172
|
+
const results = await mcp.batchSearch(['query 1', 'query 2', 'query 3'], { topN: 3 });
|
|
221
173
|
|
|
222
|
-
//
|
|
223
|
-
|
|
224
|
-
{ server: 'github', tool: 'search_repositories', params: { query: 'ai' } },
|
|
225
|
-
{ server: 'github', tool: 'search_repositories', params: { query: 'ml' } },
|
|
226
|
-
]);
|
|
174
|
+
// Progress updates (visible in Claude)
|
|
175
|
+
mcp.progress('Processing 500 files...');
|
|
227
176
|
|
|
228
|
-
//
|
|
229
|
-
|
|
230
|
-
'query 1',
|
|
231
|
-
'query 2',
|
|
232
|
-
'query 3'
|
|
233
|
-
], { topN: 3 });
|
|
177
|
+
// Debug logging
|
|
178
|
+
console.log('issue count:', issues.length);
|
|
234
179
|
```
|
|
235
180
|
|
|
236
|
-
|
|
181
|
+
---
|
|
237
182
|
|
|
238
|
-
|
|
183
|
+
## Measuring Your Savings
|
|
239
184
|
|
|
240
|
-
|
|
185
|
+
After any workflow, ask Claude to call `get_metrics`:
|
|
241
186
|
|
|
242
|
-
|
|
187
|
+
```json
|
|
188
|
+
{
|
|
189
|
+
"totalExecutions": 47,
|
|
190
|
+
"averageCompressionRatio": 0.943,
|
|
191
|
+
"totalTokensSaved": 1847230,
|
|
192
|
+
"averageExecutionMs": 73,
|
|
193
|
+
"lastExecution": {
|
|
194
|
+
"compressionRatio": 0.978,
|
|
195
|
+
"tokensSaved": 44200,
|
|
196
|
+
"inputTokens": 45000,
|
|
197
|
+
"outputTokens": 800
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
```
|
|
243
201
|
|
|
244
|
-
|
|
202
|
+
`compressionRatio: 0.978` means 97.8% of tokens were processed inside the sandbox rather than billed to your context window. `totalTokensSaved: 1,847,230` is the cumulative count across all 47 executions.
|
|
245
203
|
|
|
246
|
-
|
|
204
|
+
---
|
|
247
205
|
|
|
248
|
-
|
|
206
|
+
## MCP Tools Available to Claude
|
|
249
207
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
208
|
+
| Tool | Description |
|
|
209
|
+
|------|-------------|
|
|
210
|
+
| `execute_code` | Run TypeScript in the Deno sandbox with MCP server access |
|
|
211
|
+
| `list_servers` | List all connected backend servers |
|
|
212
|
+
| `discover_tools` | Search for tools across all servers |
|
|
213
|
+
| `get_metrics` | Session statistics and compression ratios |
|
|
214
|
+
| `set_mode` | Switch between `execution`, `passthrough`, or `hybrid` mode |
|
|
215
|
+
| `compare_modes` | Compare how a task runs in each mode |
|
|
216
|
+
| `add_server` | Add a server to the conductor config at runtime |
|
|
217
|
+
| `remove_server` | Remove a server at runtime |
|
|
218
|
+
| `update_server` | Update a server's config (e.g. rotate an API key) without restart |
|
|
219
|
+
| `reload_servers` | Reload config after manual edits |
|
|
220
|
+
| `passthrough_call` | Make a direct tool call (high token cost — debug only) |
|
|
254
221
|
|
|
255
|
-
|
|
222
|
+
---
|
|
256
223
|
|
|
257
|
-
|
|
224
|
+
## CLI Reference
|
|
258
225
|
|
|
259
|
-
|
|
226
|
+
```bash
|
|
227
|
+
# Check system requirements (Node, Deno, Claude config)
|
|
228
|
+
mcp-conductor-cli check
|
|
260
229
|
|
|
261
|
-
|
|
230
|
+
# Show current configuration status
|
|
231
|
+
mcp-conductor-cli status
|
|
262
232
|
|
|
263
|
-
|
|
233
|
+
# Enable exclusive mode (migrates servers to ~/.mcp-conductor.json)
|
|
234
|
+
mcp-conductor-cli enable-exclusive [--dry-run]
|
|
264
235
|
|
|
265
|
-
|
|
236
|
+
# Disable exclusive mode (restores servers to Claude config)
|
|
237
|
+
mcp-conductor-cli disable-exclusive [--dry-run]
|
|
266
238
|
|
|
267
|
-
|
|
239
|
+
# Add/remove/list servers in conductor config
|
|
240
|
+
mcp-conductor-cli config add <name> <command> [args...]
|
|
241
|
+
mcp-conductor-cli config remove <name>
|
|
242
|
+
mcp-conductor-cli config servers
|
|
268
243
|
|
|
269
|
-
|
|
244
|
+
# Manage Claude Code permissions (auto-allow all MCP tools)
|
|
245
|
+
mcp-conductor-cli permissions discover --new-only
|
|
246
|
+
mcp-conductor-cli permissions add [--scope project]
|
|
270
247
|
|
|
271
|
-
|
|
248
|
+
# Install CLAUDE.md to teach Claude to use execute_code
|
|
249
|
+
mcp-conductor-cli install-instructions --dir /path/to/project
|
|
250
|
+
```
|
|
272
251
|
|
|
273
|
-
|
|
252
|
+
---
|
|
274
253
|
|
|
275
|
-
|
|
254
|
+
## Recipes
|
|
276
255
|
|
|
277
|
-
|
|
256
|
+
### Parallel GitHub + Filesystem analysis
|
|
278
257
|
|
|
279
258
|
```typescript
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
259
|
+
mcp.progress('Fetching issues and scanning codebase...');
|
|
260
|
+
const [issues, files] = await mcp.batch([
|
|
261
|
+
() => mcp.server('github').call('list_issues', { owner: 'myorg', repo: 'myrepo', state: 'open', per_page: 100 }),
|
|
262
|
+
() => mcp.server('filesystem').call('search_files', { path: '/src', pattern: '*.ts' })
|
|
263
|
+
]);
|
|
264
|
+
return {
|
|
265
|
+
openBugs: issues.filter(i => i.labels.some(l => l.name === 'bug')).length,
|
|
266
|
+
tsFileCount: files.length
|
|
267
|
+
};
|
|
285
268
|
```
|
|
286
269
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
For projects requiring multiple web searches, you can add [brave-search](https://www.npmjs.com/package/@modelcontextprotocol/server-brave-search) MCP server for batched, parallel searches via `execute_code`.
|
|
290
|
-
|
|
291
|
-
### Setup
|
|
292
|
-
|
|
293
|
-
1. Get a free Brave Search API key (2000 queries/month): https://brave.com/search/api/
|
|
294
|
-
|
|
295
|
-
2. Add to your conductor config:
|
|
296
|
-
```bash
|
|
297
|
-
node dist/bin/cli.js config add brave-search npx -y @modelcontextprotocol/server-brave-search
|
|
298
|
-
```
|
|
299
|
-
|
|
300
|
-
3. Set the API key in `~/.mcp-conductor.json`:
|
|
301
|
-
```json
|
|
302
|
-
{
|
|
303
|
-
"servers": {
|
|
304
|
-
"brave-search": {
|
|
305
|
-
"command": "npx",
|
|
306
|
-
"args": ["-y", "@modelcontextprotocol/server-brave-search"],
|
|
307
|
-
"env": {
|
|
308
|
-
"BRAVE_API_KEY": "your-api-key-here"
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
```
|
|
314
|
-
|
|
315
|
-
4. Restart Claude to reload servers.
|
|
316
|
-
|
|
317
|
-
### Usage
|
|
318
|
-
|
|
319
|
-
With brave-search configured, use `mcp.batchSearch()` for automatic rate limit handling:
|
|
270
|
+
### Parallel web research
|
|
320
271
|
|
|
321
272
|
```typescript
|
|
322
|
-
|
|
323
|
-
const results = await mcp.
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
], { topN: 3 });
|
|
328
|
-
|
|
329
|
-
return results;
|
|
330
|
-
// Returns: { "TypeScript...": [{title, url, description}, ...], ... }
|
|
273
|
+
const topics = ['MCP protocol 2026', 'Deno performance benchmarks', 'token optimization AI'];
|
|
274
|
+
const results = await mcp.batch(
|
|
275
|
+
topics.map(q => () => mcp.server('brave-search').call('search', { q, count: 5 }))
|
|
276
|
+
);
|
|
277
|
+
return results.map((r, i) => ({ topic: topics[i], topResult: r[0]?.title, url: r[0]?.url }));
|
|
331
278
|
```
|
|
332
279
|
|
|
333
|
-
|
|
334
|
-
- Attempts parallel execution first (fastest)
|
|
335
|
-
- Auto-detects rate limits from API errors
|
|
336
|
-
- Falls back to sequential with 1.1s delays if rate limited
|
|
337
|
-
- Logs warnings with upgrade guidance when rate limited
|
|
338
|
-
- Parses text responses into structured data
|
|
280
|
+
### Cross-session memory persistence
|
|
339
281
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
282
|
+
```typescript
|
|
283
|
+
// Session 1: store results
|
|
284
|
+
const analysis = { /* ... your analysis ... */ };
|
|
285
|
+
await mcp.server('memory').call('store', { key: 'weekly-audit', value: analysis });
|
|
286
|
+
return analysis;
|
|
287
|
+
|
|
288
|
+
// Session 2: retrieve and compare
|
|
289
|
+
const previous = await mcp.server('memory').call('retrieve', { key: 'weekly-audit' });
|
|
290
|
+
// diff previous vs current...
|
|
344
291
|
```
|
|
345
292
|
|
|
346
|
-
|
|
347
|
-
- No manual rate limit handling needed
|
|
348
|
-
- Parallel when possible, sequential when required
|
|
349
|
-
- 80%+ token savings vs native WebSearch
|
|
350
|
-
|
|
351
|
-
### Upgrading Your Plan
|
|
352
|
-
|
|
353
|
-
After upgrading your Brave Search API plan:
|
|
354
|
-
|
|
355
|
-
1. **Update the API key** (no restart needed):
|
|
356
|
-
```typescript
|
|
357
|
-
mcp__mcp-conductor__update_server({
|
|
358
|
-
name: 'brave-search',
|
|
359
|
-
env: { BRAVE_API_KEY: 'your-new-api-key' }
|
|
360
|
-
})
|
|
361
|
-
```
|
|
362
|
-
|
|
363
|
-
2. **Test parallel mode** with `forceParallel`:
|
|
364
|
-
```typescript
|
|
365
|
-
const results = await mcp.batchSearch([
|
|
366
|
-
'query 1', 'query 2', 'query 3', 'query 4', 'query 5'
|
|
367
|
-
], { topN: 3, forceParallel: true });
|
|
368
|
-
```
|
|
369
|
-
|
|
370
|
-
3. If parallel works, it will be used automatically for all subsequent batches
|
|
293
|
+
---
|
|
371
294
|
|
|
372
|
-
##
|
|
373
|
-
|
|
374
|
-
### Exclusive Mode (Recommended)
|
|
375
|
-
|
|
376
|
-
In exclusive mode, Claude only sees mcp-conductor and **must** use `execute_code` for all MCP operations. This provides:
|
|
377
|
-
|
|
378
|
-
- **Maximum token savings** (90-98% reduction)
|
|
379
|
-
- **No bypass possible** - Claude cannot make direct MCP calls
|
|
380
|
-
- **No CLAUDE.md required** - Works automatically in any project
|
|
381
|
-
|
|
382
|
-
**How it works:**
|
|
383
|
-
|
|
384
|
-
```
|
|
385
|
-
Before (default): After (exclusive mode):
|
|
386
|
-
┌─────────────────────────────┐ ┌─────────────────────────────┐
|
|
387
|
-
│ Claude's Config │ │ Claude's Config │
|
|
388
|
-
│ ├── mcp-conductor │ │ └── mcp-conductor ← ONLY │
|
|
389
|
-
│ ├── github ← Claude sees │ └─────────────────────────────┘
|
|
390
|
-
│ ├── filesystem ← can bypass │ ┌─────────────────────────────┐
|
|
391
|
-
│ └── other servers... │ │ ~/.mcp-conductor.json │
|
|
392
|
-
└─────────────────────────────┘ │ ├── github ← hidden │
|
|
393
|
-
│ ├── filesystem ← hidden │
|
|
394
|
-
│ └── other servers... │
|
|
395
|
-
└─────────────────────────────┘
|
|
396
|
-
```
|
|
397
|
-
|
|
398
|
-
Enable exclusive mode:
|
|
399
|
-
```bash
|
|
400
|
-
node dist/bin/cli.js enable-exclusive
|
|
401
|
-
```
|
|
295
|
+
## Troubleshooting
|
|
402
296
|
|
|
403
|
-
|
|
297
|
+
**"Deno not found"** — Install Deno, then `source ~/.zshrc` (or open a new terminal). Verify with `deno --version`.
|
|
404
298
|
|
|
405
|
-
|
|
406
|
-
MCP_CONDUCTOR_PORT=0 # Bridge port (0 = dynamic allocation)
|
|
407
|
-
MCP_CONDUCTOR_MODE=execution # Operation mode
|
|
408
|
-
MCP_CONDUCTOR_TIMEOUT=30000 # Default timeout in ms
|
|
409
|
-
MCP_CONDUCTOR_LOG_LEVEL=info # Log level: debug|info|warn|error
|
|
410
|
-
```
|
|
299
|
+
**"Server not connecting"** — Validate your JSON: `cat ~/.mcp-conductor.json | python3 -m json.tool`. Check that env vars are set (not still saying `"your-token"`).
|
|
411
300
|
|
|
412
|
-
|
|
301
|
+
**"`exclusive` mode not working"** — `"exclusive": true` must be at the root level, not inside `"servers"`.
|
|
413
302
|
|
|
414
|
-
|
|
415
|
-
import { MCPConductorServer, loadConfig } from '@darkiceinteractive/mcp-conductor';
|
|
303
|
+
**"Rate limit errors from brave-search"** — Add a `rateLimit` block to the server config (see example above). Set `onLimitExceeded: "queue"` to buffer requests.
|
|
416
304
|
|
|
417
|
-
|
|
418
|
-
const server = new MCPConductorServer(config);
|
|
419
|
-
await server.start();
|
|
420
|
-
```
|
|
305
|
+
**"Config changes not applying"** — The file watcher requires valid JSON. If you saved a file with a syntax error, fix it and save again.
|
|
421
306
|
|
|
422
|
-
|
|
307
|
+
Full troubleshooting guide: [docs/troubleshooting.md](./docs/troubleshooting.md)
|
|
423
308
|
|
|
424
|
-
|
|
425
|
-
- Network access only to localhost bridge
|
|
426
|
-
- No filesystem access (except via MCP)
|
|
427
|
-
- No environment variable access
|
|
428
|
-
- No subprocess spawning
|
|
429
|
-
- Memory limits via V8 flags
|
|
309
|
+
---
|
|
430
310
|
|
|
431
311
|
## Development
|
|
432
312
|
|
|
433
313
|
```bash
|
|
434
|
-
|
|
314
|
+
git clone https://github.com/darkiceinteractive/mcp-conductor.git
|
|
315
|
+
cd mcp-conductor
|
|
435
316
|
npm install
|
|
436
|
-
|
|
437
|
-
# Build
|
|
438
317
|
npm run build
|
|
439
|
-
|
|
440
|
-
#
|
|
441
|
-
npm
|
|
442
|
-
|
|
443
|
-
# Run tests once (no watch)
|
|
444
|
-
npm run test:run
|
|
445
|
-
|
|
446
|
-
# Run with coverage
|
|
447
|
-
npm run test:coverage
|
|
448
|
-
|
|
449
|
-
# Development mode (watch)
|
|
450
|
-
npm run dev
|
|
451
|
-
|
|
452
|
-
# Lint
|
|
453
|
-
npm run lint
|
|
454
|
-
|
|
455
|
-
# Format
|
|
456
|
-
npm run format
|
|
318
|
+
npm run test:run # 673 tests, 82% coverage
|
|
319
|
+
npm run test:coverage # with coverage report
|
|
320
|
+
npm run dev # watch mode
|
|
457
321
|
```
|
|
458
322
|
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
### Publishing to npm
|
|
323
|
+
**Requirements:** Node.js 18+, Deno 2.x
|
|
462
324
|
|
|
463
|
-
|
|
464
|
-
2. Build and test:
|
|
465
|
-
```bash
|
|
466
|
-
npm run build
|
|
467
|
-
npm run test:run
|
|
468
|
-
```
|
|
469
|
-
3. Publish:
|
|
470
|
-
```bash
|
|
471
|
-
npm publish --access public
|
|
472
|
-
```
|
|
473
|
-
|
|
474
|
-
### Creating a GitHub Release
|
|
475
|
-
|
|
476
|
-
1. Tag the release:
|
|
477
|
-
```bash
|
|
478
|
-
git tag v0.1.0
|
|
479
|
-
git push origin v0.1.0
|
|
480
|
-
```
|
|
481
|
-
2. Create a release on GitHub with the changelog
|
|
482
|
-
|
|
483
|
-
### Local Development with Claude Desktop
|
|
484
|
-
|
|
485
|
-
For local development, point Claude Desktop to your development build:
|
|
486
|
-
|
|
487
|
-
```json
|
|
488
|
-
{
|
|
489
|
-
"mcpServers": {
|
|
490
|
-
"mcp-conductor": {
|
|
491
|
-
"command": "node",
|
|
492
|
-
"args": ["/Users/you/Dev/mcp-conductor/dist/index.js"]
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
```
|
|
325
|
+
---
|
|
497
326
|
|
|
498
327
|
## Architecture
|
|
499
328
|
|
|
329
|
+
Full architecture documentation: [docs/guide/](./docs/guide/)
|
|
330
|
+
|
|
500
331
|
```
|
|
501
|
-
Claude Code
|
|
502
|
-
|
|
503
|
-
|
|
332
|
+
Claude Code / Claude Desktop
|
|
333
|
+
│
|
|
334
|
+
└── MCP Protocol
|
|
335
|
+
│
|
|
336
|
+
┌───────▼──────────────┐
|
|
337
|
+
│ MCP Conductor │
|
|
338
|
+
│ (Node.js MCP server) │
|
|
339
|
+
│ │
|
|
340
|
+
│ execute_code ──────► Deno Subprocess (50ms, <50MB)
|
|
341
|
+
│ list_servers │ TypeScript code runs here
|
|
342
|
+
│ get_metrics │ MCP calls via HTTP bridge
|
|
343
|
+
│ add_server │ Only result exits sandbox
|
|
344
|
+
└───────────────────────┘
|
|
345
|
+
│
|
|
346
|
+
┌─────────▼──────────────────────────────┐
|
|
347
|
+
│ HTTP Bridge (localhost) │
|
|
348
|
+
└──┬──────────┬──────────┬───────────────┘
|
|
349
|
+
│ │ │
|
|
350
|
+
github filesystem brave-search ... (any MCP server)
|
|
504
351
|
```
|
|
505
352
|
|
|
506
|
-
|
|
507
|
-
2. Code is wrapped and run in isolated Deno subprocess
|
|
508
|
-
3. Sandbox calls HTTP bridge to invoke MCP tools
|
|
509
|
-
4. Only the final return value goes back to Claude
|
|
353
|
+
---
|
|
510
354
|
|
|
511
355
|
## Documentation
|
|
512
356
|
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
|
516
|
-
|
|
517
|
-
| [
|
|
518
|
-
| [
|
|
519
|
-
| [
|
|
520
|
-
| [
|
|
521
|
-
| [
|
|
522
|
-
| [
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
357
|
+
| Guide | Description |
|
|
358
|
+
|-------|-------------|
|
|
359
|
+
| [Getting Started](./docs/guide/getting-started.md) | First-time setup walkthrough |
|
|
360
|
+
| [MCP Clients](./docs/guide/mcp-clients.md) | Setup for Claude, Codex, Gemini, Kimi, VS Code, Cursor, Windsurf, Cline |
|
|
361
|
+
| [Configuration](./docs/configuration.md) | All config options and environment variables |
|
|
362
|
+
| [Architecture](./docs/architecture.md) | System design and data flow |
|
|
363
|
+
| [MCP Tools Reference](./docs/api/tools.md) | All tools available to Claude |
|
|
364
|
+
| [Sandbox API](./docs/api/sandbox-api.md) | The `mcp` object inside execute_code |
|
|
365
|
+
| [CLI Reference](./docs/cli-reference.md) | Command-line tool usage |
|
|
366
|
+
| [Examples](./docs/examples/) | Recipes and patterns |
|
|
367
|
+
| [Benchmarks](./docs/benchmarks/methodology.md) | Token savings methodology and results |
|
|
368
|
+
| [Security](./docs/permissions.md) | Deno sandbox permission model |
|
|
369
|
+
| [Troubleshooting](./docs/troubleshooting.md) | Common issues and fixes |
|
|
370
|
+
|
|
371
|
+
---
|
|
527
372
|
|
|
528
|
-
|
|
529
|
-
```bash
|
|
530
|
-
brew install deno # macOS
|
|
531
|
-
```
|
|
532
|
-
|
|
533
|
-
### "Network access denied"
|
|
534
|
-
|
|
535
|
-
The Deno sandbox only allows access to the localhost bridge. Ensure your MCP servers are accessible through the bridge.
|
|
536
|
-
|
|
537
|
-
### "Timeout exceeded"
|
|
373
|
+
## Contributing
|
|
538
374
|
|
|
539
|
-
|
|
540
|
-
```typescript
|
|
541
|
-
// In execute_code call
|
|
542
|
-
{ timeout_ms: 60000 }
|
|
543
|
-
```
|
|
375
|
+
Contributions welcome. Please read [CONTRIBUTING.md](./CONTRIBUTING.md) for guidelines.
|
|
544
376
|
|
|
545
|
-
|
|
377
|
+
- **Bug reports:** [GitHub Issues](https://github.com/darkiceinteractive/mcp-conductor/issues)
|
|
378
|
+
- **Discussions:** [GitHub Discussions](https://github.com/darkiceinteractive/mcp-conductor/discussions)
|
|
379
|
+
- **Security:** See [SECURITY.md](./SECURITY.md)
|
|
546
380
|
|
|
547
|
-
|
|
548
|
-
1. Listed in claude_desktop_config.json
|
|
549
|
-
2. Properly started and connected
|
|
550
|
-
3. Use `list_servers` to verify
|
|
381
|
+
---
|
|
551
382
|
|
|
552
383
|
## Licence
|
|
553
384
|
|
|
554
|
-
MIT
|
|
385
|
+
MIT — see [LICENSE](./LICENSE)
|
|
555
386
|
|
|
556
|
-
|
|
387
|
+
---
|
|
557
388
|
|
|
558
|
-
|
|
389
|
+
*Built by [DarkIce Interactive](https://darkiceinteractive.com) · [@darkiceinteractive/mcp-conductor on npm](https://www.npmjs.com/package/@darkiceinteractive/mcp-conductor)*
|