converse-mcp-server 2.29.2 → 3.0.1

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.
Files changed (42) hide show
  1. package/.env.example +6 -3
  2. package/README.md +96 -94
  3. package/docs/API.md +703 -1562
  4. package/docs/ARCHITECTURE.md +13 -11
  5. package/docs/EXAMPLES.md +241 -667
  6. package/docs/PROVIDERS.md +104 -79
  7. package/package.json +1 -1
  8. package/src/async/asyncJobStore.js +2 -2
  9. package/src/async/jobRunner.js +6 -1
  10. package/src/async/providerStreamNormalizer.js +59 -1
  11. package/src/config.js +4 -3
  12. package/src/prompts/helpPrompt.js +43 -61
  13. package/src/providers/anthropic.js +0 -31
  14. package/src/providers/claude.js +0 -14
  15. package/src/providers/codex.js +15 -21
  16. package/src/providers/copilot.js +36 -202
  17. package/src/providers/deepseek.js +73 -53
  18. package/src/providers/gemini-cli.js +0 -3
  19. package/src/providers/google.js +10 -27
  20. package/src/providers/interface.js +0 -3
  21. package/src/providers/mistral.js +169 -63
  22. package/src/providers/openai-compatible.js +113 -28
  23. package/src/providers/openai.js +14 -66
  24. package/src/providers/openrouter-discovery.js +308 -0
  25. package/src/providers/openrouter.js +452 -282
  26. package/src/providers/xai.js +298 -280
  27. package/src/services/summarizationService.js +4 -14
  28. package/src/systemPrompts.js +19 -2
  29. package/src/tools/cancelJob.js +7 -1
  30. package/src/tools/chat.js +957 -995
  31. package/src/tools/checkStatus.js +1 -0
  32. package/src/tools/index.js +2 -6
  33. package/src/tools/modes/parallel.js +488 -0
  34. package/src/tools/modes/roundtable.js +495 -0
  35. package/src/tools/modes/streamShared.js +31 -0
  36. package/src/utils/contextProcessor.js +1 -38
  37. package/src/utils/conversationExporter.js +6 -26
  38. package/src/utils/formatStatus.js +46 -19
  39. package/src/utils/modelRouting.js +207 -4
  40. package/src/providers/openrouter-endpoints-client.js +0 -220
  41. package/src/tools/consensus.js +0 -1813
  42. package/src/tools/conversation.js +0 -1233
@@ -17,17 +17,12 @@ const SAMPLE_VALUES = {
17
17
  prompt: 'Explain the authentication flow in this codebase',
18
18
  files: ['src/auth.js'],
19
19
  images: ['./diagram.png'],
20
- model: 'auto',
21
20
  models: ['codex', 'gemini', 'claude'],
21
+ mode: 'consensus',
22
22
  continuation_id: 'conv_abc123',
23
- temperature: 0.5,
24
23
  reasoning_effort: 'medium',
25
- verbosity: 'medium',
26
- use_websearch: false,
27
24
  async: false,
28
25
  export: false,
29
- enable_cross_feedback: true,
30
- cross_feedback_prompt: null,
31
26
  full_history: false,
32
27
  };
33
28
 
@@ -122,24 +117,37 @@ function generateToolExamplesFromSchema(toolName, inputSchema) {
122
117
  }
123
118
  }
124
119
 
125
- // For chat and consensus, add some optional parameters for richer examples
120
+ // For the chat tool, show one example per mode for richer documentation.
126
121
  if (toolName === 'chat') {
127
- // Add commonly used optional parameters
128
- if (properties.model) example.model = SAMPLE_VALUES.model;
129
- if (properties.files) example.files = SAMPLE_VALUES.files;
130
- if (properties.temperature) example.temperature = SAMPLE_VALUES.temperature;
131
- } else if (toolName === 'consensus') {
132
- // Add commonly used optional parameters
133
- if (properties.files) example.files = SAMPLE_VALUES.files;
134
- if (properties.enable_cross_feedback)
135
- example.enable_cross_feedback = SAMPLE_VALUES.enable_cross_feedback;
136
- if (properties.temperature) example.temperature = 0.2; // Lower for consensus
137
- } else if (toolName === 'check_status') {
138
- // For check_status, just show the continuation_id
139
- if (properties.continuation_id)
140
- example.continuation_id = SAMPLE_VALUES.continuation_id;
141
- } else if (toolName === 'cancel_job') {
142
- // For cancel_job, just show the continuation_id
122
+ const chatExample = { prompt: SAMPLE_VALUES.prompt, models: ['auto'] };
123
+ if (properties.files) chatExample.files = SAMPLE_VALUES.files;
124
+ const consensusExample = {
125
+ prompt: SAMPLE_VALUES.prompt,
126
+ models: SAMPLE_VALUES.models,
127
+ mode: 'consensus',
128
+ };
129
+ const roundtableExample = {
130
+ prompt: SAMPLE_VALUES.prompt,
131
+ models: SAMPLE_VALUES.models,
132
+ mode: 'roundtable',
133
+ };
134
+ return [
135
+ '```json',
136
+ '// mode "chat" (default) independent parallel answers',
137
+ JSON.stringify(chatExample, null, 2),
138
+ '```',
139
+ '```json',
140
+ '// mode "consensus" — ≥2 models answer, then refine',
141
+ JSON.stringify(consensusExample, null, 2),
142
+ '```',
143
+ '```json',
144
+ '// mode "roundtable" — sequential turn-based dialogue',
145
+ JSON.stringify(roundtableExample, null, 2),
146
+ '```',
147
+ ].join('\n');
148
+ }
149
+
150
+ if (toolName === 'check_status' || toolName === 'cancel_job') {
143
151
  if (properties.continuation_id)
144
152
  example.continuation_id = SAMPLE_VALUES.continuation_id;
145
153
  }
@@ -271,19 +279,12 @@ function generateConfigurationTips(tools) {
271
279
  // Get chat tool schema for parameter info
272
280
  const chatSchema = tools.chat?.inputSchema?.properties || {};
273
281
 
274
- // Temperature Settings
275
- if (chatSchema.temperature) {
276
- const tempSchema = chatSchema.temperature;
277
- output += '### Temperature Settings\n';
278
- if (tempSchema.minimum !== undefined && tempSchema.maximum !== undefined) {
279
- output += `Range: ${tempSchema.minimum} to ${tempSchema.maximum}\n`;
280
- }
281
- output += '- **0.0-0.3**: Factual, deterministic responses\n';
282
- output += '- **0.4-0.7**: Balanced creativity and accuracy (recommended)\n';
283
- output += '- **0.8-1.2**: Creative writing, brainstorming\n';
284
- if (tempSchema.maximum && tempSchema.maximum > 1.2) {
285
- output += `- **1.3-${tempSchema.maximum}**: Highly experimental, unpredictable\n`;
286
- }
282
+ // Modes
283
+ if (chatSchema.mode) {
284
+ output += '### Modes\n';
285
+ output += '- **chat** (default): 1..N models answer independently in parallel\n';
286
+ output += '- **consensus**: ≥2 models answer, then refine after seeing each other\n';
287
+ output += '- **roundtable**: models answer sequentially in the given order, each building on the transcript\n';
287
288
  output += '\n';
288
289
  }
289
290
 
@@ -307,23 +308,6 @@ function generateConfigurationTips(tools) {
307
308
  output += '\n';
308
309
  }
309
310
 
310
- // Verbosity
311
- if (chatSchema.verbosity) {
312
- const verbSchema = chatSchema.verbosity;
313
- output += '### Verbosity (for GPT-5 models)\n';
314
- if (verbSchema.enum) {
315
- const descriptions = {
316
- low: 'Concise answers',
317
- medium: 'Balanced detail (default)',
318
- high: 'Thorough explanations',
319
- };
320
- for (const value of verbSchema.enum) {
321
- output += `- **${value}**: ${descriptions[value] || value}\n`;
322
- }
323
- }
324
- output += '\n';
325
- }
326
-
327
311
  // File Context
328
312
  output += '### File Context\n';
329
313
  output +=
@@ -391,7 +375,6 @@ export function generateHelpContent(config = null) {
391
375
  const features = [];
392
376
  if (config.supportsStreaming) features.push('Streaming');
393
377
  if (config.supportsImages) features.push('Images');
394
- if (config.supportsTemperature) features.push('Temperature');
395
378
  if (config.supportsWebSearch) features.push('Web Search');
396
379
  if (config.supportsThinking) features.push('Thinking Mode');
397
380
  if (config.supportsResponsesAPI) features.push('Responses API');
@@ -475,15 +458,15 @@ ${generateConfigurationTips(tools)}
475
458
  - Specify models when you need specific capabilities
476
459
  - Consider cost vs performance tradeoffs
477
460
 
478
- 2. **Consensus Tool**
479
- - Mix different model types for diverse perspectives
480
- - Enable cross-feedback for refined responses
481
- - Use lower temperature for more consistent consensus
461
+ 2. **Choosing a Mode**
462
+ - Use **chat** for a single answer or independent parallel answers
463
+ - Use **consensus** to have ≥2 models cross-check and refine each other
464
+ - Use **roundtable** for a sequential discussion where each model builds on the last
482
465
 
483
466
  3. **Context Management**
484
467
  - Include only relevant files to avoid token limits
485
468
  - Use descriptive prompts to guide model focus
486
- - Leverage continuation IDs for multi-turn conversations
469
+ - Leverage continuation IDs for multi-turn conversations (you may switch modes on resume)
487
470
 
488
471
  4. **Error Handling**
489
472
  - Check for API key configuration if providers fail
@@ -505,8 +488,7 @@ These providers use local CLI tools and don't require API keys:
505
488
  ## Need More Help?
506
489
 
507
490
  - Check the documentation at: https://github.com/FallDownTheSystem/converse
508
- - Report issues at: https://github.com/FallDownTheSystem/converse/issues
509
- - View examples in the \`/examples\` directory`;
491
+ - Report issues at: https://github.com/FallDownTheSystem/converse/issues`;
510
492
 
511
493
  return helpContent;
512
494
  }
@@ -20,7 +20,6 @@ const SUPPORTED_MODELS = {
20
20
  maxOutputTokens: 128000,
21
21
  supportsStreaming: true,
22
22
  supportsImages: true,
23
- supportsTemperature: false, // Fable 5 rejects temperature/top_p/top_k (400)
24
23
  supportsWebSearch: false,
25
24
  supportsThinking: true,
26
25
  supportsAdaptiveThinking: true, // Adaptive thinking is the only thinking mode
@@ -46,7 +45,6 @@ const SUPPORTED_MODELS = {
46
45
  maxOutputTokens: 128000,
47
46
  supportsStreaming: true,
48
47
  supportsImages: true,
49
- supportsTemperature: true,
50
48
  supportsWebSearch: false,
51
49
  supportsThinking: true,
52
50
  supportsAdaptiveThinking: true,
@@ -79,7 +77,6 @@ const SUPPORTED_MODELS = {
79
77
  maxOutputTokens: 128000,
80
78
  supportsStreaming: true,
81
79
  supportsImages: true,
82
- supportsTemperature: true,
83
80
  supportsWebSearch: false,
84
81
  supportsThinking: true,
85
82
  supportsAdaptiveThinking: true,
@@ -110,7 +107,6 @@ const SUPPORTED_MODELS = {
110
107
  maxOutputTokens: 128000,
111
108
  supportsStreaming: true,
112
109
  supportsImages: true,
113
- supportsTemperature: true,
114
110
  supportsWebSearch: false,
115
111
  supportsThinking: true,
116
112
  supportsAdaptiveThinking: true,
@@ -141,7 +137,6 @@ const SUPPORTED_MODELS = {
141
137
  maxOutputTokens: 64000,
142
138
  supportsStreaming: true,
143
139
  supportsImages: true,
144
- supportsTemperature: true,
145
140
  supportsWebSearch: false,
146
141
  supportsThinking: true,
147
142
  minThinkingTokens: 1024,
@@ -168,7 +163,6 @@ const SUPPORTED_MODELS = {
168
163
  maxOutputTokens: 32000,
169
164
  supportsStreaming: true,
170
165
  supportsImages: true,
171
- supportsTemperature: true,
172
166
  supportsWebSearch: false,
173
167
  supportsThinking: true,
174
168
  minThinkingTokens: 1024,
@@ -197,7 +191,6 @@ const SUPPORTED_MODELS = {
197
191
  maxOutputTokens: 64000,
198
192
  supportsStreaming: true,
199
193
  supportsImages: true,
200
- supportsTemperature: true,
201
194
  supportsWebSearch: false,
202
195
  supportsThinking: true,
203
196
  supportsAdaptiveThinking: true, // Sonnet 4.6: thinking: {type: "adaptive"} recommended
@@ -230,7 +223,6 @@ const SUPPORTED_MODELS = {
230
223
  maxOutputTokens: 64000,
231
224
  supportsStreaming: true,
232
225
  supportsImages: true,
233
- supportsTemperature: true,
234
226
  supportsWebSearch: false,
235
227
  supportsThinking: true,
236
228
  minThinkingTokens: 1024,
@@ -255,7 +247,6 @@ const SUPPORTED_MODELS = {
255
247
  maxOutputTokens: 64000,
256
248
  supportsStreaming: true,
257
249
  supportsImages: true,
258
- supportsTemperature: true,
259
250
  supportsWebSearch: false,
260
251
  supportsThinking: true,
261
252
  minThinkingTokens: 1024,
@@ -550,14 +541,9 @@ export const anthropicProvider = {
550
541
  async invoke(messages, options = {}) {
551
542
  const {
552
543
  model = 'claude-3-5-sonnet-20241022',
553
- temperature = 0.7,
554
544
  maxTokens = null,
555
545
  stream = false,
556
546
  reasoning_effort = 'medium',
557
- // eslint-disable-next-line no-unused-vars
558
- use_websearch = false, // Not supported by Anthropic, ignored
559
- // eslint-disable-next-line no-unused-vars
560
- verbosity = 'medium', // OpenAI-specific parameter, ignored by Anthropic
561
547
  config,
562
548
  // Note: We don't use ...otherOptions because it can include non-API parameters
563
549
  // like continuationStore that cause "Extra inputs are not permitted" errors
@@ -704,22 +690,6 @@ export const anthropicProvider = {
704
690
  }
705
691
  }
706
692
 
707
- // Add temperature if specified and the model accepts it
708
- // (Fable 5 removed sampling parameters entirely - sending them returns 400)
709
- // When legacy thinking (type: "enabled") is active, temperature must be 1
710
- // Adaptive thinking (type: "adaptive") does not have this constraint
711
- if (temperature !== undefined && modelConfig.supportsTemperature !== false) {
712
- if (
713
- requestPayload.thinking &&
714
- requestPayload.thinking.type === 'enabled'
715
- ) {
716
- requestPayload.temperature = 1;
717
- debugLog('[Anthropic] Temperature forced to 1 for legacy thinking mode');
718
- } else {
719
- requestPayload.temperature = Math.max(0, Math.min(1, temperature));
720
- }
721
- }
722
-
723
693
  // Add effort parameter for models that support it (uses output_config)
724
694
  if (modelConfig.supportsEffort && reasoning_effort) {
725
695
  const effortValue = EFFORT_MAP[reasoning_effort];
@@ -764,7 +734,6 @@ export const anthropicProvider = {
764
734
  model: requestPayload.model,
765
735
  max_tokens: requestPayload.max_tokens,
766
736
  thinking: requestPayload.thinking,
767
- temperature: requestPayload.temperature,
768
737
  output_config: requestPayload.output_config,
769
738
  betas: requestPayload.betas,
770
739
  message_count: requestPayload.messages?.length,
@@ -28,7 +28,6 @@ const SUPPORTED_MODELS = {
28
28
  maxOutputTokens: 128000,
29
29
  supportsStreaming: true,
30
30
  supportsImages: true, // Supported via streaming input mode
31
- supportsTemperature: false, // SDK manages temperature internally
32
31
  supportsWebSearch: false, // SDK accesses files directly, not web
33
32
  timeout: 600000, // 10 minutes
34
33
  description:
@@ -50,7 +49,6 @@ const SUPPORTED_MODELS = {
50
49
  maxOutputTokens: 128000,
51
50
  supportsStreaming: true,
52
51
  supportsImages: true, // Supported via streaming input mode
53
- supportsTemperature: false, // SDK manages temperature internally
54
52
  supportsWebSearch: false, // SDK accesses files directly, not web
55
53
  timeout: 600000, // 10 minutes
56
54
  description:
@@ -451,8 +449,6 @@ export const claudeProvider = {
451
449
  stream = false,
452
450
  signal,
453
451
  reasoning_effort,
454
- temperature,
455
- use_websearch,
456
452
  } = options;
457
453
 
458
454
  // Validate configuration
@@ -464,16 +460,6 @@ export const claudeProvider = {
464
460
  }
465
461
 
466
462
  // Log unsupported parameters at debug level
467
- if (temperature !== undefined) {
468
- debugLog(
469
- '[Claude SDK] Parameter "temperature" not supported by Claude SDK (ignored)',
470
- );
471
- }
472
- if (use_websearch) {
473
- debugLog(
474
- '[Claude SDK] Parameter "use_websearch" not supported by Claude SDK (ignored)',
475
- );
476
- }
477
463
  if (reasoning_effort !== undefined) {
478
464
  debugLog(
479
465
  '[Claude SDK] Parameter "reasoning_effort" not supported by Claude SDK (ignored)',
@@ -26,7 +26,6 @@ const SUPPORTED_MODELS = {
26
26
  maxOutputTokens: 128000,
27
27
  supportsStreaming: true,
28
28
  supportsImages: true, // Codex SDK 0.118+ supports images via --image (local_image input)
29
- supportsTemperature: false, // Codex manages temperature internally
30
29
  supportsWebSearch: false, // Codex accesses files directly, not web
31
30
  timeout: 600000, // 10 minutes
32
31
  description:
@@ -104,7 +103,7 @@ async function getCodexSDK() {
104
103
  * passes local_image paths to the CLI via --image.
105
104
  *
106
105
  * Images must be on-disk files — Converse stores the original path in
107
- * metadata.path (chat.js / consensus.js set includeMetadata: true). Images
106
+ * metadata.path (chat.js sets includeMetadata: true). Images
108
107
  * without a path (e.g. pasted base64 with no metadata) are skipped.
109
108
  */
110
109
  function convertMessagesToCodexInput(messages) {
@@ -192,13 +191,20 @@ function extractPromptText(input) {
192
191
  }
193
192
 
194
193
  /**
195
- * Get thread ID from continuation metadata
196
- * Codex thread IDs are stored in continuation store for resumption
194
+ * Get thread ID from continuation metadata.
195
+ * Codex thread IDs are stored per call-plan in `providerThreads`, keyed by a
196
+ * stable `threadKey` (the requested model spec, e.g. "auto" or "codex") passed
197
+ * through provider options — NOT the resolved provider/model, so an "auto" spec
198
+ * that resolves to Codex still finds its thread on the next turn.
197
199
  */
198
- async function getThreadIdFromContinuation(continuationId, continuationStore) {
200
+ async function getThreadIdFromContinuation(
201
+ continuationId,
202
+ continuationStore,
203
+ threadKey,
204
+ ) {
199
205
  try {
200
206
  const state = await continuationStore.get(continuationId);
201
- return state?.codexThreadId || null;
207
+ return state?.providerThreads?.[threadKey] || null;
202
208
  } catch (error) {
203
209
  debugError('[Codex] Failed to retrieve continuation state', error);
204
210
  return null;
@@ -267,9 +273,8 @@ export const codexProvider = {
267
273
  signal,
268
274
  continuation_id,
269
275
  continuationStore,
276
+ threadKey,
270
277
  reasoning_effort,
271
- temperature,
272
- use_websearch,
273
278
  } = options;
274
279
 
275
280
  // Validate configuration
@@ -280,18 +285,6 @@ export const codexProvider = {
280
285
  );
281
286
  }
282
287
 
283
- // Log unsupported parameters at debug level
284
- if (temperature !== undefined) {
285
- debugLog(
286
- '[Codex] Parameter "temperature" not supported by Codex (ignored)',
287
- );
288
- }
289
- if (use_websearch) {
290
- debugLog(
291
- '[Codex] Parameter "use_websearch" not supported by Codex (ignored)',
292
- );
293
- }
294
-
295
288
  try {
296
289
  // Get Codex SDK
297
290
  const Codex = await getCodexSDK();
@@ -302,10 +295,11 @@ export const codexProvider = {
302
295
 
303
296
  // Get thread ID if resuming conversation
304
297
  const threadId =
305
- continuation_id && continuationStore
298
+ continuation_id && continuationStore && threadKey
306
299
  ? await getThreadIdFromContinuation(
307
300
  continuation_id,
308
301
  continuationStore,
302
+ threadKey,
309
303
  )
310
304
  : null;
311
305