@zhixuan92/multi-model-agent-mcp 0.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 +21 -0
- package/README.md +153 -0
- package/dist/cli.d.ts +53 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +125 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/routing/render-provider-routing-matrix.d.ts +7 -0
- package/dist/routing/render-provider-routing-matrix.d.ts.map +1 -0
- package/dist/routing/render-provider-routing-matrix.js +63 -0
- package/dist/routing/render-provider-routing-matrix.js.map +1 -0
- package/package.json +59 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Zhang Zhixuan
|
|
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,153 @@
|
|
|
1
|
+
# @zhixuan92/multi-model-agent-mcp
|
|
2
|
+
|
|
3
|
+
MCP stdio server for [`multi-model-agent`](https://github.com/zhixuan312/multi-model-agent). Exposes one tool — `delegate_tasks` — that runs work in parallel across multiple LLM providers (Claude, Codex, OpenAI-compatible) and auto-routes each task to the cheapest provider that can handle it.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Run without installing
|
|
9
|
+
npx @zhixuan92/multi-model-agent-mcp serve
|
|
10
|
+
|
|
11
|
+
# Or install globally
|
|
12
|
+
npm install -g @zhixuan92/multi-model-agent-mcp
|
|
13
|
+
multi-model-agent serve
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
If you plan to use `openai-compatible` providers, also install the optional peer dependencies:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install -g @zhixuan92/multi-model-agent-mcp @openai/agents openai
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Requires Node `>= 22`.
|
|
23
|
+
|
|
24
|
+
## Configure
|
|
25
|
+
|
|
26
|
+
Create `~/.multi-model/config.json`:
|
|
27
|
+
|
|
28
|
+
```json
|
|
29
|
+
{
|
|
30
|
+
"providers": {
|
|
31
|
+
"claude": {
|
|
32
|
+
"type": "claude",
|
|
33
|
+
"model": "claude-sonnet-4-6",
|
|
34
|
+
"costTier": "medium"
|
|
35
|
+
},
|
|
36
|
+
"codex": {
|
|
37
|
+
"type": "codex",
|
|
38
|
+
"model": "gpt-5-codex",
|
|
39
|
+
"costTier": "medium"
|
|
40
|
+
},
|
|
41
|
+
"minimax": {
|
|
42
|
+
"type": "openai-compatible",
|
|
43
|
+
"model": "MiniMax-M2",
|
|
44
|
+
"baseUrl": "https://api.minimax.io/v1",
|
|
45
|
+
"apiKeyEnv": "MINIMAX_API_KEY",
|
|
46
|
+
"costTier": "free",
|
|
47
|
+
"hostedTools": ["web_search"]
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"defaults": {
|
|
51
|
+
"maxTurns": 200,
|
|
52
|
+
"timeoutMs": 600000,
|
|
53
|
+
"tools": "full"
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Config lookup order: `--config <path>` → `MULTI_MODEL_CONFIG` env var → `~/.multi-model/config.json`.
|
|
59
|
+
|
|
60
|
+
Provider auth:
|
|
61
|
+
|
|
62
|
+
- **`codex`** uses `codex login` if available, otherwise `OPENAI_API_KEY`
|
|
63
|
+
- **`claude`** uses `ANTHROPIC_API_KEY` if set, otherwise the local Claude auth flow
|
|
64
|
+
- **`openai-compatible`** uses `apiKeyEnv` (preferred) or inline `apiKey`
|
|
65
|
+
|
|
66
|
+
## Register with an MCP client
|
|
67
|
+
|
|
68
|
+
### Claude Code
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
claude mcp add multi-model-agent -- npx @zhixuan92/multi-model-agent-mcp serve
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
If your providers need environment variables:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
claude mcp add multi-model-agent \
|
|
78
|
+
-e OPENAI_API_KEY=sk-... \
|
|
79
|
+
-e ANTHROPIC_API_KEY=sk-ant-... \
|
|
80
|
+
-e MINIMAX_API_KEY=... \
|
|
81
|
+
-- npx @zhixuan92/multi-model-agent-mcp serve
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Claude Desktop
|
|
85
|
+
|
|
86
|
+
Add to `claude_desktop_config.json`:
|
|
87
|
+
|
|
88
|
+
```json
|
|
89
|
+
{
|
|
90
|
+
"mcpServers": {
|
|
91
|
+
"multi-model-agent": {
|
|
92
|
+
"command": "npx",
|
|
93
|
+
"args": ["@zhixuan92/multi-model-agent-mcp", "serve"],
|
|
94
|
+
"env": {
|
|
95
|
+
"OPENAI_API_KEY": "sk-...",
|
|
96
|
+
"ANTHROPIC_API_KEY": "sk-ant-...",
|
|
97
|
+
"MINIMAX_API_KEY": "..."
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Restart your MCP client after changing config.
|
|
105
|
+
|
|
106
|
+
## The `delegate_tasks` tool
|
|
107
|
+
|
|
108
|
+
Accepts an array of tasks and runs them concurrently. Auto-routes each task by capability filter → quality tier filter → cheapest remaining provider, or pin a task to a specific provider.
|
|
109
|
+
|
|
110
|
+
```json
|
|
111
|
+
{
|
|
112
|
+
"tasks": [
|
|
113
|
+
{
|
|
114
|
+
"prompt": "Refactor auth.ts to use JWT.",
|
|
115
|
+
"provider": "claude",
|
|
116
|
+
"tier": "reasoning",
|
|
117
|
+
"requiredCapabilities": ["file_read", "file_write"],
|
|
118
|
+
"tools": "full",
|
|
119
|
+
"cwd": "/path/to/project"
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
"prompt": "Write tests for the auth module.",
|
|
123
|
+
"tier": "standard",
|
|
124
|
+
"requiredCapabilities": ["file_read", "file_write", "grep"],
|
|
125
|
+
"tools": "full",
|
|
126
|
+
"cwd": "/path/to/project"
|
|
127
|
+
}
|
|
128
|
+
]
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Per-task fields: `prompt`, `tier`, `requiredCapabilities`, `provider?`, `tools?`, `maxTurns?`, `timeoutMs?`, `cwd?`, `effort?`, `sandboxPolicy?`.
|
|
133
|
+
|
|
134
|
+
Capabilities: `file_read`, `file_write`, `grep`, `glob`, `shell`, `web_search`, `web_fetch`.
|
|
135
|
+
|
|
136
|
+
## Security
|
|
137
|
+
|
|
138
|
+
- File tools enforce a `cwd-only` sandbox by default — paths are resolved via `fs.realpath` and rejected if outside the task's `cwd`.
|
|
139
|
+
- `runShell` is hard-disabled under `cwd-only`. Set `sandboxPolicy: 'none'` per-provider or per-task to opt in.
|
|
140
|
+
- `readFile` rejects targets larger than 50 MiB; `writeFile` rejects content larger than 100 MiB.
|
|
141
|
+
- The server warns at config-load time if it sees an inline `apiKey` instead of `apiKeyEnv`.
|
|
142
|
+
- The server warns once if `~/.codex/auth.json` is group- or world-readable.
|
|
143
|
+
- `CODEX_DEBUG=1` enables raw request/response logging to stderr (do not enable in environments that ship logs anywhere).
|
|
144
|
+
|
|
145
|
+
## Documentation
|
|
146
|
+
|
|
147
|
+
Full docs, capability matrix, configuration reference, troubleshooting, and contributor guide:
|
|
148
|
+
|
|
149
|
+
→ **<https://github.com/zhixuan312/multi-model-agent#readme>**
|
|
150
|
+
|
|
151
|
+
## License
|
|
152
|
+
|
|
153
|
+
[MIT](./LICENSE) — Copyright (c) 2026 Zhang Zhixuan
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import { runTasks } from '@zhixuan92/multi-model-agent-core/run-tasks';
|
|
5
|
+
import type { MultiModelConfig } from '@zhixuan92/multi-model-agent-core';
|
|
6
|
+
export declare const SERVER_NAME = "multi-model-agent";
|
|
7
|
+
export declare const SERVER_VERSION = "0.1.0";
|
|
8
|
+
export declare function buildTaskSchema(availableProviders: [string, ...string[]]): z.ZodObject<{
|
|
9
|
+
prompt: z.ZodString;
|
|
10
|
+
provider: z.ZodOptional<z.ZodEnum<{
|
|
11
|
+
[x: string]: string;
|
|
12
|
+
}>>;
|
|
13
|
+
tier: z.ZodEnum<{
|
|
14
|
+
trivial: "trivial";
|
|
15
|
+
standard: "standard";
|
|
16
|
+
reasoning: "reasoning";
|
|
17
|
+
}>;
|
|
18
|
+
requiredCapabilities: z.ZodArray<z.ZodEnum<{
|
|
19
|
+
file_read: "file_read";
|
|
20
|
+
file_write: "file_write";
|
|
21
|
+
grep: "grep";
|
|
22
|
+
glob: "glob";
|
|
23
|
+
shell: "shell";
|
|
24
|
+
web_search: "web_search";
|
|
25
|
+
web_fetch: "web_fetch";
|
|
26
|
+
}>>;
|
|
27
|
+
tools: z.ZodOptional<z.ZodEnum<{
|
|
28
|
+
none: "none";
|
|
29
|
+
full: "full";
|
|
30
|
+
}>>;
|
|
31
|
+
maxTurns: z.ZodOptional<z.ZodNumber>;
|
|
32
|
+
timeoutMs: z.ZodOptional<z.ZodNumber>;
|
|
33
|
+
cwd: z.ZodOptional<z.ZodString>;
|
|
34
|
+
effort: z.ZodOptional<z.ZodEnum<{
|
|
35
|
+
low: "low";
|
|
36
|
+
medium: "medium";
|
|
37
|
+
high: "high";
|
|
38
|
+
none: "none";
|
|
39
|
+
}>>;
|
|
40
|
+
sandboxPolicy: z.ZodOptional<z.ZodEnum<{
|
|
41
|
+
none: "none";
|
|
42
|
+
"cwd-only": "cwd-only";
|
|
43
|
+
}>>;
|
|
44
|
+
}, z.core.$strip>;
|
|
45
|
+
export declare function buildMcpServer(config: Parameters<typeof runTasks>[1]): McpServer;
|
|
46
|
+
/**
|
|
47
|
+
* MCP CLI config discovery (owned by MCP, not core):
|
|
48
|
+
* 1. --config <path> argument (explicit)
|
|
49
|
+
* 2. MULTI_MODEL_CONFIG environment variable
|
|
50
|
+
* 3. ~/.multi-model/config.json (default home-directory location)
|
|
51
|
+
*/
|
|
52
|
+
export declare function discoverConfig(): Promise<MultiModelConfig>;
|
|
53
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAMA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,QAAQ,EAAE,MAAM,6CAA6C,CAAC;AACvE,OAAO,KAAK,EAAE,gBAAgB,EAAY,MAAM,mCAAmC,CAAC;AAGpF,eAAO,MAAM,WAAW,sBAAsB,CAAC;AAC/C,eAAO,MAAM,cAAc,UAAU,CAAC;AAEtC,wBAAgB,eAAe,CAAC,kBAAkB,EAAE,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAkBxE;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,aAyCpE;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAuBhE"}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import os from 'os';
|
|
5
|
+
import { fileURLToPath } from 'url';
|
|
6
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
7
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
8
|
+
import { z } from 'zod';
|
|
9
|
+
import { loadConfigFromFile } from '@zhixuan92/multi-model-agent-core/config/load';
|
|
10
|
+
import { parseConfig } from '@zhixuan92/multi-model-agent-core/config/schema';
|
|
11
|
+
import { runTasks } from '@zhixuan92/multi-model-agent-core/run-tasks';
|
|
12
|
+
import { renderProviderRoutingMatrix } from './routing/render-provider-routing-matrix.js';
|
|
13
|
+
export const SERVER_NAME = 'multi-model-agent';
|
|
14
|
+
export const SERVER_VERSION = '0.1.0';
|
|
15
|
+
export function buildTaskSchema(availableProviders) {
|
|
16
|
+
return z.object({
|
|
17
|
+
prompt: z.string().describe('Task prompt for the sub-agent'),
|
|
18
|
+
provider: z.enum(availableProviders).describe('Provider name').optional(),
|
|
19
|
+
tier: z.enum(['trivial', 'standard', 'reasoning'])
|
|
20
|
+
.describe('Required quality tier.'),
|
|
21
|
+
requiredCapabilities: z.array(z.enum([
|
|
22
|
+
'file_read', 'file_write', 'grep', 'glob',
|
|
23
|
+
'shell', 'web_search', 'web_fetch',
|
|
24
|
+
])).describe('Capabilities this task requires. Empty array if none.'),
|
|
25
|
+
tools: z.enum(['none', 'full']).optional().describe('Tool access mode. Default: full'),
|
|
26
|
+
maxTurns: z.number().int().positive().optional().describe('Max agent loop turns. Default: 200'),
|
|
27
|
+
timeoutMs: z.number().int().positive().optional().describe('Timeout in ms. Default: 600000'),
|
|
28
|
+
cwd: z.string().optional().describe('Working directory for file/shell tools'),
|
|
29
|
+
effort: z.enum(['none', 'low', 'medium', 'high']).optional()
|
|
30
|
+
.describe("Reasoning effort."),
|
|
31
|
+
sandboxPolicy: z.enum(['none', 'cwd-only']).optional().describe('File-system confinement policy. Default: cwd-only'),
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
export function buildMcpServer(config) {
|
|
35
|
+
const providerKeys = Object.keys(config.providers);
|
|
36
|
+
if (providerKeys.length === 0) {
|
|
37
|
+
throw new Error('buildMcpServer requires at least one configured provider.');
|
|
38
|
+
}
|
|
39
|
+
const server = new McpServer({
|
|
40
|
+
name: SERVER_NAME,
|
|
41
|
+
version: SERVER_VERSION,
|
|
42
|
+
});
|
|
43
|
+
const availableProviders = providerKeys;
|
|
44
|
+
server.tool('delegate_tasks', renderProviderRoutingMatrix(config), {
|
|
45
|
+
tasks: z.array(buildTaskSchema(availableProviders)).describe('Array of tasks to execute in parallel'),
|
|
46
|
+
}, async ({ tasks }) => {
|
|
47
|
+
const results = await runTasks(tasks, config);
|
|
48
|
+
const response = {
|
|
49
|
+
results: results.map((r, i) => ({
|
|
50
|
+
provider: tasks[i].provider ?? '(auto)',
|
|
51
|
+
status: r.status,
|
|
52
|
+
output: r.output,
|
|
53
|
+
turns: r.turns,
|
|
54
|
+
files: r.files,
|
|
55
|
+
usage: r.usage,
|
|
56
|
+
...(r.error && { error: r.error }),
|
|
57
|
+
})),
|
|
58
|
+
};
|
|
59
|
+
return {
|
|
60
|
+
content: [{ type: 'text', text: JSON.stringify(response, null, 2) }],
|
|
61
|
+
};
|
|
62
|
+
});
|
|
63
|
+
return server;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* MCP CLI config discovery (owned by MCP, not core):
|
|
67
|
+
* 1. --config <path> argument (explicit)
|
|
68
|
+
* 2. MULTI_MODEL_CONFIG environment variable
|
|
69
|
+
* 3. ~/.multi-model/config.json (default home-directory location)
|
|
70
|
+
*/
|
|
71
|
+
export async function discoverConfig() {
|
|
72
|
+
const args = process.argv.slice(2);
|
|
73
|
+
// 1. Explicit --config
|
|
74
|
+
const configFlagIdx = args.indexOf('--config');
|
|
75
|
+
if (configFlagIdx >= 0 && args[configFlagIdx + 1]) {
|
|
76
|
+
return loadConfigFromFile(args[configFlagIdx + 1]);
|
|
77
|
+
}
|
|
78
|
+
// 2. MULTI_MODEL_CONFIG env var (file path)
|
|
79
|
+
const envPath = process.env.MULTI_MODEL_CONFIG;
|
|
80
|
+
if (envPath) {
|
|
81
|
+
return loadConfigFromFile(envPath);
|
|
82
|
+
}
|
|
83
|
+
// 3. ~/.multi-model/config.json
|
|
84
|
+
const defaultPath = path.join(os.homedir(), '.multi-model', 'config.json');
|
|
85
|
+
if (fs.existsSync(defaultPath)) {
|
|
86
|
+
return loadConfigFromFile(defaultPath);
|
|
87
|
+
}
|
|
88
|
+
// Fallback: empty config
|
|
89
|
+
return parseConfig({});
|
|
90
|
+
}
|
|
91
|
+
async function main() {
|
|
92
|
+
const args = process.argv.slice(2);
|
|
93
|
+
if (args[0] !== 'serve') {
|
|
94
|
+
console.error('Usage: multi-model-agent serve [--config <path>]');
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
const config = await discoverConfig();
|
|
98
|
+
const providerNames = Object.keys(config.providers);
|
|
99
|
+
if (providerNames.length === 0) {
|
|
100
|
+
console.error('No providers configured. Create ~/.multi-model/config.json or pass --config <path>.');
|
|
101
|
+
process.exit(1);
|
|
102
|
+
}
|
|
103
|
+
const server = buildMcpServer(config);
|
|
104
|
+
const transport = new StdioServerTransport();
|
|
105
|
+
await server.connect(transport);
|
|
106
|
+
}
|
|
107
|
+
// Only run main when executed directly
|
|
108
|
+
const thisFile = fileURLToPath(import.meta.url);
|
|
109
|
+
const isDirectRun = (() => {
|
|
110
|
+
if (!process.argv[1])
|
|
111
|
+
return false;
|
|
112
|
+
try {
|
|
113
|
+
return fs.realpathSync(process.argv[1]) === fs.realpathSync(thisFile);
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
})();
|
|
119
|
+
if (isDirectRun) {
|
|
120
|
+
main().catch((err) => {
|
|
121
|
+
console.error('Fatal:', err);
|
|
122
|
+
process.exit(1);
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { MultiModelConfig } from '@zhixuan92/multi-model-agent-core';
|
|
2
|
+
/**
|
|
3
|
+
* Renders the full routing matrix for the MCP tool description.
|
|
4
|
+
* Helps the consuming LLM understand provider capabilities and routing rules.
|
|
5
|
+
*/
|
|
6
|
+
export declare function renderProviderRoutingMatrix(config: MultiModelConfig): string;
|
|
7
|
+
//# sourceMappingURL=render-provider-routing-matrix.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-provider-routing-matrix.d.ts","sourceRoot":"","sources":["../../src/routing/render-provider-routing-matrix.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAc,gBAAgB,EAAkB,MAAM,mCAAmC,CAAC;AAmDtG;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAkB5E"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { getBaseCapabilities } from '@zhixuan92/multi-model-agent-core/routing/capabilities';
|
|
2
|
+
import { findModelProfile, getEffectiveCostTier } from '@zhixuan92/multi-model-agent-core/routing/model-profiles';
|
|
3
|
+
const ROUTING_RECIPE = `How to route a task:
|
|
4
|
+
1. Capability filter (HARD): exclude providers missing any required capability.
|
|
5
|
+
2. Quality filter: exclude providers whose tier is below the task's tier.
|
|
6
|
+
Tier ordering: trivial < standard < reasoning.
|
|
7
|
+
3. Cost preference (STRONG): among the remainder, prefer the cheapest tier.
|
|
8
|
+
If a 'free' provider qualifies, pick it. Only escalate to paid tiers when
|
|
9
|
+
the task tier or required capabilities demand it.
|
|
10
|
+
|
|
11
|
+
Tier guidance for the consumer LLM:
|
|
12
|
+
- 'trivial' — well-defined edits, lookups, formatting. One obvious answer.
|
|
13
|
+
- 'standard' — most code work. Clear spec, multiple valid approaches.
|
|
14
|
+
- 'reasoning' — ambiguous, architectural, research, or high-stakes.
|
|
15
|
+
Use when requirements are unclear or judgment is required.
|
|
16
|
+
|
|
17
|
+
Optional 'effort' knob (per task):
|
|
18
|
+
- Only providers marked 'effort: supported' in the matrix honor this field.
|
|
19
|
+
- Use 'high' for reasoning-tier tasks when you want maximum depth,
|
|
20
|
+
'medium' for balanced, 'low' for fast-but-shallow, 'none' to disable
|
|
21
|
+
thinking entirely on providers that default it on. Omit the field on
|
|
22
|
+
providers that do not support it.`;
|
|
23
|
+
function renderProviderBlock(name, config, capabilities, profile, costSource) {
|
|
24
|
+
const cost = getEffectiveCostTier(config);
|
|
25
|
+
const costSuffix = costSource === 'config' ? ' (from config)' : '';
|
|
26
|
+
const effortLabel = profile.supportsEffort ? 'supported' : 'not supported';
|
|
27
|
+
const lines = [
|
|
28
|
+
`${name} (${config.model})`,
|
|
29
|
+
` tools: ${capabilities.join(', ')}`,
|
|
30
|
+
` tier: ${profile.tier} | cost: ${cost}${costSuffix} | effort: ${effortLabel}`,
|
|
31
|
+
` best for: ${profile.bestFor}`,
|
|
32
|
+
];
|
|
33
|
+
if (profile.notes) {
|
|
34
|
+
lines.push(` note: ${profile.notes}`);
|
|
35
|
+
}
|
|
36
|
+
if (profile.avoidFor) {
|
|
37
|
+
lines.push(` avoid for: ${profile.avoidFor}`);
|
|
38
|
+
}
|
|
39
|
+
return lines.join('\n');
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Renders the full routing matrix for the MCP tool description.
|
|
43
|
+
* Helps the consuming LLM understand provider capabilities and routing rules.
|
|
44
|
+
*/
|
|
45
|
+
export function renderProviderRoutingMatrix(config) {
|
|
46
|
+
const blocks = Object.entries(config.providers).map(([name, providerConfig]) => {
|
|
47
|
+
const capabilities = getBaseCapabilities(providerConfig);
|
|
48
|
+
const profile = findModelProfile(providerConfig.model);
|
|
49
|
+
const costSource = providerConfig.costTier ? 'config' : 'default';
|
|
50
|
+
return renderProviderBlock(name, providerConfig, capabilities, profile, costSource);
|
|
51
|
+
});
|
|
52
|
+
return [
|
|
53
|
+
'Delegate tasks to sub-agents running on different LLM providers.',
|
|
54
|
+
'All tasks execute concurrently.',
|
|
55
|
+
'',
|
|
56
|
+
'Available providers:',
|
|
57
|
+
'',
|
|
58
|
+
blocks.join('\n\n'),
|
|
59
|
+
'',
|
|
60
|
+
ROUTING_RECIPE,
|
|
61
|
+
].join('\n');
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=render-provider-routing-matrix.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-provider-routing-matrix.js","sourceRoot":"","sources":["../../src/routing/render-provider-routing-matrix.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,wDAAwD,CAAC;AAC7F,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,0DAA0D,CAAC;AAGlH,MAAM,cAAc,GAAG;;;;;;;;;;;;;;;;;;;oCAmBa,CAAC;AAErC,SAAS,mBAAmB,CAC1B,IAAY,EACZ,MAAsB,EACtB,YAA0B,EAC1B,OAAqB,EACrB,UAAgC;IAEhC,MAAM,IAAI,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAC1C,MAAM,UAAU,GAAG,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC;IACnE,MAAM,WAAW,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,eAAe,CAAC;IAC3E,MAAM,KAAK,GAAG;QACZ,GAAG,IAAI,KAAK,MAAM,CAAC,KAAK,GAAG;QAC3B,YAAY,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;QACrC,WAAW,OAAO,CAAC,IAAI,YAAY,IAAI,GAAG,UAAU,cAAc,WAAW,EAAE;QAC/E,eAAe,OAAO,CAAC,OAAO,EAAE;KACjC,CAAC;IACF,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,KAAK,CAAC,IAAI,CAAC,WAAW,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;IACzC,CAAC;IACD,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QACrB,KAAK,CAAC,IAAI,CAAC,gBAAgB,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IACjD,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,2BAA2B,CAAC,MAAwB;IAClE,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,cAAc,CAAC,EAAE,EAAE;QAC7E,MAAM,YAAY,GAAG,mBAAmB,CAAC,cAAc,CAAC,CAAC;QACzD,MAAM,OAAO,GAAG,gBAAgB,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QACvD,MAAM,UAAU,GAAyB,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;QACxF,OAAO,mBAAmB,CAAC,IAAI,EAAE,cAAc,EAAE,YAAY,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;IACtF,CAAC,CAAC,CAAC;IAEH,OAAO;QACL,kEAAkE;QAClE,iCAAiC;QACjC,EAAE;QACF,sBAAsB;QACtB,EAAE;QACF,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;QACnB,EAAE;QACF,cAAc;KACf,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@zhixuan92/multi-model-agent-mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"description": "MCP server for multi-model-agent. Exposes a delegate_tasks tool that routes work to Claude, Codex, or OpenAI-compatible sub-agents based on capability, quality tier, and cost.",
|
|
7
|
+
"author": "Zhang Zhixuan <zhangzhixuan312@gmail.com>",
|
|
8
|
+
"keywords": [
|
|
9
|
+
"mcp",
|
|
10
|
+
"model-context-protocol",
|
|
11
|
+
"llm",
|
|
12
|
+
"claude",
|
|
13
|
+
"codex",
|
|
14
|
+
"openai",
|
|
15
|
+
"agent",
|
|
16
|
+
"multi-model",
|
|
17
|
+
"delegation"
|
|
18
|
+
],
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "git+https://github.com/zhixuan312/multi-model-agent.git",
|
|
22
|
+
"directory": "packages/mcp"
|
|
23
|
+
},
|
|
24
|
+
"homepage": "https://github.com/zhixuan312/multi-model-agent#readme",
|
|
25
|
+
"bugs": "https://github.com/zhixuan312/multi-model-agent/issues",
|
|
26
|
+
"files": ["dist"],
|
|
27
|
+
"main": "./dist/index.js",
|
|
28
|
+
"types": "./dist/index.d.ts",
|
|
29
|
+
"bin": {
|
|
30
|
+
"multi-model-agent": "./dist/cli.js"
|
|
31
|
+
},
|
|
32
|
+
"exports": {
|
|
33
|
+
".": {
|
|
34
|
+
"types": "./dist/index.d.ts",
|
|
35
|
+
"import": "./dist/index.js"
|
|
36
|
+
},
|
|
37
|
+
"./routing/render-provider-routing-matrix": {
|
|
38
|
+
"types": "./dist/routing/render-provider-routing-matrix.d.ts",
|
|
39
|
+
"import": "./dist/routing/render-provider-routing-matrix.js"
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"scripts": {
|
|
43
|
+
"build": "tsc"
|
|
44
|
+
},
|
|
45
|
+
"engines": { "node": ">=22.0.0" },
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"@zhixuan92/multi-model-agent-core": "^0.1.0",
|
|
48
|
+
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
49
|
+
"zod": "^4.0.0"
|
|
50
|
+
},
|
|
51
|
+
"peerDependencies": {
|
|
52
|
+
"@openai/agents": "^0.8.0",
|
|
53
|
+
"openai": "^6.0.0"
|
|
54
|
+
},
|
|
55
|
+
"peerDependenciesMeta": {
|
|
56
|
+
"@openai/agents": { "optional": true },
|
|
57
|
+
"openai": { "optional": true }
|
|
58
|
+
}
|
|
59
|
+
}
|