converse-mcp-server 2.16.0 → 2.17.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.16.0",
3
+ "version": "2.17.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",
@@ -94,14 +94,14 @@
94
94
  ".env.example"
95
95
  ],
96
96
  "dependencies": {
97
- "@anthropic-ai/claude-agent-sdk": "^0.2.49",
97
+ "@anthropic-ai/claude-agent-sdk": "^0.2.50",
98
98
  "@anthropic-ai/sdk": "^0.74.0",
99
99
  "@github/copilot-sdk": "^0.1.25",
100
100
  "@google/genai": "^1.42.0",
101
101
  "@mistralai/mistralai": "^1.14.0",
102
102
  "@modelcontextprotocol/sdk": "^1.26.0",
103
103
  "@openai/codex-sdk": "^0.101.0",
104
- "ai": "^6.0.94",
104
+ "ai": "^6.0.97",
105
105
  "ai-sdk-provider-gemini-cli": "^2.0.1",
106
106
  "cors": "^2.8.6",
107
107
  "dotenv": "^17.3.1",
@@ -115,7 +115,7 @@
115
115
  "devDependencies": {
116
116
  "@vitest/coverage-v8": "^4.0.18",
117
117
  "cross-env": "^10.1.0",
118
- "eslint": "^10.0.0",
118
+ "eslint": "^10.0.1",
119
119
  "prettier": "^3.8.1",
120
120
  "rimraf": "^6.1.3",
121
121
  "vitest": "^4.0.18"
@@ -27,9 +27,318 @@ const SUPPORTED_MODELS = {
27
27
  supportsWebSearch: false,
28
28
  timeout: 120000,
29
29
  description:
30
- 'GitHub Copilot via CLI SDK - requires copilot auth login authentication',
30
+ 'GitHub Copilot via CLI SDK - uses default or env-configured model',
31
31
  aliases: ['copilot-sdk', 'github-copilot'],
32
32
  },
33
+
34
+ // OpenAI models
35
+ 'gpt-4.1': {
36
+ modelName: 'gpt-4.1',
37
+ friendlyName: 'GPT-4.1 (via Copilot)',
38
+ contextWindow: 1047576,
39
+ maxOutputTokens: 32768,
40
+ supportsStreaming: true,
41
+ supportsImages: false,
42
+ supportsTemperature: false,
43
+ supportsWebSearch: false,
44
+ timeout: 120000,
45
+ description: 'OpenAI GPT-4.1 via Copilot subscription',
46
+ aliases: [],
47
+ },
48
+ 'gpt-5-mini': {
49
+ modelName: 'gpt-5-mini',
50
+ friendlyName: 'GPT-5 Mini (via Copilot)',
51
+ contextWindow: 1047576,
52
+ maxOutputTokens: 16384,
53
+ supportsStreaming: true,
54
+ supportsImages: false,
55
+ supportsTemperature: false,
56
+ supportsWebSearch: false,
57
+ timeout: 120000,
58
+ description: 'OpenAI GPT-5 Mini via Copilot subscription',
59
+ aliases: [],
60
+ },
61
+ 'gpt-5.1': {
62
+ modelName: 'gpt-5.1',
63
+ friendlyName: 'GPT-5.1 (via Copilot)',
64
+ contextWindow: 1047576,
65
+ maxOutputTokens: 32768,
66
+ supportsStreaming: true,
67
+ supportsImages: false,
68
+ supportsTemperature: false,
69
+ supportsWebSearch: false,
70
+ timeout: 120000,
71
+ description: 'OpenAI GPT-5.1 via Copilot subscription',
72
+ aliases: [],
73
+ },
74
+ 'gpt-5.1-codex': {
75
+ modelName: 'gpt-5.1-codex',
76
+ friendlyName: 'GPT-5.1 Codex (via Copilot)',
77
+ contextWindow: 192000,
78
+ maxOutputTokens: 16384,
79
+ supportsStreaming: true,
80
+ supportsImages: false,
81
+ supportsTemperature: false,
82
+ supportsWebSearch: false,
83
+ timeout: 300000,
84
+ description: 'OpenAI GPT-5.1 Codex via Copilot subscription',
85
+ aliases: [],
86
+ },
87
+ 'gpt-5.1-codex-mini': {
88
+ modelName: 'gpt-5.1-codex-mini',
89
+ friendlyName: 'GPT-5.1 Codex Mini (via Copilot)',
90
+ contextWindow: 192000,
91
+ maxOutputTokens: 16384,
92
+ supportsStreaming: true,
93
+ supportsImages: false,
94
+ supportsTemperature: false,
95
+ supportsWebSearch: false,
96
+ timeout: 300000,
97
+ description: 'OpenAI GPT-5.1 Codex Mini via Copilot subscription',
98
+ aliases: [],
99
+ },
100
+ 'gpt-5.1-codex-max': {
101
+ modelName: 'gpt-5.1-codex-max',
102
+ friendlyName: 'GPT-5.1 Codex Max (via Copilot)',
103
+ contextWindow: 192000,
104
+ maxOutputTokens: 16384,
105
+ supportsStreaming: true,
106
+ supportsImages: false,
107
+ supportsTemperature: false,
108
+ supportsWebSearch: false,
109
+ timeout: 600000,
110
+ description: 'OpenAI GPT-5.1 Codex Max via Copilot subscription',
111
+ aliases: [],
112
+ },
113
+ 'gpt-5.2': {
114
+ modelName: 'gpt-5.2',
115
+ friendlyName: 'GPT-5.2 (via Copilot)',
116
+ contextWindow: 1047576,
117
+ maxOutputTokens: 32768,
118
+ supportsStreaming: true,
119
+ supportsImages: false,
120
+ supportsTemperature: false,
121
+ supportsWebSearch: false,
122
+ timeout: 120000,
123
+ description: 'OpenAI GPT-5.2 via Copilot subscription',
124
+ aliases: ['gpt-5'],
125
+ },
126
+ 'gpt-5.2-codex': {
127
+ modelName: 'gpt-5.2-codex',
128
+ friendlyName: 'GPT-5.2 Codex (via Copilot)',
129
+ contextWindow: 192000,
130
+ maxOutputTokens: 16384,
131
+ supportsStreaming: true,
132
+ supportsImages: false,
133
+ supportsTemperature: false,
134
+ supportsWebSearch: false,
135
+ timeout: 300000,
136
+ description: 'OpenAI GPT-5.2 Codex via Copilot subscription',
137
+ aliases: [],
138
+ },
139
+ 'gpt-5.3-codex': {
140
+ modelName: 'gpt-5.3-codex',
141
+ friendlyName: 'GPT-5.3 Codex (via Copilot)',
142
+ contextWindow: 192000,
143
+ maxOutputTokens: 16384,
144
+ supportsStreaming: true,
145
+ supportsImages: false,
146
+ supportsTemperature: false,
147
+ supportsWebSearch: false,
148
+ timeout: 300000,
149
+ description: 'OpenAI GPT-5.3 Codex via Copilot subscription',
150
+ aliases: ['codex'],
151
+ },
152
+
153
+ // Anthropic models
154
+ 'claude-haiku-4.5': {
155
+ modelName: 'claude-haiku-4.5',
156
+ friendlyName: 'Claude Haiku 4.5 (via Copilot)',
157
+ contextWindow: 200000,
158
+ maxOutputTokens: 8192,
159
+ supportsStreaming: true,
160
+ supportsImages: false,
161
+ supportsTemperature: false,
162
+ supportsWebSearch: false,
163
+ timeout: 120000,
164
+ description: 'Anthropic Claude Haiku 4.5 via Copilot subscription',
165
+ aliases: ['haiku'],
166
+ },
167
+ 'claude-sonnet-4': {
168
+ modelName: 'claude-sonnet-4',
169
+ friendlyName: 'Claude Sonnet 4 (via Copilot)',
170
+ contextWindow: 200000,
171
+ maxOutputTokens: 16384,
172
+ supportsStreaming: true,
173
+ supportsImages: false,
174
+ supportsTemperature: false,
175
+ supportsWebSearch: false,
176
+ timeout: 120000,
177
+ description: 'Anthropic Claude Sonnet 4 via Copilot subscription',
178
+ aliases: [],
179
+ },
180
+ 'claude-sonnet-4.5': {
181
+ modelName: 'claude-sonnet-4.5',
182
+ friendlyName: 'Claude Sonnet 4.5 (via Copilot)',
183
+ contextWindow: 200000,
184
+ maxOutputTokens: 16384,
185
+ supportsStreaming: true,
186
+ supportsImages: false,
187
+ supportsTemperature: false,
188
+ supportsWebSearch: false,
189
+ timeout: 120000,
190
+ description: 'Anthropic Claude Sonnet 4.5 via Copilot subscription',
191
+ aliases: [],
192
+ },
193
+ 'claude-sonnet-4.6': {
194
+ modelName: 'claude-sonnet-4.6',
195
+ friendlyName: 'Claude Sonnet 4.6 (via Copilot)',
196
+ contextWindow: 200000,
197
+ maxOutputTokens: 16384,
198
+ supportsStreaming: true,
199
+ supportsImages: false,
200
+ supportsTemperature: false,
201
+ supportsWebSearch: false,
202
+ timeout: 120000,
203
+ description: 'Anthropic Claude Sonnet 4.6 via Copilot subscription',
204
+ aliases: ['sonnet'],
205
+ },
206
+ 'claude-opus-4.5': {
207
+ modelName: 'claude-opus-4.5',
208
+ friendlyName: 'Claude Opus 4.5 (via Copilot)',
209
+ contextWindow: 200000,
210
+ maxOutputTokens: 32768,
211
+ supportsStreaming: true,
212
+ supportsImages: false,
213
+ supportsTemperature: false,
214
+ supportsWebSearch: false,
215
+ timeout: 300000,
216
+ description: 'Anthropic Claude Opus 4.5 via Copilot subscription',
217
+ aliases: [],
218
+ },
219
+ 'claude-opus-4.6': {
220
+ modelName: 'claude-opus-4.6',
221
+ friendlyName: 'Claude Opus 4.6 (via Copilot)',
222
+ contextWindow: 200000,
223
+ maxOutputTokens: 32768,
224
+ supportsStreaming: true,
225
+ supportsImages: false,
226
+ supportsTemperature: false,
227
+ supportsWebSearch: false,
228
+ timeout: 300000,
229
+ description: 'Anthropic Claude Opus 4.6 via Copilot subscription',
230
+ aliases: ['opus'],
231
+ },
232
+ 'claude-opus-4.6-fast': {
233
+ modelName: 'claude-opus-4.6-fast',
234
+ friendlyName: 'Claude Opus 4.6 Fast (via Copilot)',
235
+ contextWindow: 200000,
236
+ maxOutputTokens: 32768,
237
+ supportsStreaming: true,
238
+ supportsImages: false,
239
+ supportsTemperature: false,
240
+ supportsWebSearch: false,
241
+ timeout: 300000,
242
+ description: 'Anthropic Claude Opus 4.6 Fast mode via Copilot subscription',
243
+ aliases: [],
244
+ },
245
+
246
+ // Google models
247
+ 'gemini-2.5-pro': {
248
+ modelName: 'gemini-2.5-pro',
249
+ friendlyName: 'Gemini 2.5 Pro (via Copilot)',
250
+ contextWindow: 1048576,
251
+ maxOutputTokens: 65536,
252
+ supportsStreaming: true,
253
+ supportsImages: false,
254
+ supportsTemperature: false,
255
+ supportsWebSearch: false,
256
+ timeout: 300000,
257
+ description: 'Google Gemini 2.5 Pro via Copilot subscription',
258
+ aliases: ['gemini'],
259
+ },
260
+ 'gemini-3-flash-preview': {
261
+ modelName: 'gemini-3-flash-preview',
262
+ friendlyName: 'Gemini 3 Flash Preview (via Copilot)',
263
+ contextWindow: 1048576,
264
+ maxOutputTokens: 65536,
265
+ supportsStreaming: true,
266
+ supportsImages: false,
267
+ supportsTemperature: false,
268
+ supportsWebSearch: false,
269
+ timeout: 120000,
270
+ description: 'Google Gemini 3 Flash Preview via Copilot subscription',
271
+ aliases: ['flash', 'gemini-3-flash'],
272
+ },
273
+ 'gemini-3-pro-preview': {
274
+ modelName: 'gemini-3-pro-preview',
275
+ friendlyName: 'Gemini 3 Pro Preview (via Copilot)',
276
+ contextWindow: 1048576,
277
+ maxOutputTokens: 65536,
278
+ supportsStreaming: true,
279
+ supportsImages: false,
280
+ supportsTemperature: false,
281
+ supportsWebSearch: false,
282
+ timeout: 300000,
283
+ description: 'Google Gemini 3 Pro Preview via Copilot subscription',
284
+ aliases: ['gemini-3-pro'],
285
+ },
286
+ 'gemini-3.1-pro-preview': {
287
+ modelName: 'gemini-3.1-pro-preview',
288
+ friendlyName: 'Gemini 3.1 Pro Preview (via Copilot)',
289
+ contextWindow: 1048576,
290
+ maxOutputTokens: 65536,
291
+ supportsStreaming: true,
292
+ supportsImages: false,
293
+ supportsTemperature: false,
294
+ supportsWebSearch: false,
295
+ timeout: 300000,
296
+ description: 'Google Gemini 3.1 Pro Preview via Copilot subscription',
297
+ aliases: ['gemini-3.1-pro'],
298
+ },
299
+
300
+ // xAI models
301
+ 'grok-code-fast-1': {
302
+ modelName: 'grok-code-fast-1',
303
+ friendlyName: 'Grok Code Fast 1 (via Copilot)',
304
+ contextWindow: 131072,
305
+ maxOutputTokens: 16384,
306
+ supportsStreaming: true,
307
+ supportsImages: false,
308
+ supportsTemperature: false,
309
+ supportsWebSearch: false,
310
+ timeout: 120000,
311
+ description: 'xAI Grok Code Fast 1 via Copilot subscription',
312
+ aliases: ['grok'],
313
+ },
314
+
315
+ // Fine-tuned / specialized models
316
+ 'raptor-mini': {
317
+ modelName: 'raptor-mini',
318
+ friendlyName: 'Raptor Mini (via Copilot)',
319
+ contextWindow: 128000,
320
+ maxOutputTokens: 16384,
321
+ supportsStreaming: true,
322
+ supportsImages: false,
323
+ supportsTemperature: false,
324
+ supportsWebSearch: false,
325
+ timeout: 120000,
326
+ description: 'GitHub fine-tuned Raptor Mini via Copilot subscription',
327
+ aliases: [],
328
+ },
329
+ goldeneye: {
330
+ modelName: 'goldeneye',
331
+ friendlyName: 'Goldeneye (via Copilot)',
332
+ contextWindow: 128000,
333
+ maxOutputTokens: 16384,
334
+ supportsStreaming: true,
335
+ supportsImages: false,
336
+ supportsTemperature: false,
337
+ supportsWebSearch: false,
338
+ timeout: 120000,
339
+ description: 'GitHub Goldeneye model via Copilot subscription',
340
+ aliases: [],
341
+ },
33
342
  };
34
343
 
35
344
  class CopilotProviderError extends ProviderError {
@@ -196,28 +505,76 @@ function createPermissionHandler(accessLevel) {
196
505
  };
197
506
  }
198
507
 
508
+ /**
509
+ * Resolve a friendly alias to its SDK model identifier (case-insensitive)
510
+ * Returns the resolved model name, or null if no alias matches
511
+ */
512
+ function resolveModelAlias(name) {
513
+ if (typeof name !== 'string') return null;
514
+ const lower = name.toLowerCase().trim();
515
+ if (!lower) return null;
516
+
517
+ // Direct key match
518
+ if (SUPPORTED_MODELS[lower] && lower !== 'copilot') {
519
+ return SUPPORTED_MODELS[lower].modelName;
520
+ }
521
+
522
+ // Alias match
523
+ for (const config of Object.values(SUPPORTED_MODELS)) {
524
+ if (config.modelName === 'copilot') continue;
525
+ if (
526
+ config.aliases &&
527
+ config.aliases.some((alias) => alias.toLowerCase() === lower)
528
+ ) {
529
+ return config.modelName;
530
+ }
531
+ }
532
+
533
+ return null;
534
+ }
535
+
199
536
  /**
200
537
  * Resolve model to pass to SDK session
201
538
  * Precedence: explicit model param > config COPILOT_MODEL > omit (SDK default)
202
539
  *
540
+ * Handles copilot: prefix stripping, alias resolution, and env var fallback.
203
541
  * Note: "copilot" is a Converse routing alias, not a valid SDK model ID.
204
- * Only pass through model names that are actual SDK model IDs.
205
542
  */
206
543
  function resolveSessionModel(requestModel, config) {
207
544
  const converseAliases = ['copilot', 'copilot-sdk', 'github-copilot'];
208
545
 
209
- // If user specified a non-alias model name, pass it to SDK
210
- if (requestModel && !converseAliases.includes(requestModel.toLowerCase())) {
211
- return requestModel;
546
+ // Guard non-string inputs
547
+ if (typeof requestModel !== 'string') {
548
+ requestModel = '';
549
+ }
550
+
551
+ // Strip copilot: prefix (case-insensitive)
552
+ let effectiveModel = requestModel;
553
+ if (effectiveModel.toLowerCase().startsWith('copilot:')) {
554
+ effectiveModel = effectiveModel.slice('copilot:'.length).trim();
212
555
  }
213
556
 
214
- // Fall back to config value
215
- if (config?.providers?.copilotmodel) {
216
- return config.providers.copilotmodel;
557
+ // Empty suffix or converse alias → use env/default
558
+ if (
559
+ !effectiveModel ||
560
+ converseAliases.includes(effectiveModel.toLowerCase())
561
+ ) {
562
+ const envModel = config?.providers?.copilotmodel;
563
+ if (envModel) {
564
+ let resolved = typeof envModel === 'string' ? envModel : '';
565
+ if (resolved.toLowerCase().startsWith('copilot:')) {
566
+ resolved = resolved.slice('copilot:'.length).trim();
567
+ }
568
+ if (!resolved || converseAliases.includes(resolved.toLowerCase())) {
569
+ return undefined;
570
+ }
571
+ return resolveModelAlias(resolved) || resolved;
572
+ }
573
+ return undefined;
217
574
  }
218
575
 
219
- // Omit let SDK use its default
220
- return undefined;
576
+ // Resolve alias or passthrough unknown models to SDK
577
+ return resolveModelAlias(effectiveModel) || effectiveModel;
221
578
  }
222
579
 
223
580
  /**
@@ -376,6 +733,8 @@ async function* createStreamingGenerator(client, prompt, options, signal, config
376
733
  }
377
734
  }
378
735
 
736
+ export { resolveModelAlias, resolveSessionModel };
737
+
379
738
  /**
380
739
  * Copilot SDK Provider Implementation
381
740
  */
@@ -419,6 +778,7 @@ export const copilotProvider = {
419
778
  const client = await getCopilotClient(cwd);
420
779
  const prompt = convertMessagesToPrompt(messages);
421
780
 
781
+ const sessionModel = resolveSessionModel(model, config);
422
782
  const modelConfig = SUPPORTED_MODELS.copilot;
423
783
  const invokeOptions = {
424
784
  model,
@@ -458,13 +818,13 @@ export const copilotProvider = {
458
818
  rawResponse: { content, usage },
459
819
  metadata: {
460
820
  provider: 'copilot',
461
- model,
821
+ model: sessionModel || 'copilot',
462
822
  usage: usage
463
823
  ? {
464
824
  input_tokens: usage.input_tokens || 0,
465
825
  output_tokens: usage.output_tokens || 0,
466
826
  total_tokens:
467
- (usage.input_tokens || 0) + (usage.output_tokens || 0),
827
+ (usage.input_tokens || 0) + (usage.output_tokens || 0),
468
828
  cached_input_tokens: usage.cached_input_tokens || 0,
469
829
  }
470
830
  : null,
@@ -533,16 +893,24 @@ export const copilotProvider = {
533
893
  },
534
894
 
535
895
  getModelConfig(modelName) {
536
- const modelNameLower = modelName.toLowerCase();
896
+ if (typeof modelName !== 'string') return null;
897
+
898
+ let name = modelName;
899
+ if (name.toLowerCase().startsWith('copilot:')) {
900
+ name = name.slice('copilot:'.length).trim();
901
+ }
902
+ if (!name) return SUPPORTED_MODELS.copilot;
903
+
904
+ const nameLower = name.toLowerCase();
537
905
 
538
- if (SUPPORTED_MODELS[modelNameLower]) {
539
- return SUPPORTED_MODELS[modelNameLower];
906
+ if (SUPPORTED_MODELS[nameLower]) {
907
+ return SUPPORTED_MODELS[nameLower];
540
908
  }
541
909
 
542
- for (const [_name, config] of Object.entries(SUPPORTED_MODELS)) {
910
+ for (const config of Object.values(SUPPORTED_MODELS)) {
543
911
  if (
544
912
  config.aliases &&
545
- config.aliases.some((alias) => alias.toLowerCase() === modelNameLower)
913
+ config.aliases.some((alias) => alias.toLowerCase() === nameLower)
546
914
  ) {
547
915
  return config;
548
916
  }
package/src/tools/chat.js CHANGED
@@ -584,6 +584,12 @@ export function mapModelToProvider(model, providers) {
584
584
  return 'copilot';
585
585
  }
586
586
 
587
+ // Check copilot: prefix (e.g., copilot:gpt-5.2, copilot:claude-sonnet-4.6)
588
+ // Must be before slash-format and keyword matching to prevent misrouting
589
+ if (modelLower.startsWith('copilot:')) {
590
+ return 'copilot';
591
+ }
592
+
587
593
  // Check OpenRouter-specific patterns first
588
594
  if (
589
595
  modelLower === 'openrouter auto' ||
@@ -787,6 +787,12 @@ function mapModelToProvider(model, providers) {
787
787
  return 'copilot';
788
788
  }
789
789
 
790
+ // Check copilot: prefix (e.g., copilot:gpt-5.2, copilot:claude-sonnet-4.6)
791
+ // Must be before slash-format and keyword matching to prevent misrouting
792
+ if (modelLower.startsWith('copilot:')) {
793
+ return 'copilot';
794
+ }
795
+
790
796
  // Check OpenRouter-specific patterns first
791
797
  if (
792
798
  modelLower === 'openrouter auto' ||