converse-mcp-server 2.26.1 → 2.27.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/docs/PROVIDERS.md CHANGED
@@ -37,12 +37,13 @@ This guide documents all supported AI providers in the Converse MCP Server and t
37
37
  - **Get Key**: [console.anthropic.com](https://console.anthropic.com/)
38
38
  - **Environment Variable**: `ANTHROPIC_API_KEY`
39
39
  - **Supported Models**:
40
- - `claude-opus-4-5-20250220` - Most capable with extended thinking (32K output)
41
- - `claude-opus-4-1-20250805` - Highest intelligence with extended thinking (32K output)
42
- - `claude-sonnet-4-5-20250929` - Enhanced reasoning with extended thinking (64K output)
43
- - `claude-sonnet-4-20250514` - Balanced performance with extended thinking (64K output)
44
- - `claude-haiku-4-5-20251001` - Fast and intelligent with extended thinking (64K output)
45
- - `claude-3-opus-20240229`, `claude-3-sonnet-20240229`, `claude-3-haiku-20240307` - Previous generation
40
+ - `claude-fable-5` (alias `fable`) - Most capable model for demanding reasoning and long-horizon agentic work (1M context, 128K output)
41
+ - `claude-opus-4-8` (alias `opus`) - Most capable Opus for complex reasoning and agentic coding (128K output)
42
+ - `claude-opus-4-7`, `claude-opus-4-6` - Previous Opus generations with adaptive thinking (128K output)
43
+ - `claude-opus-4-5-20251101`, `claude-opus-4-1-20250805` - Legacy Opus models (64K / 32K output)
44
+ - `claude-sonnet-4-6` (alias `sonnet`) - Best combination of speed and intelligence with adaptive thinking (64K output)
45
+ - `claude-sonnet-4-5-20250929` - Legacy Sonnet (64K output)
46
+ - `claude-haiku-4-5-20251001` (alias `haiku`) - Fast and intelligent with extended thinking (64K output)
46
47
 
47
48
  ### Mistral
48
49
  - **API Key Format**: 32+ character string
@@ -160,7 +161,7 @@ gemini
160
161
  "name": "consensus",
161
162
  "arguments": {
162
163
  "prompt": "Should we use TypeScript for this component?",
163
- "models": ["gemini", "gpt-5", "claude-sonnet-4"]
164
+ "models": ["gemini", "gpt-5", "claude-sonnet-4-6"]
164
165
  }
165
166
  }
166
167
  ```
@@ -177,6 +178,27 @@ gemini
177
178
  - **Model Routing**: `gemini` → CLI provider, specific names (e.g., `gemini-2.5-pro`) → API provider
178
179
  - **Models**: Only gemini-3-pro-preview vs full Gemini model family
179
180
 
181
+ ### Claude Agent SDK
182
+ - **Authentication**: Claude Code CLI login (no API key needed)
183
+ - **Setup Required**: Authenticate once with `claude login` (Claude Code CLI)
184
+ - **Environment Variables**: None (uses Claude Code credentials)
185
+ - **Supported Models**:
186
+ - `claude` (aliases: `claude-sdk`, `claude-code`) - Defaults to Claude Fable 5
187
+ - `claude:fable` - Claude Fable 5 explicitly
188
+ - `claude:opus` - Claude Opus 4.8
189
+ - Other `claude:`-prefixed names pass through to the SDK (e.g. `claude:claude-sonnet-4-6`)
190
+
191
+ **Key Features:**
192
+ - **Subscription Access**: Uses your Claude subscription instead of API credits
193
+ - **Local File Access**: Reads files directly from the working directory
194
+ - **Image Support**: Via the SDK's streaming input mode
195
+ - **SDK-Managed Parameters**: `temperature`, `use_websearch`, and `reasoning_effort` are managed internally (ignored if specified)
196
+
197
+ **Differences from Anthropic API Provider:**
198
+ - **Authentication**: Claude Code login vs `ANTHROPIC_API_KEY`
199
+ - **Billing**: Claude subscription vs pay-per-use API
200
+ - **Model Routing**: `claude` and `claude:*` → SDK provider; specific names (e.g., `claude-fable-5`, `opus`, `sonnet`) → API provider
201
+
180
202
  ## Configuration Examples
181
203
 
182
204
  ### Basic Configuration (.env file)
@@ -243,7 +265,7 @@ All providers support streaming responses for real-time output.
243
265
  - **Google**:
244
266
  - Gemini 3.0 Pro: Thinking levels (low/high) via `reasoning_effort` - always enabled
245
267
  - Gemini 2.5 Pro/Flash: Thinking budget (token-based) via `reasoning_effort`
246
- - **Anthropic**: All Claude 4 series models support extended thinking with `reasoning_effort`
268
+ - **Anthropic**: Claude Fable 5, Opus 4.6+, and Sonnet 4.6 use adaptive thinking (depth controlled by `reasoning_effort` via Anthropic's `effort` parameter); older Claude 4 models use budget-based extended thinking
247
269
  - **Codex**: Thread-based agentic reasoning with persistent context
248
270
  - **Others**: Standard inference only
249
271
 
@@ -257,29 +279,38 @@ When using the chat or consensus tools, specify models using their identifiers:
257
279
 
258
280
  ### Model Routing Logic
259
281
 
260
- 1. **Simple Names**: Models without "/" are routed by keyword matching:
282
+ 1. **SDK Providers** (exact matches and prefixes, checked first):
283
+ - `codex` → Codex
284
+ - `gemini`, `gemini-cli` → Gemini CLI
285
+ - `claude`, `claude-sdk`, `claude-code` and any `claude:`-prefixed name (e.g., `claude:fable`, `claude:opus`) → Claude Agent SDK
286
+ - `copilot`, `copilot-sdk`, `github-copilot` and any `copilot:`-prefixed name (e.g., `copilot:codex`) → Copilot SDK
287
+
288
+ 2. **Simple Names**: Other models without "/" are routed by keyword matching:
261
289
  - Contains "gpt", "o1", "o3", "o4" → OpenAI
262
- - Contains "claude", "opus", "sonnet", "haiku" → Anthropic
290
+ - Contains "claude", "fable", "opus", "sonnet", "haiku" → Anthropic
263
291
  - Contains "gemini", "flash", "pro" → Google
264
292
  - Contains "grok" → X.AI
265
293
  - Contains "mistral", "magistral" → Mistral
266
294
  - Contains "deepseek", "reasoner", "r1" → DeepSeek
267
295
  - Contains "qwen", "kimi", "k2" → OpenRouter
268
296
 
269
- 2. **Slash Format**: Models with "/" check native providers first:
297
+ 3. **Slash Format**: Models with "/" check native providers first:
270
298
  - If exact model exists in a native provider → Routes to that provider
271
299
  - If not found in any native provider → Routes to OpenRouter
272
300
  - This allows using models like "anthropic/claude-3.5-sonnet" via OpenRouter
273
301
 
274
- 3. **OpenRouter Auto**: Special aliases route to OpenRouter's auto-selection:
302
+ 4. **OpenRouter Auto**: Special aliases route to OpenRouter's auto-selection:
275
303
  - "openrouter/auto", "openrouter auto", "auto router", "auto-router"
276
304
 
277
305
  ```javascript
278
306
  // Chat tool examples
279
307
  {
280
308
  "model": "gpt-5", // OpenAI (keyword match)
281
- "model": "claude-opus-4", // Anthropic (keyword match, auto-resolves)
282
- "model": "sonnet", // Anthropic (keyword match)
309
+ "model": "fable", // Anthropic (keyword match -> claude-fable-5)
310
+ "model": "opus", // Anthropic (keyword match -> claude-opus-4-8)
311
+ "model": "sonnet", // Anthropic (keyword match -> claude-sonnet-4-6)
312
+ "model": "claude", // Claude Agent SDK (defaults to Claude Fable 5)
313
+ "model": "claude:opus", // Claude Agent SDK (Claude Opus 4.8)
283
314
  "model": "gemini-2.5-pro", // Google (keyword match)
284
315
  "model": "grok-4", // X.AI (keyword match)
285
316
  "model": "mistral-large", // Mistral (keyword match)
@@ -293,7 +324,7 @@ When using the chat or consensus tools, specify models using their identifiers:
293
324
  {
294
325
  "models": [
295
326
  {"model": "o3"},
296
- {"model": "claude-sonnet-4"},
327
+ {"model": "claude-sonnet-4-6"},
297
328
  {"model": "gemini-2.5-pro"}
298
329
  ]
299
330
  }
@@ -308,7 +339,8 @@ When using the chat or consensus tools, specify models using their identifiers:
308
339
 
309
340
  ### Model Not Found
310
341
  - Use exact model identifiers as listed above
311
- - Some providers support aliases (e.g., "claude" → "claude-sonnet-4-5")
342
+ - Some providers support aliases (e.g., "fable" → "claude-fable-5", "opus" → "claude-opus-4-8")
343
+ - Note: bare "claude" routes to the Claude Agent SDK provider, not the Anthropic API
312
344
  - Check provider documentation for model availability in your region
313
345
 
314
346
  ### Rate Limits
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "converse-mcp-server",
3
- "version": "2.26.1",
3
+ "version": "2.27.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",
@@ -94,30 +94,30 @@
94
94
  ".env.example"
95
95
  ],
96
96
  "dependencies": {
97
- "@anthropic-ai/claude-agent-sdk": "^0.3.152",
98
- "@anthropic-ai/sdk": "^0.99.0",
99
- "@github/copilot-sdk": "^0.3.0",
100
- "@google/genai": "^2.7.0",
101
- "@mistralai/mistralai": "^2.2.1",
97
+ "@anthropic-ai/claude-agent-sdk": "^0.3.169",
98
+ "@anthropic-ai/sdk": "^0.102.0",
99
+ "@github/copilot-sdk": "^1.0.0",
100
+ "@google/genai": "^2.8.0",
101
+ "@mistralai/mistralai": "^2.2.5",
102
102
  "@modelcontextprotocol/sdk": "^1.29.0",
103
- "@openai/codex-sdk": "^0.133.0",
104
- "ai": "^6.0.191",
103
+ "@openai/codex-sdk": "^0.138.0",
104
+ "ai": "^6.0.198",
105
105
  "ai-sdk-provider-gemini-cli": "^2.0.1",
106
106
  "cors": "^2.8.6",
107
107
  "dotenv": "^17.4.2",
108
108
  "express": "^5.2.1",
109
- "lru-cache": "^11.5.0",
109
+ "lru-cache": "^11.5.1",
110
110
  "nanoid": "^5.1.11",
111
- "openai": "^6.39.0",
111
+ "openai": "^6.42.0",
112
112
  "p-limit": "^7.3.0",
113
- "vite": "^8.0.14"
113
+ "vite": "^8.0.16"
114
114
  },
115
115
  "devDependencies": {
116
- "@vitest/coverage-v8": "^4.1.7",
116
+ "@vitest/coverage-v8": "^4.1.8",
117
117
  "cross-env": "^10.1.0",
118
- "eslint": "^10.4.0",
118
+ "eslint": "^10.4.1",
119
119
  "prettier": "^3.8.3",
120
120
  "rimraf": "^6.1.3",
121
- "vitest": "^4.1.7"
121
+ "vitest": "^4.1.8"
122
122
  }
123
123
  }
@@ -13,6 +13,32 @@ 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-fable-5': {
17
+ modelName: 'claude-fable-5',
18
+ friendlyName: 'Claude Fable 5',
19
+ contextWindow: 1000000, // 1M context by default - no beta header required
20
+ maxOutputTokens: 128000,
21
+ supportsStreaming: true,
22
+ supportsImages: true,
23
+ supportsTemperature: false, // Fable 5 rejects temperature/top_p/top_k (400)
24
+ supportsWebSearch: false,
25
+ supportsThinking: true,
26
+ supportsAdaptiveThinking: true, // Adaptive thinking is the only thinking mode
27
+ timeout: 600000,
28
+ supportsEffort: true,
29
+ effortGA: true,
30
+ supportsCompaction: true,
31
+ description:
32
+ 'Claude Fable 5 - Most capable model for the most demanding reasoning and long-horizon agentic work',
33
+ aliases: [
34
+ 'claude-fable-5',
35
+ 'claude-fable',
36
+ 'claude-5-fable',
37
+ 'fable-5',
38
+ 'fable5',
39
+ 'fable',
40
+ ],
41
+ },
16
42
  'claude-opus-4-8': {
17
43
  modelName: 'claude-opus-4-8',
18
44
  friendlyName: 'Claude Opus 4.8',
@@ -678,10 +704,11 @@ export const anthropicProvider = {
678
704
  }
679
705
  }
680
706
 
681
- // Add temperature if specified
707
+ // Add temperature if specified and the model accepts it
708
+ // (Fable 5 removed sampling parameters entirely - sending them returns 400)
682
709
  // When legacy thinking (type: "enabled") is active, temperature must be 1
683
710
  // Adaptive thinking (type: "adaptive") does not have this constraint
684
- if (temperature !== undefined) {
711
+ if (temperature !== undefined && modelConfig.supportsTemperature !== false) {
685
712
  if (
686
713
  requestPayload.thinking &&
687
714
  requestPayload.thinking.type === 'enabled'
@@ -16,20 +16,46 @@
16
16
  import { debugLog, debugError } from '../utils/console.js';
17
17
  import { ProviderError, ErrorCodes, StopReasons } from './interface.js';
18
18
 
19
+ // Default underlying model when the request is just "claude" (or "claude:fable")
20
+ const DEFAULT_SDK_MODEL = 'claude-fable-5';
21
+
19
22
  // Supported Claude SDK models with their configurations
20
23
  const SUPPORTED_MODELS = {
21
- claude: {
22
- modelName: 'claude',
23
- friendlyName: 'Claude (via Agent SDK)',
24
+ fable: {
25
+ modelName: 'claude-fable-5',
26
+ friendlyName: 'Claude Fable 5 (via Agent SDK)',
27
+ contextWindow: 1000000,
28
+ maxOutputTokens: 128000,
29
+ supportsStreaming: true,
30
+ supportsImages: true, // Supported via streaming input mode
31
+ supportsTemperature: false, // SDK manages temperature internally
32
+ supportsWebSearch: false, // SDK accesses files directly, not web
33
+ timeout: 600000, // 10 minutes
34
+ description:
35
+ 'Claude Fable 5 via Agent SDK (default) - requires claude login authentication',
36
+ aliases: [
37
+ 'claude',
38
+ 'claude-sdk',
39
+ 'claude-code',
40
+ 'claude:fable',
41
+ 'claude-fable-5',
42
+ 'claude-fable',
43
+ 'fable-5',
44
+ ],
45
+ },
46
+ opus: {
47
+ modelName: 'claude-opus-4-8',
48
+ friendlyName: 'Claude Opus 4.8 (via Agent SDK)',
24
49
  contextWindow: 200000,
25
- maxOutputTokens: 8192,
50
+ maxOutputTokens: 128000,
26
51
  supportsStreaming: true,
27
52
  supportsImages: true, // Supported via streaming input mode
28
53
  supportsTemperature: false, // SDK manages temperature internally
29
54
  supportsWebSearch: false, // SDK accesses files directly, not web
30
55
  timeout: 600000, // 10 minutes
31
- description: 'Claude via Agent SDK - requires claude login authentication',
32
- aliases: ['claude-sdk', 'claude-code'],
56
+ description:
57
+ 'Claude Opus 4.8 via Agent SDK - requires claude login authentication',
58
+ aliases: ['claude:opus', 'claude-opus-4-8'],
33
59
  },
34
60
  };
35
61
 
@@ -81,6 +107,61 @@ async function getClaudeSDK() {
81
107
  }
82
108
  }
83
109
 
110
+ /**
111
+ * Look up model config from SUPPORTED_MODELS by name or alias.
112
+ * Strips the claude: prefix first (e.g. "claude:opus" -> "opus").
113
+ */
114
+ function findModelConfig(modelName) {
115
+ if (typeof modelName !== 'string') return null;
116
+
117
+ let name = modelName.trim();
118
+ if (name.toLowerCase().startsWith('claude:')) {
119
+ name = name.slice('claude:'.length).trim();
120
+ }
121
+ if (!name) return SUPPORTED_MODELS.fable;
122
+
123
+ const nameLower = name.toLowerCase();
124
+
125
+ if (SUPPORTED_MODELS[nameLower]) {
126
+ return SUPPORTED_MODELS[nameLower];
127
+ }
128
+
129
+ for (const config of Object.values(SUPPORTED_MODELS)) {
130
+ if (
131
+ config.aliases &&
132
+ config.aliases.some((alias) => alias.toLowerCase() === nameLower)
133
+ ) {
134
+ return config;
135
+ }
136
+ }
137
+
138
+ return null;
139
+ }
140
+
141
+ /**
142
+ * Resolve the requested model to the underlying SDK model ID.
143
+ * - "claude" (and bare "claude:") defaults to Claude Fable 5
144
+ * - "claude:fable" / "claude:opus" select the specific model
145
+ * - Unknown names are passed through (after prefix stripping) so users can
146
+ * target any model ID the Agent SDK accepts (e.g. "claude:claude-sonnet-4-6")
147
+ */
148
+ function resolveSdkModel(modelName) {
149
+ if (typeof modelName !== 'string' || !modelName.trim()) {
150
+ return DEFAULT_SDK_MODEL;
151
+ }
152
+
153
+ const config = findModelConfig(modelName);
154
+ if (config) {
155
+ return config.modelName;
156
+ }
157
+
158
+ let name = modelName.trim();
159
+ if (name.toLowerCase().startsWith('claude:')) {
160
+ name = name.slice('claude:'.length).trim();
161
+ }
162
+ return name || DEFAULT_SDK_MODEL;
163
+ }
164
+
84
165
  /**
85
166
  * Convert message array to SDK input format
86
167
  * Claude SDK supports two modes:
@@ -209,7 +290,7 @@ async function* createSdkMessageGenerator(sdkMessage) {
209
290
  * @param {Function} queryFn - The SDK query function
210
291
  * @param {string|null} prompt - String prompt for single message mode, or null for streaming input mode
211
292
  * @param {Object|null} sdkMessage - SDK user message for streaming input mode (with images)
212
- * @param {Object} options - SDK options (cwd, etc.)
293
+ * @param {Object} options - SDK options (cwd, model, etc.)
213
294
  * @param {AbortSignal} signal - Abort signal for cancellation
214
295
  */
215
296
  async function* createStreamingGenerator(
@@ -223,7 +304,7 @@ async function* createStreamingGenerator(
223
304
  // Build query options
224
305
  // Use higher maxTurns to allow for file reading operations
225
306
  const queryOptions = {
226
- model: 'claude-opus-4-8', // Use Opus 4.8 for best quality
307
+ model: options.model || DEFAULT_SDK_MODEL,
227
308
  maxTurns: 20, // Allow multiple turns for file operations
228
309
  permissionMode: 'bypassPermissions', // Don't prompt for permissions
229
310
  };
@@ -259,14 +340,14 @@ async function* createStreamingGenerator(
259
340
  });
260
341
 
261
342
  let _sessionId = null;
262
- let _modelUsed = 'claude';
343
+ let _modelUsed = queryOptions.model;
263
344
  let _accumulatedContent = '';
264
345
 
265
346
  // Yield start event
266
347
  yield {
267
348
  type: 'start',
268
349
  provider: 'claude',
269
- model: 'claude',
350
+ model: queryOptions.model,
270
351
  };
271
352
 
272
353
  // Iterate over SDK messages
@@ -281,7 +362,7 @@ async function* createStreamingGenerator(
281
362
  case 'system':
282
363
  if (message.subtype === 'init') {
283
364
  _sessionId = message.session_id;
284
- _modelUsed = message.model || 'claude';
365
+ _modelUsed = message.model || queryOptions.model;
285
366
  debugLog(
286
367
  `[Claude SDK] Session initialized: ${_sessionId}, model: ${_modelUsed}`,
287
368
  );
@@ -414,9 +495,14 @@ export const claudeProvider = {
414
495
  debugLog('[Claude SDK] Using streaming input mode for image support');
415
496
  }
416
497
 
498
+ // Resolve requested model (claude/claude:fable -> claude-fable-5, claude:opus -> claude-opus-4-8)
499
+ const sdkModel = resolveSdkModel(model);
500
+ debugLog(`[Claude SDK] Resolved model "${model}" -> "${sdkModel}"`);
501
+
417
502
  // Build SDK options
418
503
  const sdkOptions = {
419
504
  cwd: config.server?.client_cwd || process.cwd(),
505
+ model: sdkModel,
420
506
  };
421
507
 
422
508
  // Streaming mode
@@ -459,7 +545,7 @@ export const claudeProvider = {
459
545
  rawResponse: { content, usage },
460
546
  metadata: {
461
547
  provider: 'claude',
462
- model,
548
+ model: sdkModel,
463
549
  usage: usage
464
550
  ? {
465
551
  input_tokens: usage.input_tokens || 0,
@@ -546,25 +632,9 @@ export const claudeProvider = {
546
632
 
547
633
  /**
548
634
  * Get model configuration for specific model
635
+ * Handles claude: prefixed names (e.g. "claude:opus", "claude:fable")
549
636
  */
550
637
  getModelConfig(modelName) {
551
- const modelNameLower = modelName.toLowerCase();
552
-
553
- // Check exact match
554
- if (SUPPORTED_MODELS[modelNameLower]) {
555
- return SUPPORTED_MODELS[modelNameLower];
556
- }
557
-
558
- // Check aliases
559
- for (const [_name, config] of Object.entries(SUPPORTED_MODELS)) {
560
- if (
561
- config.aliases &&
562
- config.aliases.some((alias) => alias.toLowerCase() === modelNameLower)
563
- ) {
564
- return config;
565
- }
566
- }
567
-
568
- return null;
638
+ return findModelConfig(modelName);
569
639
  },
570
640
  };
@@ -7,12 +7,11 @@
7
7
  * Key differences from traditional providers:
8
8
  * - Uses GitHub Copilot CLI subscription authentication - NOT API keys
9
9
  * - Manages a singleton CopilotClient (spawns CLI process via JSON-RPC)
10
- * - Creates a fresh CopilotSession per request, destroyed after each request
10
+ * - Creates a fresh CopilotSession per request, disconnected after each request
11
11
  * - Bridges SDK push-based events to pull-based async generator for streaming
12
12
  * - Requires GitHub CLI authenticated (gh auth login) with active Copilot subscription
13
13
  */
14
14
 
15
- import { register } from 'node:module';
16
15
  import { debugLog, debugError } from '../utils/console.js';
17
16
  import { ProviderError, ErrorCodes, StopReasons } from './interface.js';
18
17
 
@@ -317,28 +316,10 @@ function isCopilotSDKAvailable() {
317
316
  return _sdkAvailable;
318
317
  }
319
318
 
320
- /**
321
- * Register a module resolution hook to fix the extensionless
322
- * "vscode-jsonrpc/node" import in @github/copilot-sdk >=0.1.29.
323
- * The SDK's session.js imports "vscode-jsonrpc/node" without a .js extension,
324
- * which fails under Node.js strict ESM resolution. The hook rewrites it to
325
- * "vscode-jsonrpc/node.js". Runs once, works regardless of package manager.
326
- */
327
- let _hookRegistered = false;
328
- function ensureJsonrpcResolveHook() {
329
- if (_hookRegistered) return;
330
- _hookRegistered = true;
331
- register(`data:text/javascript,${encodeURIComponent(
332
- 'export function resolve(s,c,n){' +
333
- 'return s==="vscode-jsonrpc/node"?n("vscode-jsonrpc/node.js",c):n(s,c);}',
334
- )}`);
335
- }
336
-
337
319
  /**
338
320
  * Dynamically import Copilot SDK (lazy loading)
339
321
  */
340
322
  async function getCopilotSDK() {
341
- ensureJsonrpcResolveHook();
342
323
  try {
343
324
  const { CopilotClient } = await import('@github/copilot-sdk');
344
325
  return CopilotClient;
@@ -370,14 +351,13 @@ async function getCopilotClient(cwd) {
370
351
 
371
352
  clientInitPromise = (async () => {
372
353
  const CopilotClient = await getCopilotSDK();
354
+ const workingDirectory = cwd || process.cwd();
373
355
  clientInstance = new CopilotClient({
374
- autoStart: true,
375
- autoRestart: true,
376
356
  useLoggedInUser: true,
377
- cwd: cwd || process.cwd(),
357
+ workingDirectory,
378
358
  });
379
359
  await clientInstance.start();
380
- debugLog('[Copilot SDK] Client started (cwd: %s)', clientInstance.options?.cwd || cwd);
360
+ debugLog('[Copilot SDK] Client started (cwd: %s)', workingDirectory);
381
361
  return clientInstance;
382
362
  })();
383
363
 
@@ -808,9 +788,9 @@ async function* createStreamingGenerator(client, prompt, options, signal, config
808
788
  }
809
789
  } finally {
810
790
  try {
811
- await session.destroy();
812
- } catch (destroyError) {
813
- debugError('[Copilot SDK] Session destroy error', destroyError);
791
+ await session.disconnect();
792
+ } catch (disconnectError) {
793
+ debugError('[Copilot SDK] Session disconnect error', disconnectError);
814
794
  }
815
795
  }
816
796
  }
package/src/tools/chat.js CHANGED
@@ -599,6 +599,12 @@ export function mapModelToProvider(model, providers) {
599
599
  return 'claude';
600
600
  }
601
601
 
602
+ // Check claude: prefix (e.g., claude:fable, claude:opus) - routes to SDK provider
603
+ // Must be before keyword matching to prevent misrouting to Anthropic API
604
+ if (modelLower.startsWith('claude:')) {
605
+ return 'claude';
606
+ }
607
+
602
608
  // Check Copilot SDK (exact match only - routes to SDK provider)
603
609
  if (
604
610
  modelLower === 'copilot' ||
@@ -673,6 +679,7 @@ export function mapModelToProvider(model, providers) {
673
679
  // Anthropic models
674
680
  if (
675
681
  modelLower.includes('claude') ||
682
+ modelLower.includes('fable') ||
676
683
  modelLower.includes('opus') ||
677
684
  modelLower.includes('sonnet') ||
678
685
  modelLower.includes('haiku')
@@ -1149,7 +1156,7 @@ chatTool.inputSchema = {
1149
1156
  model: {
1150
1157
  type: 'string',
1151
1158
  description:
1152
- 'AI model to use. Examples: "auto" (recommended), "codex", "gemini", "claude", "copilot", "copilot:codex". Defaults to auto-selection.',
1159
+ 'AI model to use. Examples: "auto" (recommended), "codex", "gemini", "claude", "claude:fable", "claude:opus", "copilot", "copilot:codex". Defaults to auto-selection.',
1153
1160
  },
1154
1161
  files: {
1155
1162
  type: 'array',
@@ -803,6 +803,12 @@ function mapModelToProvider(model, providers) {
803
803
  return 'claude';
804
804
  }
805
805
 
806
+ // Check claude: prefix (e.g., claude:fable, claude:opus) - routes to SDK provider
807
+ // Must be before keyword matching to prevent misrouting to Anthropic API
808
+ if (modelLower.startsWith('claude:')) {
809
+ return 'claude';
810
+ }
811
+
806
812
  // Check Copilot SDK (exact match only - routes to SDK provider)
807
813
  if (
808
814
  modelLower === 'copilot' ||
@@ -877,6 +883,7 @@ function mapModelToProvider(model, providers) {
877
883
  // Anthropic models
878
884
  if (
879
885
  modelLower.includes('claude') ||
886
+ modelLower.includes('fable') ||
880
887
  modelLower.includes('opus') ||
881
888
  modelLower.includes('sonnet') ||
882
889
  modelLower.includes('haiku')
@@ -1705,7 +1712,7 @@ consensusTool.inputSchema = {
1705
1712
  items: { type: 'string' },
1706
1713
  minItems: 1,
1707
1714
  description:
1708
- 'List of models to consult. Examples: ["codex", "gemini", "claude", "copilot", "copilot:codex"]',
1715
+ 'List of models to consult. Examples: ["codex", "gemini", "claude", "claude:opus", "copilot", "copilot:codex"]',
1709
1716
  },
1710
1717
  files: {
1711
1718
  type: 'array',
@@ -89,6 +89,12 @@ export function mapModelToProvider(model, providers) {
89
89
  return 'claude';
90
90
  }
91
91
 
92
+ // Check claude: prefix (e.g., claude:fable, claude:opus) - routes to SDK provider
93
+ // Must be before keyword matching to prevent misrouting to Anthropic API
94
+ if (modelLower.startsWith('claude:')) {
95
+ return 'claude';
96
+ }
97
+
92
98
  // Check Copilot SDK (exact match only - routes to SDK provider)
93
99
  if (
94
100
  modelLower === 'copilot' ||
@@ -163,6 +169,7 @@ export function mapModelToProvider(model, providers) {
163
169
  // Anthropic models
164
170
  if (
165
171
  modelLower.includes('claude') ||
172
+ modelLower.includes('fable') ||
166
173
  modelLower.includes('opus') ||
167
174
  modelLower.includes('sonnet') ||
168
175
  modelLower.includes('haiku')