converse-mcp-server 2.5.0 → 2.5.2
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/bin/converse.js +0 -0
- package/package.json +54 -54
- package/src/providers/gemini-cli.js +112 -13
- package/src/providers/google.js +0 -1
- package/src/providers/index.js +1 -1
- package/src/tools/chat.js +12 -4
- package/src/tools/consensus.js +11 -3
package/bin/converse.js
CHANGED
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "converse-mcp-server",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.2",
|
|
4
4
|
"description": "Converse MCP Server - Converse with other LLMs with chat and consensus tools",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
@@ -11,58 +11,6 @@
|
|
|
11
11
|
"engines": {
|
|
12
12
|
"node": ">=20.0.0"
|
|
13
13
|
},
|
|
14
|
-
"keywords": [
|
|
15
|
-
"mcp",
|
|
16
|
-
"server",
|
|
17
|
-
"ai",
|
|
18
|
-
"chat",
|
|
19
|
-
"consensus",
|
|
20
|
-
"openai",
|
|
21
|
-
"google",
|
|
22
|
-
"gemini",
|
|
23
|
-
"grok"
|
|
24
|
-
],
|
|
25
|
-
"author": "Converse MCP Server",
|
|
26
|
-
"license": "MIT",
|
|
27
|
-
"homepage": "https://github.com/FallDownTheSystem/converse#readme",
|
|
28
|
-
"repository": {
|
|
29
|
-
"type": "git",
|
|
30
|
-
"url": "git+https://github.com/FallDownTheSystem/converse.git"
|
|
31
|
-
},
|
|
32
|
-
"bugs": {
|
|
33
|
-
"url": "https://github.com/FallDownTheSystem/converse/issues"
|
|
34
|
-
},
|
|
35
|
-
"files": [
|
|
36
|
-
"src/",
|
|
37
|
-
"bin/",
|
|
38
|
-
"docs/",
|
|
39
|
-
"README.md",
|
|
40
|
-
".env.example"
|
|
41
|
-
],
|
|
42
|
-
"dependencies": {
|
|
43
|
-
"@anthropic-ai/sdk": "^0.70.0",
|
|
44
|
-
"@google/genai": "^1.30.0",
|
|
45
|
-
"@mistralai/mistralai": "^1.10.0",
|
|
46
|
-
"@modelcontextprotocol/sdk": "^1.22.0",
|
|
47
|
-
"@openai/codex-sdk": "^0.58.0",
|
|
48
|
-
"ai": "^5.0.101",
|
|
49
|
-
"ai-sdk-provider-gemini-cli": "^1.4.0",
|
|
50
|
-
"cors": "^2.8.5",
|
|
51
|
-
"dotenv": "^17.2.3",
|
|
52
|
-
"express": "^5.1.0",
|
|
53
|
-
"lru-cache": "^11.2.2",
|
|
54
|
-
"openai": "^6.9.1",
|
|
55
|
-
"p-limit": "^7.2.0",
|
|
56
|
-
"vite": "^7.2.2"
|
|
57
|
-
},
|
|
58
|
-
"devDependencies": {
|
|
59
|
-
"@vitest/coverage-v8": "^4.0.10",
|
|
60
|
-
"cross-env": "^10.1.0",
|
|
61
|
-
"eslint": "^9.39.1",
|
|
62
|
-
"prettier": "^3.6.2",
|
|
63
|
-
"rimraf": "^6.1.0",
|
|
64
|
-
"vitest": "^4.0.10"
|
|
65
|
-
},
|
|
66
14
|
"scripts": {
|
|
67
15
|
"kill-server": "node scripts/kill-server.js",
|
|
68
16
|
"start": "npm run kill-server && node src/index.js",
|
|
@@ -116,5 +64,57 @@
|
|
|
116
64
|
"validate:fix": "node scripts/validate.js --fix",
|
|
117
65
|
"validate:fast": "node scripts/validate.js --skip-tests --skip-lint",
|
|
118
66
|
"precommit": "npm run validate"
|
|
67
|
+
},
|
|
68
|
+
"keywords": [
|
|
69
|
+
"mcp",
|
|
70
|
+
"server",
|
|
71
|
+
"ai",
|
|
72
|
+
"chat",
|
|
73
|
+
"consensus",
|
|
74
|
+
"openai",
|
|
75
|
+
"google",
|
|
76
|
+
"gemini",
|
|
77
|
+
"grok"
|
|
78
|
+
],
|
|
79
|
+
"author": "Converse MCP Server",
|
|
80
|
+
"license": "MIT",
|
|
81
|
+
"homepage": "https://github.com/FallDownTheSystem/converse#readme",
|
|
82
|
+
"repository": {
|
|
83
|
+
"type": "git",
|
|
84
|
+
"url": "git+https://github.com/FallDownTheSystem/converse.git"
|
|
85
|
+
},
|
|
86
|
+
"bugs": {
|
|
87
|
+
"url": "https://github.com/FallDownTheSystem/converse/issues"
|
|
88
|
+
},
|
|
89
|
+
"files": [
|
|
90
|
+
"src/",
|
|
91
|
+
"bin/",
|
|
92
|
+
"docs/",
|
|
93
|
+
"README.md",
|
|
94
|
+
".env.example"
|
|
95
|
+
],
|
|
96
|
+
"dependencies": {
|
|
97
|
+
"@anthropic-ai/sdk": "^0.70.0",
|
|
98
|
+
"@google/genai": "^1.30.0",
|
|
99
|
+
"@mistralai/mistralai": "^1.10.0",
|
|
100
|
+
"@modelcontextprotocol/sdk": "^1.22.0",
|
|
101
|
+
"@openai/codex-sdk": "^0.58.0",
|
|
102
|
+
"ai": "^5.0.101",
|
|
103
|
+
"ai-sdk-provider-gemini-cli": "^1.4.0",
|
|
104
|
+
"cors": "^2.8.5",
|
|
105
|
+
"dotenv": "^17.2.3",
|
|
106
|
+
"express": "^5.1.0",
|
|
107
|
+
"lru-cache": "^11.2.2",
|
|
108
|
+
"openai": "^6.9.1",
|
|
109
|
+
"p-limit": "^7.2.0",
|
|
110
|
+
"vite": "^7.2.2"
|
|
111
|
+
},
|
|
112
|
+
"devDependencies": {
|
|
113
|
+
"@vitest/coverage-v8": "^4.0.10",
|
|
114
|
+
"cross-env": "^10.1.0",
|
|
115
|
+
"eslint": "^9.39.1",
|
|
116
|
+
"prettier": "^3.6.2",
|
|
117
|
+
"rimraf": "^6.1.0",
|
|
118
|
+
"vitest": "^4.0.10"
|
|
119
119
|
}
|
|
120
|
-
}
|
|
120
|
+
}
|
|
@@ -24,8 +24,8 @@ import { ProviderError, ErrorCodes, StopReasons } from './interface.js';
|
|
|
24
24
|
|
|
25
25
|
// Supported Gemini CLI models with their configurations
|
|
26
26
|
const SUPPORTED_MODELS = {
|
|
27
|
-
|
|
28
|
-
modelName: 'gemini
|
|
27
|
+
gemini: {
|
|
28
|
+
modelName: 'gemini',
|
|
29
29
|
friendlyName: 'Gemini 3.0 Pro Preview (via CLI)',
|
|
30
30
|
contextWindow: 1048576, // 1M tokens
|
|
31
31
|
maxOutputTokens: 64000,
|
|
@@ -37,6 +37,9 @@ const SUPPORTED_MODELS = {
|
|
|
37
37
|
timeout: 300000, // 5 minutes
|
|
38
38
|
description:
|
|
39
39
|
'Gemini 3.0 Pro Preview via OAuth - requires Gemini CLI authentication',
|
|
40
|
+
aliases: ['gemini-cli'],
|
|
41
|
+
// Internal SDK model name (user-facing "gemini" maps to SDK's "gemini-3-pro-preview")
|
|
42
|
+
sdkModelName: 'gemini-3-pro-preview',
|
|
40
43
|
},
|
|
41
44
|
};
|
|
42
45
|
|
|
@@ -103,16 +106,17 @@ async function getAISDK() {
|
|
|
103
106
|
* Yields normalized events compatible with ProviderStreamNormalizer
|
|
104
107
|
*/
|
|
105
108
|
async function* createStreamingGenerator(
|
|
106
|
-
|
|
109
|
+
modelInstance,
|
|
107
110
|
messages,
|
|
108
111
|
options,
|
|
109
112
|
signal,
|
|
113
|
+
userFacingModelName = 'gemini',
|
|
110
114
|
) {
|
|
111
115
|
const { streamText } = await getAISDK();
|
|
112
116
|
|
|
113
117
|
try {
|
|
114
118
|
const streamOptions = {
|
|
115
|
-
model,
|
|
119
|
+
model: modelInstance,
|
|
116
120
|
messages,
|
|
117
121
|
...options,
|
|
118
122
|
};
|
|
@@ -127,7 +131,7 @@ async function* createStreamingGenerator(
|
|
|
127
131
|
yield {
|
|
128
132
|
type: 'start',
|
|
129
133
|
provider: 'gemini-cli',
|
|
130
|
-
model:
|
|
134
|
+
model: userFacingModelName,
|
|
131
135
|
};
|
|
132
136
|
|
|
133
137
|
// Stream text chunks
|
|
@@ -137,10 +141,12 @@ async function* createStreamingGenerator(
|
|
|
137
141
|
throw new GeminiCliProviderError('Request cancelled', 'CANCELLED');
|
|
138
142
|
}
|
|
139
143
|
|
|
140
|
-
// Yield delta event with content chunk
|
|
144
|
+
// Yield delta event with content chunk (normalized format)
|
|
141
145
|
yield {
|
|
142
146
|
type: 'delta',
|
|
143
|
-
|
|
147
|
+
data: {
|
|
148
|
+
textDelta: chunk,
|
|
149
|
+
},
|
|
144
150
|
};
|
|
145
151
|
}
|
|
146
152
|
|
|
@@ -196,6 +202,68 @@ function mapFinishReason(finishReason) {
|
|
|
196
202
|
}
|
|
197
203
|
}
|
|
198
204
|
|
|
205
|
+
/**
|
|
206
|
+
* Convert messages from Converse internal format to Gemini CLI SDK format
|
|
207
|
+
*
|
|
208
|
+
* Converse format (used by other providers like Anthropic):
|
|
209
|
+
* - Images: { type: 'image', source: { type: 'base64', media_type: '...', data: '...' } }
|
|
210
|
+
*
|
|
211
|
+
* Gemini CLI SDK format (from SDK guide):
|
|
212
|
+
* - Images: { type: 'image', data: '...' } (base64 string)
|
|
213
|
+
* - Text: { type: 'text', text: '...' }
|
|
214
|
+
*
|
|
215
|
+
* @param {Array} messages - Messages in Converse internal format
|
|
216
|
+
* @returns {Array} Messages in Gemini CLI SDK format
|
|
217
|
+
*/
|
|
218
|
+
function convertToGeminiCliMessages(messages) {
|
|
219
|
+
return messages.map((message) => {
|
|
220
|
+
// If content is a string, no conversion needed
|
|
221
|
+
if (typeof message.content === 'string') {
|
|
222
|
+
return message;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// If content is an array, convert each part
|
|
226
|
+
if (Array.isArray(message.content)) {
|
|
227
|
+
const convertedContent = message.content.map((part) => {
|
|
228
|
+
// Text parts are already in correct format
|
|
229
|
+
if (part.type === 'text') {
|
|
230
|
+
return part;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Convert image from Converse format to Gemini CLI SDK format
|
|
234
|
+
if (part.type === 'image' && part.source) {
|
|
235
|
+
return {
|
|
236
|
+
type: 'image',
|
|
237
|
+
data: part.source.data, // Extract base64 data (use 'data' not 'image')
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// If already in Gemini CLI format, return as-is
|
|
242
|
+
if (part.type === 'image' && part.data) {
|
|
243
|
+
return part;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Handle file parts (future-proofing)
|
|
247
|
+
if (part.type === 'file' && part.data) {
|
|
248
|
+
return part;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// Unknown part type, return as-is and let SDK handle it
|
|
252
|
+
debugLog(`[Gemini CLI] Unknown content part type: ${part.type}`);
|
|
253
|
+
return part;
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
return {
|
|
257
|
+
...message,
|
|
258
|
+
content: convertedContent,
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// Unknown content type, return as-is
|
|
263
|
+
return message;
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
|
|
199
267
|
/**
|
|
200
268
|
* Gemini CLI Provider Implementation
|
|
201
269
|
*/
|
|
@@ -208,7 +276,7 @@ export const geminiCliProvider = {
|
|
|
208
276
|
*/
|
|
209
277
|
async invoke(messages, options = {}) {
|
|
210
278
|
const {
|
|
211
|
-
model = 'gemini
|
|
279
|
+
model = 'gemini',
|
|
212
280
|
config,
|
|
213
281
|
stream = false,
|
|
214
282
|
signal,
|
|
@@ -234,6 +302,18 @@ export const geminiCliProvider = {
|
|
|
234
302
|
}
|
|
235
303
|
|
|
236
304
|
try {
|
|
305
|
+
// Get model configuration to map user-facing name to SDK model name
|
|
306
|
+
const modelConfig = this.getModelConfig(model);
|
|
307
|
+
if (!modelConfig) {
|
|
308
|
+
throw new GeminiCliProviderError(
|
|
309
|
+
`Model ${model} not supported by Gemini CLI provider`,
|
|
310
|
+
ErrorCodes.MODEL_NOT_FOUND,
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// Get the SDK model name (e.g., "gemini" -> "gemini-3-pro-preview")
|
|
315
|
+
const sdkModelName = modelConfig.sdkModelName || model;
|
|
316
|
+
|
|
237
317
|
// Get SDKs
|
|
238
318
|
const createGeminiProvider = await getGeminiCliSDK();
|
|
239
319
|
const { generateText } = await getAISDK();
|
|
@@ -243,12 +323,15 @@ export const geminiCliProvider = {
|
|
|
243
323
|
authType: 'oauth-personal',
|
|
244
324
|
});
|
|
245
325
|
|
|
246
|
-
// Create model instance
|
|
247
|
-
const modelInstance = gemini(
|
|
326
|
+
// Create model instance with SDK model name
|
|
327
|
+
const modelInstance = gemini(sdkModelName);
|
|
328
|
+
|
|
329
|
+
// Convert messages from Converse format to Gemini CLI SDK format
|
|
330
|
+
const convertedMessages = convertToGeminiCliMessages(messages);
|
|
248
331
|
|
|
249
332
|
// Build AI SDK options
|
|
250
333
|
const aiOptions = {
|
|
251
|
-
messages,
|
|
334
|
+
messages: convertedMessages,
|
|
252
335
|
};
|
|
253
336
|
|
|
254
337
|
// Add optional parameters
|
|
@@ -271,7 +354,13 @@ export const geminiCliProvider = {
|
|
|
271
354
|
|
|
272
355
|
// Streaming mode
|
|
273
356
|
if (stream) {
|
|
274
|
-
return createStreamingGenerator(
|
|
357
|
+
return createStreamingGenerator(
|
|
358
|
+
modelInstance,
|
|
359
|
+
convertedMessages,
|
|
360
|
+
aiOptions,
|
|
361
|
+
signal,
|
|
362
|
+
model, // Pass user-facing model name for metadata
|
|
363
|
+
);
|
|
275
364
|
}
|
|
276
365
|
|
|
277
366
|
// Synchronous mode
|
|
@@ -382,7 +471,17 @@ export const geminiCliProvider = {
|
|
|
382
471
|
return SUPPORTED_MODELS[modelNameLower];
|
|
383
472
|
}
|
|
384
473
|
|
|
385
|
-
//
|
|
474
|
+
// Check aliases
|
|
475
|
+
for (const [supportedModel, config] of Object.entries(SUPPORTED_MODELS)) {
|
|
476
|
+
if (config.aliases) {
|
|
477
|
+
for (const alias of config.aliases) {
|
|
478
|
+
if (alias.toLowerCase() === modelNameLower) {
|
|
479
|
+
return config;
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
|
|
386
485
|
return null;
|
|
387
486
|
},
|
|
388
487
|
};
|
package/src/providers/google.js
CHANGED
package/src/providers/index.js
CHANGED
|
@@ -26,13 +26,13 @@ import { geminiCliProvider } from './gemini-cli.js';
|
|
|
26
26
|
const providers = {
|
|
27
27
|
openai: openaiProvider,
|
|
28
28
|
xai: xaiProvider,
|
|
29
|
+
'gemini-cli': geminiCliProvider,
|
|
29
30
|
google: googleProvider,
|
|
30
31
|
anthropic: anthropicProvider,
|
|
31
32
|
mistral: mistralProvider,
|
|
32
33
|
deepseek: deepseekProvider,
|
|
33
34
|
openrouter: openrouterProvider,
|
|
34
35
|
codex: codexProvider,
|
|
35
|
-
'gemini-cli': geminiCliProvider,
|
|
36
36
|
};
|
|
37
37
|
|
|
38
38
|
/**
|
package/src/tools/chat.js
CHANGED
|
@@ -416,6 +416,8 @@ function resolveAutoModel(model, providerName) {
|
|
|
416
416
|
}
|
|
417
417
|
|
|
418
418
|
const defaults = {
|
|
419
|
+
codex: 'codex',
|
|
420
|
+
'gemini-cli': 'gemini',
|
|
419
421
|
openai: 'gpt-5',
|
|
420
422
|
xai: 'grok-4-0709',
|
|
421
423
|
google: 'gemini-pro',
|
|
@@ -431,8 +433,15 @@ function resolveAutoModel(model, providerName) {
|
|
|
431
433
|
export function mapModelToProvider(model, providers) {
|
|
432
434
|
const modelLower = model.toLowerCase();
|
|
433
435
|
|
|
434
|
-
// Handle "auto" -
|
|
436
|
+
// Handle "auto" - prioritize: codex > gemini-cli > openai
|
|
435
437
|
if (modelLower === 'auto') {
|
|
438
|
+
// Check availability in priority order
|
|
439
|
+
if (providers['codex']) {
|
|
440
|
+
return 'codex';
|
|
441
|
+
}
|
|
442
|
+
if (providers['gemini-cli']) {
|
|
443
|
+
return 'gemini-cli';
|
|
444
|
+
}
|
|
436
445
|
return 'openai';
|
|
437
446
|
}
|
|
438
447
|
|
|
@@ -442,7 +451,7 @@ export function mapModelToProvider(model, providers) {
|
|
|
442
451
|
}
|
|
443
452
|
|
|
444
453
|
// Check Gemini CLI (exact match only - routes to CLI provider instead of Google API)
|
|
445
|
-
if (modelLower === 'gemini') {
|
|
454
|
+
if (modelLower === 'gemini' || modelLower === 'gemini-cli') {
|
|
446
455
|
return 'gemini-cli';
|
|
447
456
|
}
|
|
448
457
|
|
|
@@ -495,7 +504,6 @@ export function mapModelToProvider(model, providers) {
|
|
|
495
504
|
|
|
496
505
|
// Google models
|
|
497
506
|
if (
|
|
498
|
-
modelLower.includes('gemini') ||
|
|
499
507
|
modelLower.includes('flash') ||
|
|
500
508
|
modelLower.includes('pro') ||
|
|
501
509
|
modelLower === 'google'
|
|
@@ -939,7 +947,7 @@ chatTool.inputSchema = {
|
|
|
939
947
|
model: {
|
|
940
948
|
type: 'string',
|
|
941
949
|
description:
|
|
942
|
-
'AI model to use. Examples: "auto" (recommended), "
|
|
950
|
+
'AI model to use. Examples: "auto" (recommended), "codex", "gemini", "gpt-5", "grok-4-0709". Defaults to auto-selection.',
|
|
943
951
|
},
|
|
944
952
|
files: {
|
|
945
953
|
type: 'array',
|
package/src/tools/consensus.js
CHANGED
|
@@ -653,6 +653,8 @@ Please provide your refined response:`;
|
|
|
653
653
|
*/
|
|
654
654
|
function getDefaultModelForProvider(providerName) {
|
|
655
655
|
const defaults = {
|
|
656
|
+
codex: 'codex',
|
|
657
|
+
'gemini-cli': 'gemini',
|
|
656
658
|
openai: 'gpt-5',
|
|
657
659
|
xai: 'grok-4-0709',
|
|
658
660
|
google: 'gemini-pro',
|
|
@@ -679,8 +681,15 @@ function resolveAutoModel(model, providerName) {
|
|
|
679
681
|
function mapModelToProvider(model, providers) {
|
|
680
682
|
const modelLower = model.toLowerCase();
|
|
681
683
|
|
|
682
|
-
// Handle "auto" -
|
|
684
|
+
// Handle "auto" - prioritize: codex > gemini-cli > openai
|
|
683
685
|
if (modelLower === 'auto') {
|
|
686
|
+
// Check availability in priority order
|
|
687
|
+
if (providers['codex']) {
|
|
688
|
+
return 'codex';
|
|
689
|
+
}
|
|
690
|
+
if (providers['gemini-cli']) {
|
|
691
|
+
return 'gemini-cli';
|
|
692
|
+
}
|
|
684
693
|
return 'openai';
|
|
685
694
|
}
|
|
686
695
|
|
|
@@ -690,7 +699,7 @@ function mapModelToProvider(model, providers) {
|
|
|
690
699
|
}
|
|
691
700
|
|
|
692
701
|
// Check Gemini CLI (exact match only - routes to CLI provider instead of Google API)
|
|
693
|
-
if (modelLower === 'gemini') {
|
|
702
|
+
if (modelLower === 'gemini' || modelLower === 'gemini-cli') {
|
|
694
703
|
return 'gemini-cli';
|
|
695
704
|
}
|
|
696
705
|
|
|
@@ -743,7 +752,6 @@ function mapModelToProvider(model, providers) {
|
|
|
743
752
|
|
|
744
753
|
// Google models
|
|
745
754
|
if (
|
|
746
|
-
modelLower.includes('gemini') ||
|
|
747
755
|
modelLower.includes('flash') ||
|
|
748
756
|
modelLower.includes('pro') ||
|
|
749
757
|
modelLower === 'google'
|