@osanoai/multicli 1.5.6 → 1.5.8
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 +13 -13
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +1 -1
- package/dist/index.js +51 -47
- package/dist/index.js.map +1 -1
- package/dist/modelCatalog.generated.json +15 -7
- package/dist/modelCatalog.js +3 -3
- package/dist/tierConfig.js +3 -3
- package/dist/tools/ask-claude.tool.js +3 -3
- package/dist/tools/ask-codex.tool.js +3 -3
- package/dist/tools/ask-gemini.tool.js +3 -3
- package/dist/tools/fetch-chunk.tool.js +2 -2
- package/dist/tools/important-read-now.tool.js +1 -1
- package/dist/tools/index.js +7 -7
- package/dist/tools/simple-tools.js +9 -9
- package/dist/utils/commandExecutor.d.ts +8 -0
- package/dist/utils/commandExecutor.d.ts.map +1 -1
- package/dist/utils/commandExecutor.js +18 -2
- package/dist/utils/commandExecutor.js.map +1 -1
- package/package.json +1 -5
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Multi-CLI MCP
|
|
2
2
|
|
|
3
|
-
[](https://www.npmjs.com/package/@osanoai/multicli)
|
|
4
4
|
[](https://github.com/osanoai/multicli/actions/workflows/tests.yml)
|
|
5
5
|
[](https://github.com/osanoai/multicli/actions/workflows/scan.yml)
|
|
6
6
|
[](https://github.com/osanoai/multicli/releases/latest)
|
|
@@ -72,7 +72,7 @@ Prefer to install per-client yourself? Each command is one line.
|
|
|
72
72
|
### Claude Code
|
|
73
73
|
|
|
74
74
|
```bash
|
|
75
|
-
claude mcp add Multi-CLI -- npx -y @osanoai/multicli@latest
|
|
75
|
+
claude mcp add --scope user Multi-CLI -- npx -y @osanoai/multicli@latest
|
|
76
76
|
```
|
|
77
77
|
|
|
78
78
|
<details>
|
|
@@ -164,16 +164,16 @@ Once connected, your AI client gains access to tools for the *other* CLIs (never
|
|
|
164
164
|
|
|
165
165
|
| Tool | Description |
|
|
166
166
|
|------|-------------|
|
|
167
|
-
| `List
|
|
168
|
-
| `Ask
|
|
169
|
-
| `Fetch
|
|
170
|
-
| `Gemini
|
|
171
|
-
| `List
|
|
172
|
-
| `Ask
|
|
173
|
-
| `Codex
|
|
174
|
-
| `List
|
|
175
|
-
| `Ask
|
|
176
|
-
| `Claude
|
|
167
|
+
| `List-Gemini-Models` | List available Gemini models and their strengths |
|
|
168
|
+
| `Ask-Gemini` | Ask-Gemini a question or give it a task |
|
|
169
|
+
| `Fetch-Chunk` | Retrieve chunked responses from Gemini |
|
|
170
|
+
| `Gemini-Help` | Get Gemini CLI help info |
|
|
171
|
+
| `List-Codex-Models` | List available Codex models |
|
|
172
|
+
| `Ask-Codex` | Ask-Codex a question or give it a task |
|
|
173
|
+
| `Codex-Help` | Get Codex CLI help info |
|
|
174
|
+
| `List-Claude-Models` | List available Claude models |
|
|
175
|
+
| `Ask-Claude` | Ask-Claude a question or give it a task |
|
|
176
|
+
| `Claude-Help` | Get Claude Code CLI help info |
|
|
177
177
|
|
|
178
178
|
---
|
|
179
179
|
|
|
@@ -182,7 +182,7 @@ Once connected, your AI client gains access to tools for the *other* CLIs (never
|
|
|
182
182
|
Once installed, just talk naturally to your AI:
|
|
183
183
|
|
|
184
184
|
```
|
|
185
|
-
"Ask
|
|
185
|
+
"Ask-Gemini what it thinks about this architecture"
|
|
186
186
|
"Have Codex review this function for performance issues"
|
|
187
187
|
"Get Claude's opinion on this error message"
|
|
188
188
|
"Use Gemini to analyze @largefile.js"
|
package/dist/constants.d.ts
CHANGED
package/dist/constants.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -21,9 +21,6 @@ server.oninitialized = () => {
|
|
|
21
21
|
const clientInfo = server.getClientVersion();
|
|
22
22
|
connectedClientName = clientInfo?.name;
|
|
23
23
|
};
|
|
24
|
-
let isProcessing = false;
|
|
25
|
-
let currentOperationName = "";
|
|
26
|
-
let latestOutput = "";
|
|
27
24
|
/**
|
|
28
25
|
* @param progressToken The progress token provided by the client
|
|
29
26
|
* @param progress The current progress value
|
|
@@ -31,7 +28,7 @@ let latestOutput = "";
|
|
|
31
28
|
* @param message Optional status message
|
|
32
29
|
*/
|
|
33
30
|
async function sendProgressNotification(progressToken, progress, total, message) {
|
|
34
|
-
if (
|
|
31
|
+
if (progressToken === undefined || progressToken === null)
|
|
35
32
|
return; // Only send if client requested progress
|
|
36
33
|
try {
|
|
37
34
|
const params = {
|
|
@@ -51,53 +48,62 @@ async function sendProgressNotification(progressToken, progress, total, message)
|
|
|
51
48
|
// progress notification errors are non-critical
|
|
52
49
|
}
|
|
53
50
|
}
|
|
54
|
-
function startProgressUpdates(operationName, progressToken) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
51
|
+
async function startProgressUpdates(operationName, progressToken) {
|
|
52
|
+
const progressData = {
|
|
53
|
+
operationName,
|
|
54
|
+
progressToken,
|
|
55
|
+
completed: false
|
|
56
|
+
};
|
|
57
|
+
// If no progress token provided, return minimal data without starting a loop
|
|
58
|
+
if (progressToken === undefined || progressToken === null) {
|
|
59
|
+
return progressData;
|
|
60
|
+
}
|
|
58
61
|
const progressMessages = [
|
|
59
|
-
`🧠 ${operationName} -
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
`🧠 ${operationName} - Thinking through your request...`,
|
|
63
|
+
`🔍 ${operationName} - Analyzing context and gathering details...`,
|
|
64
|
+
`⚙️ ${operationName} - Processing data and generating insights...`,
|
|
65
|
+
`📝 ${operationName} - Formulating a comprehensive response...`,
|
|
66
|
+
`⏱️ ${operationName} - Large task in progress (this is normal)...`,
|
|
67
|
+
`✨ ${operationName} - Refining results for accuracy...`,
|
|
68
|
+
`📊 ${operationName} - Structuring final output...`,
|
|
69
|
+
`📡 ${operationName} - Almost there, finalizing the response...`,
|
|
70
|
+
`🦾 ${operationName} - Still working hard on this...`,
|
|
71
|
+
`🔄 ${operationName} - Continuing to process...`,
|
|
64
72
|
];
|
|
65
73
|
let messageIndex = 0;
|
|
66
74
|
let progress = 0;
|
|
67
|
-
// Send immediate acknowledgment
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
+
// Send immediate acknowledgment and wait for it to ensure correct ordering
|
|
76
|
+
await sendProgressNotification(progressToken, 0, undefined, // No total - indeterminate progress
|
|
77
|
+
`🔍 Starting ${operationName}`);
|
|
78
|
+
// Self-scheduling loop instead of setInterval to prevent overlap and races
|
|
79
|
+
const scheduleNext = () => {
|
|
80
|
+
progressData.timeout = setTimeout(async () => {
|
|
81
|
+
if (progressData.completed)
|
|
82
|
+
return;
|
|
75
83
|
// Simply increment progress value
|
|
76
84
|
progress += 1;
|
|
77
|
-
//
|
|
78
|
-
const
|
|
79
|
-
const outputPreview = latestOutput.slice(-150).trim(); // Last 150 chars
|
|
80
|
-
const message = outputPreview
|
|
81
|
-
? `${baseMessage}\n📝 Output: ...${outputPreview}`
|
|
82
|
-
: baseMessage;
|
|
85
|
+
// Use standard progress message from rotation
|
|
86
|
+
const message = progressMessages[messageIndex % progressMessages.length];
|
|
83
87
|
await sendProgressNotification(progressToken, progress, undefined, // No total - indeterminate progress
|
|
84
88
|
message);
|
|
85
89
|
messageIndex++;
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
90
|
+
// Schedule next tick only after this one is done
|
|
91
|
+
if (!progressData.completed) {
|
|
92
|
+
scheduleNext();
|
|
93
|
+
}
|
|
94
|
+
}, PROTOCOL.KEEPALIVE_INTERVAL); // Every 10 seconds
|
|
95
|
+
};
|
|
96
|
+
scheduleNext();
|
|
97
|
+
return progressData;
|
|
92
98
|
}
|
|
93
|
-
function stopProgressUpdates(progressData, success = true) {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
99
|
+
async function stopProgressUpdates(progressData, success = true) {
|
|
100
|
+
progressData.completed = true;
|
|
101
|
+
if (progressData.timeout) {
|
|
102
|
+
clearTimeout(progressData.timeout);
|
|
103
|
+
}
|
|
98
104
|
// Send final progress notification if client requested progress
|
|
99
|
-
if (progressData.progressToken) {
|
|
100
|
-
sendProgressNotification(progressData.progressToken, 100, 100, success ? `✅ ${operationName} completed successfully` : `❌ ${operationName} failed`);
|
|
105
|
+
if (progressData.progressToken !== undefined && progressData.progressToken !== null) {
|
|
106
|
+
await sendProgressNotification(progressData.progressToken, 100, 100, success ? `✅ ${progressData.operationName} completed successfully` : `❌ ${progressData.operationName} failed`);
|
|
101
107
|
}
|
|
102
108
|
}
|
|
103
109
|
// tools/list
|
|
@@ -127,16 +133,14 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
127
133
|
// Check if client requested progress updates
|
|
128
134
|
const progressToken = request.params._meta?.progressToken;
|
|
129
135
|
// Start progress updates if client requested them
|
|
130
|
-
const progressData = startProgressUpdates(toolName, progressToken);
|
|
136
|
+
const progressData = await startProgressUpdates(toolName, progressToken);
|
|
131
137
|
try {
|
|
132
138
|
// Get prompt and other parameters from arguments with proper typing
|
|
133
139
|
const args = request.params.arguments || {};
|
|
134
|
-
// Execute the tool using the unified registry
|
|
135
|
-
const result = await executeTool(toolName, args
|
|
136
|
-
latestOutput = newOutput;
|
|
137
|
-
});
|
|
140
|
+
// Execute the tool using the unified registry
|
|
141
|
+
const result = await executeTool(toolName, args);
|
|
138
142
|
// Stop progress updates
|
|
139
|
-
stopProgressUpdates(progressData, true);
|
|
143
|
+
await stopProgressUpdates(progressData, true);
|
|
140
144
|
return {
|
|
141
145
|
content: [
|
|
142
146
|
{
|
|
@@ -149,7 +153,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
149
153
|
}
|
|
150
154
|
catch (error) {
|
|
151
155
|
// Stop progress updates on error
|
|
152
|
-
stopProgressUpdates(progressData, false);
|
|
156
|
+
await stopProgressUpdates(progressData, false);
|
|
153
157
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
154
158
|
return {
|
|
155
159
|
content: [
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,eAAe,CAAC;AAEvB,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,wBAAwB,EACxB,sBAAsB,GASvB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAiB,MAAM,gBAAgB,CAAC;AAEzD,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,WAAW,EACX,UAAU,EACV,gBAAgB,EAChB,YAAY,EACZ,SAAS,GACV,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAC1E,OAAO,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAEjF,MAAM,MAAM,GAAG,IAAI,MAAM,CACvB;IACE,IAAI,EAAE,WAAW;IACjB,OAAO,EAAE,OAAO;CACjB,EAAC;IACA,YAAY,EAAE;QACZ,KAAK,EAAE,EAAE;QACT,OAAO,EAAE,EAAE;KACZ;CACF,CACF,CAAC;AAEF,IAAI,mBAAuC,CAAC;AAE5C,MAAM,CAAC,aAAa,GAAG,GAAG,EAAE;IAC1B,MAAM,UAAU,GAAG,MAAM,CAAC,gBAAgB,EAAE,CAAC;IAC7C,mBAAmB,GAAG,UAAU,EAAE,IAAI,CAAC;AACzC,CAAC,CAAC;AAEF
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"generatedAt": "2026-03-
|
|
2
|
+
"generatedAt": "2026-03-06T04:31:11.325Z",
|
|
3
3
|
"catalogs": {
|
|
4
4
|
"claude": {
|
|
5
5
|
"cli": "claude",
|
|
@@ -7,12 +7,13 @@
|
|
|
7
7
|
{
|
|
8
8
|
"tier": "fast",
|
|
9
9
|
"models": [
|
|
10
|
-
"claude-haiku-4-5
|
|
10
|
+
"claude-haiku-4-5"
|
|
11
11
|
]
|
|
12
12
|
},
|
|
13
13
|
{
|
|
14
14
|
"tier": "balanced",
|
|
15
15
|
"models": [
|
|
16
|
+
"claude-sonnet-4-5",
|
|
16
17
|
"claude-sonnet-4-6"
|
|
17
18
|
]
|
|
18
19
|
},
|
|
@@ -37,14 +38,15 @@
|
|
|
37
38
|
{
|
|
38
39
|
"tier": "balanced",
|
|
39
40
|
"models": [
|
|
41
|
+
"gemini-2.5-pro",
|
|
40
42
|
"gemini-3-flash-preview"
|
|
41
43
|
]
|
|
42
44
|
},
|
|
43
45
|
{
|
|
44
46
|
"tier": "powerful",
|
|
45
47
|
"models": [
|
|
46
|
-
"gemini-3
|
|
47
|
-
"gemini-
|
|
48
|
+
"gemini-3-pro-preview",
|
|
49
|
+
"gemini-3.1-pro-preview"
|
|
48
50
|
]
|
|
49
51
|
}
|
|
50
52
|
]
|
|
@@ -55,21 +57,27 @@
|
|
|
55
57
|
{
|
|
56
58
|
"tier": "fast",
|
|
57
59
|
"models": [
|
|
60
|
+
"gpt-5-codex-mini",
|
|
58
61
|
"gpt-5.1-codex-mini"
|
|
59
62
|
]
|
|
60
63
|
},
|
|
61
64
|
{
|
|
62
65
|
"tier": "balanced",
|
|
63
66
|
"models": [
|
|
64
|
-
"gpt-5
|
|
67
|
+
"gpt-5",
|
|
68
|
+
"gpt-5-codex",
|
|
69
|
+
"gpt-5.1",
|
|
70
|
+
"gpt-5.1-codex",
|
|
71
|
+
"gpt-5.2",
|
|
72
|
+
"gpt-5.2-codex",
|
|
73
|
+
"gpt-5.3-codex"
|
|
65
74
|
]
|
|
66
75
|
},
|
|
67
76
|
{
|
|
68
77
|
"tier": "powerful",
|
|
69
78
|
"models": [
|
|
70
|
-
"gpt-5.3-codex",
|
|
71
79
|
"gpt-5.1-codex-max",
|
|
72
|
-
"gpt-5.
|
|
80
|
+
"gpt-5.4"
|
|
73
81
|
]
|
|
74
82
|
}
|
|
75
83
|
]
|
package/dist/modelCatalog.js
CHANGED
|
@@ -32,7 +32,7 @@ const FALLBACK_CATALOGS = {
|
|
|
32
32
|
useWhen: 'ONLY for: complex analysis, deep reasoning, large codebase understanding, nuanced opinions, architectural decisions.',
|
|
33
33
|
},
|
|
34
34
|
],
|
|
35
|
-
note: 'Run Gemini
|
|
35
|
+
note: 'Run Gemini-Help for the latest CLI options. Model IDs may change as Google releases new versions.',
|
|
36
36
|
},
|
|
37
37
|
codex: {
|
|
38
38
|
cli: 'codex',
|
|
@@ -56,7 +56,7 @@ const FALLBACK_CATALOGS = {
|
|
|
56
56
|
useWhen: 'ONLY for: complex architecture, large refactors, deep reasoning, nuanced analysis, multi-step planning.',
|
|
57
57
|
},
|
|
58
58
|
],
|
|
59
|
-
note: 'Run Codex
|
|
59
|
+
note: 'Run Codex-Help for the latest CLI options. Model IDs may change as OpenAI releases new versions.',
|
|
60
60
|
},
|
|
61
61
|
claude: {
|
|
62
62
|
cli: 'claude',
|
|
@@ -80,7 +80,7 @@ const FALLBACK_CATALOGS = {
|
|
|
80
80
|
useWhen: 'ONLY for: complex reasoning, nuanced analysis, difficult multi-step tasks, architectural decisions.',
|
|
81
81
|
},
|
|
82
82
|
],
|
|
83
|
-
note: 'Run Claude
|
|
83
|
+
note: 'Run Claude-Help for the latest CLI options.',
|
|
84
84
|
},
|
|
85
85
|
};
|
|
86
86
|
// ── Build catalog from generated data ────────────────────────────────────────
|
package/dist/tierConfig.js
CHANGED
|
@@ -48,8 +48,8 @@ export const TIER_CONFIG = {
|
|
|
48
48
|
},
|
|
49
49
|
};
|
|
50
50
|
export const CLI_NOTES = {
|
|
51
|
-
claude: 'Run Claude
|
|
52
|
-
gemini: 'Run Gemini
|
|
53
|
-
codex: 'Run Codex
|
|
51
|
+
claude: 'Run Claude-Help for the latest CLI options.',
|
|
52
|
+
gemini: 'Run Gemini-Help for the latest CLI options. Model IDs may change as Google releases new versions.',
|
|
53
|
+
codex: 'Run Codex-Help for the latest CLI options. Model IDs may change as OpenAI releases new versions.',
|
|
54
54
|
};
|
|
55
55
|
//# sourceMappingURL=tierConfig.js.map
|
|
@@ -3,14 +3,14 @@ import { executeClaudeCLI } from '../utils/claudeExecutor.js';
|
|
|
3
3
|
import { ERROR_MESSAGES, STATUS_MESSAGES } from '../constants.js';
|
|
4
4
|
const askClaudeArgsSchema = z.object({
|
|
5
5
|
prompt: z.string().min(1).describe("The question or task for Claude Code. REQUIRED — MUST be a non-empty string. Claude Code has FULL access to the filesystem and can read files itself. Do NOT pre-read or inline file contents — just describe the task and let Claude explore the codebase."),
|
|
6
|
-
model: z.string().min(1).describe("REQUIRED — you MUST first call List
|
|
6
|
+
model: z.string().min(1).describe("REQUIRED — you MUST first call List-Claude-Models, review the available model families and their strengths, then select the best model for your task's scope and complexity. It's the law. Empty strings will be rejected."),
|
|
7
7
|
permissionMode: z.enum(['default', 'acceptEdits', 'bypassPermissions', 'dontAsk', 'plan']).optional().describe("Optional. Do NOT set unless explicitly needed. Permission mode: 'default' (requires approval), 'acceptEdits' (auto-accepts file edits), 'bypassPermissions' (skips all checks — use with care), 'dontAsk', or 'plan'."),
|
|
8
8
|
maxBudgetUsd: z.number().positive().optional().describe("Optional. Do NOT set unless explicitly needed. Maximum dollar amount to spend on API calls for this request."),
|
|
9
9
|
systemPrompt: z.string().optional().describe("Optional. Do NOT set unless explicitly needed. Override or append a system prompt for this request."),
|
|
10
10
|
});
|
|
11
11
|
export const askClaudeTool = {
|
|
12
|
-
name: "Ask
|
|
13
|
-
description: "Ask Claude Code a question or give it a task. Claude Code has full filesystem access and will read files itself — do NOT pre-gather context or inline file contents into the prompt. Just describe what you need. You MUST call List
|
|
12
|
+
name: "Ask-Claude",
|
|
13
|
+
description: "Ask Claude Code a question or give it a task. Claude Code has full filesystem access and will read files itself — do NOT pre-gather context or inline file contents into the prompt. Just describe what you need. You MUST call List-Claude-Models first to select an appropriate model. Do NOT set optional parameters unless you have a specific reason.",
|
|
14
14
|
zodSchema: askClaudeArgsSchema,
|
|
15
15
|
prompt: {
|
|
16
16
|
description: "Execute 'claude --print <prompt>' to get Claude Code's response.",
|
|
@@ -3,13 +3,13 @@ import { executeCodexCLI } from '../utils/codexExecutor.js';
|
|
|
3
3
|
import { ERROR_MESSAGES, STATUS_MESSAGES } from '../constants.js';
|
|
4
4
|
const askCodexArgsSchema = z.object({
|
|
5
5
|
prompt: z.string().min(1).describe("The question or task for Codex. REQUIRED — MUST be a non-empty string. Codex has FULL access to the filesystem and can read files itself. Do NOT pre-read or inline file contents — just describe the task and let Codex explore the codebase."),
|
|
6
|
-
model: z.string().min(1).describe("REQUIRED — you MUST first call List
|
|
6
|
+
model: z.string().min(1).describe("REQUIRED — you MUST first call List-Codex-Models, review the available model families and their strengths, then select the best model for your task's scope and complexity. It's the law. Empty strings will be rejected."),
|
|
7
7
|
sandbox: z.enum(['read-only', 'workspace-write', 'danger-full-access']).optional().describe("Optional. Do NOT set unless explicitly needed. Sandbox mode: 'read-only' (safe), 'workspace-write' (default), or 'danger-full-access' (unrestricted)."),
|
|
8
8
|
approvalPolicy: z.enum(['never', 'on-request', 'on-failure', 'untrusted']).optional().describe("Optional. Do NOT set unless explicitly needed. Approval policy: 'never', 'on-request' (default), 'on-failure', or 'untrusted'."),
|
|
9
9
|
});
|
|
10
10
|
export const askCodexTool = {
|
|
11
|
-
name: "Ask
|
|
12
|
-
description: "Ask OpenAI Codex a question or give it a task. Codex has full filesystem access and will read files itself — do NOT pre-gather context or inline file contents into the prompt. Just describe what you need. You MUST call List
|
|
11
|
+
name: "Ask-Codex",
|
|
12
|
+
description: "Ask OpenAI Codex a question or give it a task. Codex has full filesystem access and will read files itself — do NOT pre-gather context or inline file contents into the prompt. Just describe what you need. You MUST call List-Codex-Models first to select an appropriate model. Do NOT set optional parameters unless you have a specific reason.",
|
|
13
13
|
zodSchema: askCodexArgsSchema,
|
|
14
14
|
prompt: {
|
|
15
15
|
description: "Execute 'codex exec <prompt> --full-auto' to get Codex's response.",
|
|
@@ -3,15 +3,15 @@ import { executeGeminiCLI, processChangeModeOutput } from '../utils/geminiExecut
|
|
|
3
3
|
import { ERROR_MESSAGES, STATUS_MESSAGES } from '../constants.js';
|
|
4
4
|
const askGeminiArgsSchema = z.object({
|
|
5
5
|
prompt: z.string().min(1).describe("The question or task for Gemini. REQUIRED — MUST be a non-empty string. Gemini has filesystem access — use @ syntax to reference files (e.g., '@src/index.ts review this'). Do NOT pre-read or inline file contents — just describe the task and reference files with @."),
|
|
6
|
-
model: z.string().min(1).describe("REQUIRED — you MUST first call List
|
|
6
|
+
model: z.string().min(1).describe("REQUIRED — you MUST first call List-Gemini-Models, review the available model families and their strengths, then select the best model for your task's scope and complexity. It's the law. Empty strings will be rejected."),
|
|
7
7
|
sandbox: z.boolean().default(false).describe("Optional. Do NOT set unless explicitly needed. Run in sandbox mode (-s flag) for safely testing code changes in an isolated environment. Defaults to false."),
|
|
8
8
|
changeMode: z.boolean().default(false).describe("Optional. Do NOT set unless explicitly needed. Return structured edit suggestions instead of plain text. Defaults to false."),
|
|
9
9
|
chunkIndex: z.union([z.number(), z.string()]).optional().describe("Internal — do NOT set unless you received a chunked changeMode response. Which chunk to return (1-based)."),
|
|
10
10
|
chunkCacheKey: z.string().optional().describe("Internal — do NOT set unless you received a chunked changeMode response. Cache key from a prior response for fetching subsequent chunks."),
|
|
11
11
|
});
|
|
12
12
|
export const askGeminiTool = {
|
|
13
|
-
name: "Ask
|
|
14
|
-
description: "Ask Google Gemini a question or give it a task. Gemini has filesystem access via @ syntax — do NOT pre-gather context or inline file contents into the prompt. Just describe what you need and use @file references. You MUST call List
|
|
13
|
+
name: "Ask-Gemini",
|
|
14
|
+
description: "Ask Google Gemini a question or give it a task. Gemini has filesystem access via @ syntax — do NOT pre-gather context or inline file contents into the prompt. Just describe what you need and use @file references. You MUST call List-Gemini-Models first to select an appropriate model. Do NOT set optional parameters unless you have a specific reason.",
|
|
15
15
|
zodSchema: askGeminiArgsSchema,
|
|
16
16
|
prompt: {
|
|
17
17
|
description: "Execute 'gemini <prompt>' to get Gemini AI's response. Supports enhanced change mode for structured edit suggestions.",
|
|
@@ -6,7 +6,7 @@ const inputSchema = z.object({
|
|
|
6
6
|
chunkIndex: z.number().min(1).describe("Which chunk to retrieve (1-based index)")
|
|
7
7
|
});
|
|
8
8
|
export const fetchChunkTool = {
|
|
9
|
-
name: 'Fetch
|
|
9
|
+
name: 'Fetch-Chunk',
|
|
10
10
|
description: 'Retrieves cached chunks from a Gemini changeMode response. Use this to get subsequent chunks after receiving a partial changeMode response.',
|
|
11
11
|
zodSchema: inputSchema,
|
|
12
12
|
prompt: {
|
|
@@ -28,7 +28,7 @@ export const fetchChunkTool = {
|
|
|
28
28
|
return `❌ Cache miss: No chunks found for cache key "${cacheKey}".
|
|
29
29
|
|
|
30
30
|
Possible reasons:
|
|
31
|
-
1. The cache key is incorrect, Have you ran Ask
|
|
31
|
+
1. The cache key is incorrect, Have you ran Ask-Gemini with changeMode enabled?
|
|
32
32
|
2. The cache has expired (10 minute TTL)
|
|
33
33
|
3. The MCP server was restarted and the file-based cache was cleared
|
|
34
34
|
|
|
@@ -20,7 +20,7 @@ To verify a CLI is available, run one of these commands in a terminal:
|
|
|
20
20
|
After installing a CLI, restart the MCP server to pick up the change.
|
|
21
21
|
`;
|
|
22
22
|
export const importantReadNowTool = {
|
|
23
|
-
name: "Claude
|
|
23
|
+
name: "Claude-Gemini-Codex",
|
|
24
24
|
description: "CRITICAL: No usable AI CLIs detected by Multi-CLI. Call this tool immediately for troubleshooting instructions.",
|
|
25
25
|
zodSchema: noArgsSchema,
|
|
26
26
|
category: 'utility',
|
package/dist/tools/index.js
CHANGED
|
@@ -13,19 +13,19 @@ import { detectAvailableClis } from '../utils/cliDetector.js';
|
|
|
13
13
|
export async function initTools() {
|
|
14
14
|
const availability = await detectAvailableClis();
|
|
15
15
|
if (availability.gemini) {
|
|
16
|
-
toolRegistry.push(geminiListModelsTool, // List
|
|
17
|
-
askGeminiTool, // Ask
|
|
18
|
-
fetchChunkTool, // Fetch
|
|
16
|
+
toolRegistry.push(geminiListModelsTool, // List-Gemini-Models
|
|
17
|
+
askGeminiTool, // Ask-Gemini
|
|
18
|
+
fetchChunkTool, // Fetch-Chunk
|
|
19
19
|
geminiHelpTool);
|
|
20
20
|
}
|
|
21
21
|
if (availability.codex) {
|
|
22
|
-
toolRegistry.push(codexListModelsTool, // List
|
|
23
|
-
askCodexTool, // Ask
|
|
22
|
+
toolRegistry.push(codexListModelsTool, // List-Codex-Models
|
|
23
|
+
askCodexTool, // Ask-Codex
|
|
24
24
|
codexHelpTool);
|
|
25
25
|
}
|
|
26
26
|
if (availability.claude) {
|
|
27
|
-
toolRegistry.push(claudeListModelsTool, // List
|
|
28
|
-
askClaudeTool, // Ask
|
|
27
|
+
toolRegistry.push(claudeListModelsTool, // List-Claude-Models
|
|
28
|
+
askClaudeTool, // Ask-Claude
|
|
29
29
|
claudeHelpTool);
|
|
30
30
|
}
|
|
31
31
|
return availability;
|
|
@@ -3,7 +3,7 @@ import { executeCommand } from '../utils/commandExecutor.js';
|
|
|
3
3
|
import { formatCatalog } from '../modelCatalog.js';
|
|
4
4
|
const helpArgsSchema = z.object({});
|
|
5
5
|
export const geminiHelpTool = {
|
|
6
|
-
name: "Gemini
|
|
6
|
+
name: "Gemini-Help",
|
|
7
7
|
description: "Receive help information from the Gemini CLI",
|
|
8
8
|
zodSchema: helpArgsSchema,
|
|
9
9
|
prompt: {
|
|
@@ -15,7 +15,7 @@ export const geminiHelpTool = {
|
|
|
15
15
|
}
|
|
16
16
|
};
|
|
17
17
|
export const codexHelpTool = {
|
|
18
|
-
name: "Codex
|
|
18
|
+
name: "Codex-Help",
|
|
19
19
|
description: "Receive help information from the Codex CLI",
|
|
20
20
|
zodSchema: helpArgsSchema,
|
|
21
21
|
prompt: {
|
|
@@ -27,7 +27,7 @@ export const codexHelpTool = {
|
|
|
27
27
|
}
|
|
28
28
|
};
|
|
29
29
|
export const claudeHelpTool = {
|
|
30
|
-
name: "Claude
|
|
30
|
+
name: "Claude-Help",
|
|
31
31
|
description: "Receive help information from the Claude Code CLI",
|
|
32
32
|
zodSchema: helpArgsSchema,
|
|
33
33
|
prompt: {
|
|
@@ -40,8 +40,8 @@ export const claudeHelpTool = {
|
|
|
40
40
|
};
|
|
41
41
|
const noArgsSchema = z.object({});
|
|
42
42
|
export const geminiListModelsTool = {
|
|
43
|
-
name: "List
|
|
44
|
-
description: "List available Gemini model families, their strengths, and known model IDs. You MUST call this before Ask
|
|
43
|
+
name: "List-Gemini-Models",
|
|
44
|
+
description: "List available Gemini model families, their strengths, and known model IDs. You MUST call this before Ask-Gemini to choose the right model for your task. It's the law.",
|
|
45
45
|
zodSchema: noArgsSchema,
|
|
46
46
|
prompt: {
|
|
47
47
|
description: "List available Gemini models with family descriptions",
|
|
@@ -52,8 +52,8 @@ export const geminiListModelsTool = {
|
|
|
52
52
|
}
|
|
53
53
|
};
|
|
54
54
|
export const codexListModelsTool = {
|
|
55
|
-
name: "List
|
|
56
|
-
description: "List available Codex model families, their strengths, and known model IDs. You MUST call this before Ask
|
|
55
|
+
name: "List-Codex-Models",
|
|
56
|
+
description: "List available Codex model families, their strengths, and known model IDs. You MUST call this before Ask-Codex to choose the right model for your task. It's the law.",
|
|
57
57
|
zodSchema: noArgsSchema,
|
|
58
58
|
prompt: {
|
|
59
59
|
description: "List available Codex models with family descriptions",
|
|
@@ -64,8 +64,8 @@ export const codexListModelsTool = {
|
|
|
64
64
|
}
|
|
65
65
|
};
|
|
66
66
|
export const claudeListModelsTool = {
|
|
67
|
-
name: "List
|
|
68
|
-
description: "List available Claude model families, their strengths, and known model IDs. You MUST call this before Ask
|
|
67
|
+
name: "List-Claude-Models",
|
|
68
|
+
description: "List available Claude model families, their strengths, and known model IDs. You MUST call this before Ask-Claude to choose the right model for your task. It's the law.",
|
|
69
69
|
zodSchema: noArgsSchema,
|
|
70
70
|
prompt: {
|
|
71
71
|
description: "List available Claude models with family descriptions",
|
|
@@ -1,2 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sanitize a single argument for safe use with cmd.exe (shell: true on Windows).
|
|
3
|
+
* Uses correct cmd.exe escaping conventions:
|
|
4
|
+
* - `""` for literal double quotes (cmd.exe convention, not `\"`)
|
|
5
|
+
* - `%%` for literal percent signs (prevents env variable expansion)
|
|
6
|
+
* - `^` prefix for cmd.exe operators: & | < > ^
|
|
7
|
+
*/
|
|
8
|
+
export declare function sanitizeArgForCmd(arg: string): string;
|
|
1
9
|
export declare function executeCommand(command: string, args: string[], onProgress?: (newOutput: string) => void): Promise<string>;
|
|
2
10
|
//# sourceMappingURL=commandExecutor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commandExecutor.d.ts","sourceRoot":"","sources":["../../src/utils/commandExecutor.ts"],"names":[],"mappings":"AAKA,wBAAsB,cAAc,CAClC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,GACvC,OAAO,CAAC,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"commandExecutor.d.ts","sourceRoot":"","sources":["../../src/utils/commandExecutor.ts"],"names":[],"mappings":"AAKA;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAMrD;AAED,wBAAsB,cAAc,CAClC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,GACvC,OAAO,CAAC,MAAM,CAAC,CAwDjB"}
|
|
@@ -1,10 +1,26 @@
|
|
|
1
1
|
import { spawn } from "child_process";
|
|
2
2
|
// Detect Windows platform for shell compatibility
|
|
3
3
|
const isWindows = process.platform === "win32";
|
|
4
|
+
/**
|
|
5
|
+
* Sanitize a single argument for safe use with cmd.exe (shell: true on Windows).
|
|
6
|
+
* Uses correct cmd.exe escaping conventions:
|
|
7
|
+
* - `""` for literal double quotes (cmd.exe convention, not `\"`)
|
|
8
|
+
* - `%%` for literal percent signs (prevents env variable expansion)
|
|
9
|
+
* - `^` prefix for cmd.exe operators: & | < > ^
|
|
10
|
+
*/
|
|
11
|
+
export function sanitizeArgForCmd(arg) {
|
|
12
|
+
return arg
|
|
13
|
+
.replace(/"/g, '""') // cmd.exe double-quote escaping
|
|
14
|
+
.replace(/%/g, '%%') // prevent %VAR% expansion
|
|
15
|
+
.replace(/[&|<>^]/g, c => `^${c}`) // caret-escape shell operators
|
|
16
|
+
;
|
|
17
|
+
}
|
|
4
18
|
export async function executeCommand(command, args, onProgress) {
|
|
5
19
|
return new Promise((resolve, reject) => {
|
|
6
|
-
// Use shell: true on Windows to properly execute .cmd files and resolve PATH
|
|
7
|
-
|
|
20
|
+
// Use shell: true on Windows to properly execute .cmd files and resolve PATH.
|
|
21
|
+
// Sanitize args to prevent cmd.exe metacharacter injection.
|
|
22
|
+
const safeArgs = isWindows ? args.map(sanitizeArgForCmd) : args;
|
|
23
|
+
const childProcess = spawn(command, safeArgs, {
|
|
8
24
|
env: process.env,
|
|
9
25
|
shell: isWindows,
|
|
10
26
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commandExecutor.js","sourceRoot":"","sources":["../../src/utils/commandExecutor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAEtC,kDAAkD;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC;AAE/C,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,OAAe,EACf,IAAc,EACd,UAAwC;IAExC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,
|
|
1
|
+
{"version":3,"file":"commandExecutor.js","sourceRoot":"","sources":["../../src/utils/commandExecutor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAEtC,kDAAkD;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC;AAE/C;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC3C,OAAO,GAAG;SACP,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAe,gCAAgC;SAClE,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAe,0BAA0B;SAC5D,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,+BAA+B;KACnE;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,OAAe,EACf,IAAc,EACd,UAAwC;IAExC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,8EAA8E;QAC9E,4DAA4D;QAC5D,MAAM,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAChE,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,EAAE,QAAQ,EAAE;YAC5C,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,KAAK,EAAE,SAAS;YAChB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;SAClC,CAAC,CAAC;QAEH,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,UAAU,GAAG,KAAK,CAAC;QACvB,IAAI,kBAAkB,GAAG,CAAC,CAAC;QAE3B,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;YACtC,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAE1B,0CAA0C;YAC1C,IAAI,UAAU,IAAI,MAAM,CAAC,MAAM,GAAG,kBAAkB,EAAE,CAAC;gBACrD,MAAM,UAAU,GAAG,MAAM,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC;gBACxD,kBAAkB,GAAG,MAAM,CAAC,MAAM,CAAC;gBACnC,UAAU,CAAC,UAAU,CAAC,CAAC;YACzB,CAAC;QACH,CAAC,CAAC,CAAC;QAGH,mBAAmB;QACnB,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;YACtC,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC1B,wDAAwD;YACxD,IAAI,MAAM,CAAC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,CAAC;gBAC1C,uEAAuE;YACzE,CAAC;QACH,CAAC,CAAC,CAAC;QACH,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YACjC,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,UAAU,GAAG,IAAI,CAAC;gBAClB,MAAM,CAAC,IAAI,KAAK,CAAC,4BAA4B,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YACjE,CAAC;QACH,CAAC,CAAC,CAAC;QACH,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YAChC,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,UAAU,GAAG,IAAI,CAAC;gBAClB,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;oBACf,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;gBACzB,CAAC;qBAAM,CAAC;oBACN,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,EAAE,IAAI,eAAe,CAAC;oBACtD,MAAM,CACJ,IAAI,KAAK,CAAC,iCAAiC,IAAI,KAAK,YAAY,EAAE,CAAC,CACpE,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@osanoai/multicli",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.8",
|
|
4
4
|
"description": "MCP server for Multiple CLI coding agent integration (Claude + Gemini + Codex)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -17,8 +17,6 @@
|
|
|
17
17
|
"lint": "tsc --noEmit",
|
|
18
18
|
"prepublishOnly": "echo '⚠️ Remember to test locally first!' && npm run build",
|
|
19
19
|
"refresh-catalog": "npx tsx scripts/refresh-catalog.ts",
|
|
20
|
-
"changeset": "changeset",
|
|
21
|
-
"version-packages": "changeset version",
|
|
22
20
|
"prepare": "husky || true"
|
|
23
21
|
},
|
|
24
22
|
"keywords": [
|
|
@@ -54,8 +52,6 @@
|
|
|
54
52
|
"zod": "^4.3.6"
|
|
55
53
|
},
|
|
56
54
|
"devDependencies": {
|
|
57
|
-
"@changesets/changelog-github": "^0.6.0",
|
|
58
|
-
"@changesets/cli": "^2.30.0",
|
|
59
55
|
"@types/node": "^25.3.3",
|
|
60
56
|
"@vitest/coverage-v8": "^4.0.18",
|
|
61
57
|
"husky": "^9.1.7",
|