converse-mcp-server 2.28.0 → 2.28.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "converse-mcp-server",
3
- "version": "2.28.0",
3
+ "version": "2.28.1",
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",
@@ -93,29 +93,29 @@
93
93
  ".env.example"
94
94
  ],
95
95
  "dependencies": {
96
- "@anthropic-ai/claude-agent-sdk": "^0.3.169",
97
- "@anthropic-ai/sdk": "^0.102.0",
98
- "@github/copilot-sdk": "^1.0.0",
99
- "@google/genai": "^2.8.0",
96
+ "@anthropic-ai/claude-agent-sdk": "^0.3.185",
97
+ "@anthropic-ai/sdk": "^0.105.0",
98
+ "@github/copilot-sdk": "^1.0.3",
99
+ "@google/genai": "^2.9.0",
100
100
  "@lydell/node-pty": "1.2.0-beta.12",
101
- "@mistralai/mistralai": "^2.2.5",
101
+ "@mistralai/mistralai": "^2.2.6",
102
102
  "@modelcontextprotocol/sdk": "^1.29.0",
103
- "@openai/codex-sdk": "^0.138.0",
104
- "ai": "^6.0.198",
103
+ "@openai/codex-sdk": "^0.141.0",
104
+ "ai": "^6.0.208",
105
105
  "cors": "^2.8.6",
106
106
  "dotenv": "^17.4.2",
107
107
  "express": "^5.2.1",
108
108
  "lru-cache": "^11.5.1",
109
- "nanoid": "^5.1.11",
110
- "openai": "^6.42.0",
109
+ "nanoid": "^5.1.15",
110
+ "openai": "^6.44.0",
111
111
  "p-limit": "^7.3.0",
112
112
  "vite": "^8.0.16"
113
113
  },
114
114
  "devDependencies": {
115
- "@vitest/coverage-v8": "^4.1.8",
115
+ "@vitest/coverage-v8": "^4.1.9",
116
116
  "cross-env": "^10.1.0",
117
- "eslint": "^10.4.1",
117
+ "eslint": "^10.5.0",
118
118
  "rimraf": "^6.1.3",
119
- "vitest": "^4.1.8"
119
+ "vitest": "^4.1.9"
120
120
  }
121
121
  }
package/src/config.js CHANGED
@@ -296,6 +296,12 @@ const CONFIG_SCHEMA = {
296
296
  description:
297
297
  'Default model for Copilot SDK sessions (e.g., gpt-5, claude-sonnet-4.5)',
298
298
  },
299
+ COPILOT_CLI_PATH: {
300
+ type: 'string',
301
+ required: false,
302
+ description:
303
+ 'Explicit path to the Copilot CLI runtime (index.js or copilot binary). Overrides automatic resolution.',
304
+ },
299
305
  },
300
306
 
301
307
  // MCP configuration
@@ -12,6 +12,9 @@
12
12
  * - Requires GitHub CLI authenticated (gh auth login) with active Copilot subscription
13
13
  */
14
14
 
15
+ import { existsSync } from 'node:fs';
16
+ import { delimiter, dirname, join } from 'node:path';
17
+ import { fileURLToPath } from 'node:url';
15
18
  import { debugLog, debugError } from '../utils/console.js';
16
19
  import { ProviderError, ErrorCodes, StopReasons } from './interface.js';
17
20
 
@@ -321,8 +324,10 @@ function isCopilotSDKAvailable() {
321
324
  */
322
325
  async function getCopilotSDK() {
323
326
  try {
324
- const { CopilotClient } = await import('@github/copilot-sdk');
325
- return CopilotClient;
327
+ const { CopilotClient, RuntimeConnection } = await import(
328
+ '@github/copilot-sdk'
329
+ );
330
+ return { CopilotClient, RuntimeConnection };
326
331
  } catch (error) {
327
332
  throw new CopilotProviderError(
328
333
  `Copilot SDK import failed: ${error.message}`,
@@ -332,6 +337,78 @@ async function getCopilotSDK() {
332
337
  }
333
338
  }
334
339
 
340
+ /**
341
+ * Locate a runnable `copilot` executable on PATH (e.g. a winget or global
342
+ * install). On Windows only real executables (.exe/.com) qualify — .cmd/.bat
343
+ * shims can't be spawned without a shell, and the SDK spawns the CLI without
344
+ * one, so handing it a shim would fail.
345
+ */
346
+ function findCopilotBinaryOnPath() {
347
+ const pathDirs = (process.env.PATH || process.env.Path || '')
348
+ .split(delimiter)
349
+ .filter(Boolean);
350
+ const exts = process.platform === 'win32' ? ['.exe', '.com'] : [''];
351
+ for (const dir of pathDirs) {
352
+ for (const ext of exts) {
353
+ const candidate = join(dir, `copilot${ext}`);
354
+ if (existsSync(candidate)) return candidate;
355
+ }
356
+ }
357
+ return null;
358
+ }
359
+
360
+ /**
361
+ * Resolve the Copilot CLI runtime path deterministically.
362
+ *
363
+ * The SDK's built-in resolver (getBundledCliPath) reconstructs
364
+ * `<@github/copilot root>/index.js` from the package's `./sdk` export. That
365
+ * assumption breaks across layouts — pnpm stores with multiple versions, global
366
+ * installs, and loader-style `@github/copilot` variants that ship no root
367
+ * `index.js` — and there is no escape hatch wired up, so a wrong/missing
368
+ * bundled copy takes down the whole provider (the "Copilot CLI not found at
369
+ * ...@github\index.js" failure). We own discovery here and hand the SDK an
370
+ * explicit, verified path so that entire class of resolution failures can't
371
+ * occur.
372
+ *
373
+ * Precedence: explicit override → bundled npm CLI (index.js, run via node) →
374
+ * `copilot` on PATH. Returns null to let the SDK fall back to its own
375
+ * resolution as a last resort (preserves behavior on flat installs).
376
+ */
377
+ function resolveCopilotCliPath(config) {
378
+ // 1. Explicit override (COPILOT_CLI_PATH via config or env)
379
+ const override =
380
+ config?.providers?.copilotclipath || process.env.COPILOT_CLI_PATH;
381
+ if (override && existsSync(override)) {
382
+ debugLog('[Copilot SDK] Using configured CLI path: %s', override);
383
+ return override;
384
+ }
385
+
386
+ // 2. Bundled npm CLI: resolve the @github/copilot/sdk export, walk to the
387
+ // package root, and use its index.js. A .js path is spawned via `node`, which
388
+ // also sidesteps Windows .cmd/.bat shim issues.
389
+ try {
390
+ const sdkEntry = fileURLToPath(import.meta.resolve('@github/copilot/sdk'));
391
+ const candidate = join(dirname(dirname(sdkEntry)), 'index.js');
392
+ if (existsSync(candidate)) {
393
+ debugLog('[Copilot SDK] Using bundled CLI: %s', candidate);
394
+ return candidate;
395
+ }
396
+ } catch {
397
+ // @github/copilot not resolvable from here — fall through.
398
+ }
399
+
400
+ // 3. Standalone `copilot` binary on PATH.
401
+ const binary = findCopilotBinaryOnPath();
402
+ if (binary) {
403
+ debugLog('[Copilot SDK] Using copilot binary from PATH: %s', binary);
404
+ return binary;
405
+ }
406
+
407
+ // 4. Nothing found — defer to the SDK's own resolution.
408
+ debugLog('[Copilot SDK] No CLI path resolved — deferring to SDK default');
409
+ return null;
410
+ }
411
+
335
412
  // Module-level singleton client
336
413
  let clientInstance = null;
337
414
  let clientInitPromise = null;
@@ -340,7 +417,7 @@ let clientInitPromise = null;
340
417
  * Get or create the singleton CopilotClient
341
418
  * The client manages the CLI process lifecycle via JSON-RPC
342
419
  */
343
- async function getCopilotClient(cwd) {
420
+ async function getCopilotClient(cwd, config) {
344
421
  if (clientInstance) {
345
422
  return clientInstance;
346
423
  }
@@ -350,12 +427,19 @@ async function getCopilotClient(cwd) {
350
427
  }
351
428
 
352
429
  clientInitPromise = (async () => {
353
- const CopilotClient = await getCopilotSDK();
430
+ const { CopilotClient, RuntimeConnection } = await getCopilotSDK();
354
431
  const workingDirectory = cwd || process.cwd();
355
- clientInstance = new CopilotClient({
432
+ const clientOptions = {
356
433
  useLoggedInUser: true,
357
434
  workingDirectory,
358
- });
435
+ };
436
+
437
+ const cliPath = resolveCopilotCliPath(config);
438
+ if (cliPath) {
439
+ clientOptions.connection = RuntimeConnection.forStdio({ path: cliPath });
440
+ }
441
+
442
+ clientInstance = new CopilotClient(clientOptions);
359
443
  await clientInstance.start();
360
444
  debugLog('[Copilot SDK] Client started (cwd: %s)', workingDirectory);
361
445
  return clientInstance;
@@ -795,7 +879,7 @@ async function* createStreamingGenerator(client, prompt, options, signal, config
795
879
  }
796
880
  }
797
881
 
798
- export { resolveModelAlias, resolveSessionModel };
882
+ export { resolveModelAlias, resolveSessionModel, resolveCopilotCliPath };
799
883
 
800
884
  /**
801
885
  * Copilot SDK Provider Implementation
@@ -831,7 +915,7 @@ export const copilotProvider = {
831
915
  }
832
916
  try {
833
917
  const cwd = config.server?.client_cwd || process.cwd();
834
- const client = await getCopilotClient(cwd);
918
+ const client = await getCopilotClient(cwd, config);
835
919
  const prompt = convertMessagesToPrompt(messages);
836
920
 
837
921
  const sessionModel = resolveSessionModel(model, config);