converse-mcp-server 2.9.4 → 2.9.5

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 CHANGED
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "converse-mcp-server",
3
- "version": "2.9.4",
3
+ "version": "2.9.5",
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,60 +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/claude-agent-sdk": "^0.1.51",
44
- "@anthropic-ai/sdk": "^0.70.0",
45
- "@google/genai": "^1.30.0",
46
- "@mistralai/mistralai": "^1.10.0",
47
- "@modelcontextprotocol/sdk": "^1.22.0",
48
- "@openai/codex-sdk": "^0.63.0",
49
- "ai": "^5.0.101",
50
- "ai-sdk-provider-gemini-cli": "^1.4.0",
51
- "cors": "^2.8.5",
52
- "dotenv": "^17.2.3",
53
- "express": "^5.1.0",
54
- "lru-cache": "^11.2.2",
55
- "nanoid": "^5.1.6",
56
- "openai": "^6.9.1",
57
- "p-limit": "^7.2.0",
58
- "vite": "^7.2.2"
59
- },
60
- "devDependencies": {
61
- "@vitest/coverage-v8": "^4.0.10",
62
- "cross-env": "^10.1.0",
63
- "eslint": "^9.39.1",
64
- "prettier": "^3.6.2",
65
- "rimraf": "^6.1.0",
66
- "vitest": "^4.0.10"
67
- },
68
14
  "scripts": {
69
15
  "kill-server": "node scripts/kill-server.js",
70
16
  "start": "npm run kill-server && node src/index.js",
@@ -118,5 +64,59 @@
118
64
  "validate:fix": "node scripts/validate.js --fix",
119
65
  "validate:fast": "node scripts/validate.js --skip-tests --skip-lint",
120
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/claude-agent-sdk": "^0.1.51",
98
+ "@anthropic-ai/sdk": "^0.70.0",
99
+ "@google/genai": "^1.30.0",
100
+ "@mistralai/mistralai": "^1.10.0",
101
+ "@modelcontextprotocol/sdk": "^1.22.0",
102
+ "@openai/codex-sdk": "^0.63.0",
103
+ "ai": "^5.0.101",
104
+ "ai-sdk-provider-gemini-cli": "^1.4.0",
105
+ "cors": "^2.8.5",
106
+ "dotenv": "^17.2.3",
107
+ "express": "^5.1.0",
108
+ "lru-cache": "^11.2.2",
109
+ "nanoid": "^5.1.6",
110
+ "openai": "^6.9.1",
111
+ "p-limit": "^7.2.0",
112
+ "vite": "^7.2.2"
113
+ },
114
+ "devDependencies": {
115
+ "@vitest/coverage-v8": "^4.0.10",
116
+ "cross-env": "^10.1.0",
117
+ "eslint": "^9.39.1",
118
+ "prettier": "^3.6.2",
119
+ "rimraf": "^6.1.0",
120
+ "vitest": "^4.0.10"
121
121
  }
122
- }
122
+ }
@@ -10,9 +10,9 @@ import { debugLog, debugError } from '../utils/console.js';
10
10
 
11
11
  // Define supported models with their capabilities
12
12
  const SUPPORTED_MODELS = {
13
- 'gpt-5.1': {
14
- modelName: 'gpt-5.1',
15
- friendlyName: 'OpenAI (GPT-5.1)',
13
+ 'gpt-5.2': {
14
+ modelName: 'gpt-5.2',
15
+ friendlyName: 'OpenAI (GPT-5.2)',
16
16
  contextWindow: 400000,
17
17
  maxOutputTokens: 128000,
18
18
  supportsStreaming: true,
@@ -20,7 +20,7 @@ const SUPPORTED_MODELS = {
20
20
  supportsTemperature: false, // GPT-5 doesn't support temperature
21
21
  supportsWebSearch: true,
22
22
  supportsResponsesAPI: true,
23
- supportsNoneReasoningEffort: true, // GPT-5.1 supports "none" for faster responses
23
+ supportsNoneReasoningEffort: true, // GPT-5.2 supports "none" for faster responses
24
24
  timeout: 3600000, // 1 hour
25
25
  description:
26
26
  'Latest flagship model (400K context, 128K output) - Superior reasoning, code generation, analysis. Supports "none" reasoning for faster responses',
@@ -28,9 +28,9 @@ const SUPPORTED_MODELS = {
28
28
  'gpt-5',
29
29
  'gpt5',
30
30
  'gpt 5',
31
- 'gpt-5.1-2025-11-13',
32
- 'gpt5.1',
33
- 'gpt 5.1',
31
+ 'gpt-5.2-2025-12-11',
32
+ 'gpt5.2',
33
+ 'gpt 5.2',
34
34
  ],
35
35
  },
36
36
  'gpt-5-2025-08-07': {
package/src/tools/chat.js CHANGED
@@ -21,6 +21,7 @@ import { applyTokenLimit, getTokenLimit } from '../utils/tokenLimiter.js';
21
21
  import { validateAllPaths } from '../utils/fileValidator.js';
22
22
  import { SummarizationService } from '../services/summarizationService.js';
23
23
  import { exportConversation } from '../utils/conversationExporter.js';
24
+ import { isRecoverableError, retryWithBackoff } from '../utils/errorHandler.js';
24
25
 
25
26
  const logger = createLogger('chat');
26
27
 
@@ -265,12 +266,14 @@ export async function chatTool(args, dependencies) {
265
266
 
266
267
  messages.push(userMessage);
267
268
 
268
- // Select provider
269
+ // Select provider(s)
269
270
  let selectedProvider;
270
271
  let providerName;
271
272
 
273
+ const providerCandidates = [];
274
+
272
275
  if (model === 'auto') {
273
- // Auto-select first available provider in priority order
276
+ // Auto-select providers in priority order
274
277
  // Prioritize subscription-based providers (codex, gemini-cli, claude) over API-key providers
275
278
  const providerOrder = [
276
279
  'codex',
@@ -288,20 +291,17 @@ export async function chatTool(args, dependencies) {
288
291
  for (const name of providerOrder) {
289
292
  const provider = providers[name];
290
293
  if (provider && provider.isAvailable && provider.isAvailable(config)) {
291
- providerName = name;
292
- selectedProvider = provider;
293
- break;
294
+ providerCandidates.push({ name, provider });
294
295
  }
295
296
  }
296
297
 
297
- if (!providerName) {
298
+ if (providerCandidates.length === 0) {
298
299
  return createToolError(
299
300
  'No providers available. Please configure at least one API key.',
300
301
  );
301
302
  }
302
303
  } else {
303
304
  // Use specified provider/model
304
- // Try to map model to provider
305
305
  providerName = mapModelToProvider(model, providers);
306
306
  selectedProvider = providers[providerName];
307
307
 
@@ -314,32 +314,60 @@ export async function chatTool(args, dependencies) {
314
314
  `Provider ${providerName} is not available. Check API key configuration.`,
315
315
  );
316
316
  }
317
- }
318
317
 
319
- // Resolve model name and prepare provider options
320
- const resolvedModel = resolveAutoModel(model, providerName);
321
- const providerOptions = {
322
- model: resolvedModel,
323
- temperature,
324
- reasoning_effort,
325
- verbosity,
326
- use_websearch,
327
- config,
328
- continuation_id, // Pass for thread resumption
329
- continuationStore, // Pass store for state management
330
- };
318
+ providerCandidates.push({ name: providerName, provider: selectedProvider });
319
+ }
331
320
 
332
- // Call provider
321
+ // Call provider with recovery (retry and, for auto, failover)
333
322
  let response;
334
323
  const startTime = Date.now();
335
- try {
336
- response = await selectedProvider.invoke(messages, providerOptions);
337
- } catch (error) {
338
- logger.error('Provider error', {
339
- error,
340
- data: { provider: providerName },
341
- });
342
- return createToolError(`Provider error: ${error.message}`);
324
+ let lastError;
325
+ let resolvedModel;
326
+
327
+ for (const candidate of providerCandidates) {
328
+ providerName = candidate.name;
329
+ selectedProvider = candidate.provider;
330
+
331
+ // Resolve model name and prepare provider options
332
+ resolvedModel = resolveAutoModel(model, providerName);
333
+ const providerOptions = {
334
+ model: resolvedModel,
335
+ temperature,
336
+ reasoning_effort,
337
+ verbosity,
338
+ use_websearch,
339
+ config,
340
+ continuation_id, // Pass for thread resumption
341
+ continuationStore, // Pass store for state management
342
+ };
343
+
344
+ try {
345
+ response = await retryWithBackoff(
346
+ () => selectedProvider.invoke(messages, providerOptions),
347
+ getProviderRetryOptions(config, providerName),
348
+ );
349
+ break;
350
+ } catch (error) {
351
+ lastError = error;
352
+ logger.error('Provider error', {
353
+ error,
354
+ data: { provider: providerName },
355
+ });
356
+
357
+ if (
358
+ model !== 'auto' ||
359
+ !shouldFailoverToNextProvider(error) ||
360
+ candidate === providerCandidates[providerCandidates.length - 1]
361
+ ) {
362
+ return createToolError(`Provider error: ${error.message}`);
363
+ }
364
+ }
365
+ }
366
+
367
+ if (!response) {
368
+ return createToolError(
369
+ `Provider error: ${(lastError && lastError.message) || 'Unknown error'}`,
370
+ );
343
371
  }
344
372
  const executionTime = (Date.now() - startTime) / 1000; // Convert to seconds
345
373
 
@@ -472,6 +500,29 @@ function resolveAutoModel(model, providerName) {
472
500
  return defaults[providerName] || 'gpt-5';
473
501
  }
474
502
 
503
+ function getProviderRetryOptions(config, providerName) {
504
+ const nodeEnv = config?.environment?.nodeEnv || process.env.NODE_ENV;
505
+ const isTest = nodeEnv === 'test';
506
+
507
+ return {
508
+ retries: isTest ? 1 : 3,
509
+ delay: isTest ? 0 : 500,
510
+ maxDelay: isTest ? 0 : 10000,
511
+ operation: `provider-invoke:${providerName}`,
512
+ };
513
+ }
514
+
515
+ function shouldFailoverToNextProvider(error) {
516
+ if (isRecoverableError(error)) {
517
+ return true;
518
+ }
519
+
520
+ const message = (error && error.message) || '';
521
+ return /(api key|authentication|unauthorized|forbidden|invalid|not available)/i.test(
522
+ message,
523
+ );
524
+ }
525
+
475
526
  export function mapModelToProvider(model, providers) {
476
527
  const modelLower = model.toLowerCase();
477
528