converse-mcp-server 2.6.0 → 2.7.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "converse-mcp-server",
3
- "version": "2.6.0",
3
+ "version": "2.7.0",
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",
@@ -13,6 +13,35 @@ import { ProviderError, ErrorCodes, StopReasons } from './interface.js';
13
13
 
14
14
  // Define supported Claude models with their capabilities
15
15
  const SUPPORTED_MODELS = {
16
+ 'claude-opus-4-5-20251101': {
17
+ modelName: 'claude-opus-4-5-20251101',
18
+ friendlyName: 'Claude Opus 4.5',
19
+ contextWindow: 200000,
20
+ maxOutputTokens: 64000,
21
+ supportsStreaming: true,
22
+ supportsImages: true,
23
+ supportsTemperature: true,
24
+ supportsWebSearch: false,
25
+ supportsThinking: true,
26
+ minThinkingTokens: 1024,
27
+ maxThinkingTokens: 64000,
28
+ timeout: 300000,
29
+ supportsEffort: true, // Opus 4.5 exclusive effort parameter
30
+ description:
31
+ 'Claude Opus 4.5 - Most intelligent model combining maximum capability with practical performance',
32
+ aliases: [
33
+ 'claude-opus-4-5',
34
+ 'claude-4.5-opus',
35
+ 'claude-4-5-opus',
36
+ 'opus-4.5',
37
+ 'opus-4-5',
38
+ 'opus4.5',
39
+ 'opus4-5',
40
+ 'claude-opus-4.5',
41
+ 'opus',
42
+ 'claude-opus',
43
+ ],
44
+ },
16
45
  'claude-opus-4-1-20250805': {
17
46
  modelName: 'claude-opus-4-1-20250805',
18
47
  friendlyName: 'Claude Opus 4.1',
@@ -36,11 +65,9 @@ const SUPPORTED_MODELS = {
36
65
  'opus-4-1',
37
66
  'claude-4-opus',
38
67
  'opus-4',
39
- 'opus',
40
- 'claude-opus',
41
- 'claude-opus-4',
42
68
  'opus4',
43
69
  'opus4.1',
70
+ 'claude-opus-4',
44
71
  'claude-opus-4.1',
45
72
  ],
46
73
  },
@@ -202,6 +229,18 @@ const THINKING_BUDGETS = {
202
229
  max: 1.0, // 100% of max thinking tokens
203
230
  };
204
231
 
232
+ /**
233
+ * Effort parameter mapping for Opus 4.5
234
+ * Maps reasoning_effort values to Anthropic's effort parameter values
235
+ */
236
+ const EFFORT_MAP = {
237
+ minimal: 'low',
238
+ low: 'low',
239
+ medium: 'medium',
240
+ high: 'high',
241
+ max: 'high',
242
+ };
243
+
205
244
  /**
206
245
  * Custom error class for Anthropic provider errors
207
246
  */
@@ -496,6 +535,14 @@ export const anthropicProvider = {
496
535
  );
497
536
  }
498
537
 
538
+ // Add effort beta feature for Opus 4.5
539
+ if (modelConfig.supportsEffort && reasoning_effort) {
540
+ betas.push('effort-2025-11-24');
541
+ debugLog(
542
+ `[Anthropic] Model ${resolvedModel} supports effort parameter with beta feature`,
543
+ );
544
+ }
545
+
499
546
  // Convert messages to Anthropic format (system messages are always cached)
500
547
  const { systemPrompt, messages: anthropicMessages } =
501
548
  convertMessagesToAnthropic(messages);
@@ -539,12 +586,14 @@ export const anthropicProvider = {
539
586
  // For other models, check against max_tokens if set
540
587
  const maxTokensLimit =
541
588
  requestPayload.max_tokens ||
542
- (resolvedModel.includes('claude-opus-4')
543
- ? 32000
544
- : resolvedModel.includes('claude-sonnet-4-5') ||
545
- resolvedModel.includes('claude-sonnet-4')
546
- ? 64000
547
- : modelConfig.maxOutputTokens);
589
+ (resolvedModel.includes('claude-opus-4-5')
590
+ ? 64000
591
+ : resolvedModel.includes('claude-opus-4')
592
+ ? 32000
593
+ : resolvedModel.includes('claude-sonnet-4-5') ||
594
+ resolvedModel.includes('claude-sonnet-4')
595
+ ? 64000
596
+ : modelConfig.maxOutputTokens);
548
597
 
549
598
  if (thinkingBudget > 0 && thinkingBudget < maxTokensLimit) {
550
599
  // According to Anthropic docs: thinking tokens count towards max_tokens limit
@@ -574,6 +623,19 @@ export const anthropicProvider = {
574
623
  }
575
624
  }
576
625
 
626
+ // Add effort parameter for Opus 4.5 (uses output_config)
627
+ if (modelConfig.supportsEffort && reasoning_effort && reasoning_effort !== 'none') {
628
+ const effortValue = EFFORT_MAP[reasoning_effort];
629
+ if (effortValue) {
630
+ requestPayload.output_config = {
631
+ effort: effortValue,
632
+ };
633
+ debugLog(
634
+ `[Anthropic] Effort parameter set to "${effortValue}" for ${resolvedModel} (from reasoning_effort: ${reasoning_effort})`,
635
+ );
636
+ }
637
+ }
638
+
577
639
  // If streaming is requested and model doesn't support it, fall back to non-streaming
578
640
  if (stream && modelConfig.supportsStreaming === false) {
579
641
  debugLog(
@@ -605,6 +667,7 @@ export const anthropicProvider = {
605
667
  max_tokens: requestPayload.max_tokens,
606
668
  thinking: requestPayload.thinking,
607
669
  temperature: requestPayload.temperature,
670
+ output_config: requestPayload.output_config,
608
671
  betas: requestPayload.betas,
609
672
  message_count: requestPayload.messages?.length,
610
673
  system_length: Array.isArray(requestPayload.system)
@@ -513,13 +513,38 @@ Please provide your refined response:`;
513
513
  // Save conversation state
514
514
  let conversationState;
515
515
  try {
516
+ // Build formatted consensus response with actual model responses
517
+ let formattedContent = '';
518
+
519
+ // Add initial responses
520
+ formattedContent += '## Initial Responses\n\n';
521
+ for (const result of initialPhase.successful) {
522
+ formattedContent += `### ${result.model} (initial response):\n${result.response}\n\n---\n\n`;
523
+ }
524
+
525
+ // Add refined responses if cross-feedback was enabled
526
+ if (refinedPhase) {
527
+ formattedContent += '## Refined Responses\n\n';
528
+ for (const result of refinedPhase) {
529
+ if (result.status === 'success' && result.refined_response) {
530
+ formattedContent += `### ${result.model} (refined response):\n${result.refined_response}\n\n---\n\n`;
531
+ } else if (result.status === 'partial') {
532
+ // Show initial response for models that failed refinement
533
+ formattedContent += `### ${result.model} (refinement failed, showing initial):\n${result.initial_response}\n\n---\n\n`;
534
+ }
535
+ }
536
+ }
537
+
538
+ // Add summary at the end
539
+ formattedContent += `\n**Summary:** Consensus completed with ${initialPhase.successful.length} successful initial responses`;
540
+ if (refinedPhase) {
541
+ const successfulRefinements = refinedPhase.filter(r => r.status === 'success').length;
542
+ formattedContent += ` and ${successfulRefinements} successful refined responses`;
543
+ }
544
+ formattedContent += '.';
516
545
  const consensusMessage = {
517
546
  role: 'assistant',
518
- content:
519
- `Consensus completed with ${initialPhase.successful.length} successful responses` +
520
- (refinedPhase
521
- ? ` and ${refinedPhase.filter((r) => r.status === 'success').length} refined responses`
522
- : ''),
547
+ content: formattedContent,
523
548
  };
524
549
 
525
550
  conversationState = {
@@ -548,7 +573,7 @@ Please provide your refined response:`;
548
573
  await exportConversation(conversationState, {
549
574
  clientCwd: dependencies.config.server?.client_cwd,
550
575
  continuation_id: continuationId,
551
- models: models.join(','),
576
+ models,
552
577
  temperature,
553
578
  reasoning_effort,
554
579
  use_websearch,
@@ -1187,13 +1212,38 @@ Please provide your refined response:`;
1187
1212
  // Save conversation state
1188
1213
  let conversationState;
1189
1214
  try {
1215
+ // Build formatted consensus response with actual model responses
1216
+ let formattedContent = '';
1217
+
1218
+ // Add initial responses
1219
+ formattedContent += '## Initial Responses\n\n';
1220
+ for (const result of initialPhase.successful) {
1221
+ formattedContent += `### ${result.model} (initial response):\n${result.response}\n\n---\n\n`;
1222
+ }
1223
+
1224
+ // Add refined responses if cross-feedback was enabled
1225
+ if (refinedPhase) {
1226
+ formattedContent += '## Refined Responses\n\n';
1227
+ for (const result of refinedPhase) {
1228
+ if (result.status === 'success' && result.refined_response) {
1229
+ formattedContent += `### ${result.model} (refined response):\n${result.refined_response}\n\n---\n\n`;
1230
+ } else if (result.status === 'partial') {
1231
+ // Show initial response for models that failed refinement
1232
+ formattedContent += `### ${result.model} (refinement failed, showing initial):\n${result.initial_response}\n\n---\n\n`;
1233
+ }
1234
+ }
1235
+ }
1236
+
1237
+ // Add summary at the end
1238
+ formattedContent += `\n**Summary:** Consensus completed with ${initialPhase.successful.length} successful initial responses`;
1239
+ if (refinedPhase) {
1240
+ const successfulRefinements = refinedPhase.filter(r => r.status === 'success').length;
1241
+ formattedContent += ` and ${successfulRefinements} successful refined responses`;
1242
+ }
1243
+ formattedContent += '.';
1190
1244
  const consensusMessage = {
1191
1245
  role: 'assistant',
1192
- content:
1193
- `Consensus completed with ${initialPhase.successful.length} successful responses` +
1194
- (refinedPhase
1195
- ? ` and ${refinedPhase.filter((r) => r.status === 'success').length} refined responses`
1196
- : ''),
1246
+ content: formattedContent,
1197
1247
  };
1198
1248
 
1199
1249
  conversationState = {
@@ -1218,7 +1268,7 @@ Please provide your refined response:`;
1218
1268
  await exportConversation(conversationState, {
1219
1269
  clientCwd: config.server?.client_cwd,
1220
1270
  continuation_id: continuationId,
1221
- models: models.join(','),
1271
+ models,
1222
1272
  temperature,
1223
1273
  reasoning_effort,
1224
1274
  use_websearch,
@@ -200,6 +200,8 @@ export async function exportConversation(conversationState, options = {}) {
200
200
  use_websearch,
201
201
  files,
202
202
  images,
203
+ models,
204
+ enable_cross_feedback,
203
205
  } = options;
204
206
 
205
207
  if (!continuation_id) {
@@ -256,6 +258,8 @@ export async function exportConversation(conversationState, options = {}) {
256
258
  use_websearch,
257
259
  files,
258
260
  images,
261
+ models,
262
+ enable_cross_feedback,
259
263
  });
260
264
 
261
265
  const metadataPath = path.join(exportDir, 'metadata.json');