converse-mcp-server 3.3.0 → 3.4.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/.env.example +3 -3
- package/README.md +4 -1
- package/docs/API.md +3 -2
- package/docs/PROVIDERS.md +4 -2
- package/package.json +8 -8
- package/src/config.js +2 -2
- package/src/providers/codex.js +117 -31
- package/src/utils/modelRouting.js +5 -3
package/.env.example
CHANGED
|
@@ -80,9 +80,9 @@ OPENROUTER_API_KEY=your_openrouter_api_key_here
|
|
|
80
80
|
# WARNING: Interactive policies may cause hangs in server/headless mode
|
|
81
81
|
# CODEX_APPROVAL_POLICY=never
|
|
82
82
|
|
|
83
|
-
# Default Codex model (default: gpt-
|
|
84
|
-
# Options: gpt-
|
|
85
|
-
# CODEX_MODEL=gpt-
|
|
83
|
+
# Default Codex backend model (default: gpt-6-astra). Per-request override: models: ["codex:<model>"]
|
|
84
|
+
# Options: gpt-6-astra, gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna, gpt-5.5, gpt-5.3-codex-spark
|
|
85
|
+
# CODEX_MODEL=gpt-6-astra
|
|
86
86
|
|
|
87
87
|
# ============================================
|
|
88
88
|
# Server Configuration
|
package/README.md
CHANGED
|
@@ -281,7 +281,9 @@ Any other model works via its full `provider/model` slug or the `openrouter:` na
|
|
|
281
281
|
|
|
282
282
|
### Codex Models
|
|
283
283
|
|
|
284
|
-
- **codex**: OpenAI Codex agentic coding assistant
|
|
284
|
+
- **codex**: OpenAI Codex agentic coding assistant (GPT-6 Astra by default)
|
|
285
|
+
- Pick another backend per request with `codex:<model>` (e.g. `codex:sol`, `codex:gpt-5.6-terra`) or globally with `CODEX_MODEL`; backends: `gpt-6-astra` (alias `astra`), `gpt-5.6-sol` (`sol`), `gpt-5.6-terra` (`terra`), `gpt-5.6-luna` (`luna`), `gpt-5.5`, `gpt-5.3-codex-spark` (`spark`)
|
|
286
|
+
- `reasoning_effort` maps onto the tiers the chosen backend accepts (GPT-6 Astra: `low` through `max`, no `none`)
|
|
285
287
|
- Thread-based sessions with persistent context
|
|
286
288
|
- Direct filesystem access from working directory
|
|
287
289
|
- Typical response time: 6-20 seconds (longer for complex tasks)
|
|
@@ -357,6 +359,7 @@ CODEX_API_KEY=your_codex_api_key_here # Optional if ChatGPT login availabl
|
|
|
357
359
|
CODEX_SANDBOX_MODE=read-only # read-only (default), workspace-write, danger-full-access
|
|
358
360
|
CODEX_SKIP_GIT_CHECK=true # true (default), false
|
|
359
361
|
CODEX_APPROVAL_POLICY=never # never (default), untrusted, on-failure, on-request
|
|
362
|
+
CODEX_MODEL=gpt-6-astra # gpt-6-astra (default), gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna, gpt-5.5
|
|
360
363
|
```
|
|
361
364
|
|
|
362
365
|
### Configuration Options
|
package/docs/API.md
CHANGED
|
@@ -456,12 +456,13 @@ Any other model works via its full `provider/model` slug (e.g. `anthropic/claude
|
|
|
456
456
|
|
|
457
457
|
**Codex** is an agentic coding assistant with direct filesystem access:
|
|
458
458
|
|
|
459
|
-
- **Model**: `codex` (underlying model: GPT-
|
|
459
|
+
- **Model**: `codex` (underlying model: GPT-6 Astra by default)
|
|
460
|
+
- **Backend selection**: `codex:<model>` per request (e.g. `codex:astra`, `codex:sol`, `codex:gpt-5.6-terra`), or `CODEX_MODEL` globally; unknown names pass through to the CLI verbatim
|
|
460
461
|
- **Thread-based sessions**: persistent conversation history via `continuation_id` in `chat` mode
|
|
461
462
|
- **Direct file access**: reads files from the working directory (paths relative to `CLIENT_CWD`)
|
|
462
463
|
- **Response times**: 6-20 seconds typical (complex tasks may take minutes)
|
|
463
464
|
- **Authentication**: ChatGPT login OR `CODEX_API_KEY` (NOT `OPENAI_API_KEY`)
|
|
464
|
-
- `reasoning_effort`
|
|
465
|
+
- `reasoning_effort` is clamped onto the tiers the chosen backend accepts (GPT-6 Astra: `low`–`max`, no `none`; GPT-5.6: `none`–`max`); web search is not applicable — Codex manages its own execution
|
|
465
466
|
|
|
466
467
|
### Claude Agent SDK (subscription)
|
|
467
468
|
|
package/docs/PROVIDERS.md
CHANGED
|
@@ -101,9 +101,11 @@ This guide documents all supported AI providers in the Converse MCP Server and t
|
|
|
101
101
|
- `CODEX_SANDBOX_MODE` - Filesystem access control (default: read-only)
|
|
102
102
|
- `CODEX_SKIP_GIT_CHECK` - Skip Git repository validation (default: true)
|
|
103
103
|
- `CODEX_APPROVAL_POLICY` - Command approval behavior (default: never)
|
|
104
|
-
- `CODEX_MODEL` - Underlying model for Codex sessions (default: gpt-
|
|
104
|
+
- `CODEX_MODEL` - Underlying model for Codex sessions (default: gpt-6-astra; e.g. gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna, gpt-5.5)
|
|
105
105
|
- **Supported Models**:
|
|
106
|
-
- `codex` - OpenAI Codex agentic coding assistant (GPT-
|
|
106
|
+
- `codex` - OpenAI Codex agentic coding assistant (GPT-6 Astra by default)
|
|
107
|
+
- `codex:<model>` - Same, with an explicit backend: `codex:astra`, `codex:sol`, `codex:terra`, `codex:luna`, `codex:gpt-5.5`, `codex:spark`, or any slug the Codex CLI knows
|
|
108
|
+
- `reasoning_effort` is clamped onto what the backend accepts (GPT-6 Astra: `low`–`max`, no `none`)
|
|
107
109
|
- Thread-based sessions with persistent context
|
|
108
110
|
- Direct filesystem access from working directory
|
|
109
111
|
- Typical response time: 6-20 seconds (longer for complex tasks)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "converse-mcp-server",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.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",
|
|
@@ -93,28 +93,28 @@
|
|
|
93
93
|
".env.example"
|
|
94
94
|
],
|
|
95
95
|
"dependencies": {
|
|
96
|
-
"@anthropic-ai/claude-agent-sdk": "^0.3.
|
|
96
|
+
"@anthropic-ai/claude-agent-sdk": "^0.3.261",
|
|
97
97
|
"@anthropic-ai/sdk": "^0.123.0",
|
|
98
98
|
"@github/copilot-sdk": "^1.0.11",
|
|
99
|
-
"@google/genai": "^2.
|
|
99
|
+
"@google/genai": "^2.21.0",
|
|
100
100
|
"@lydell/node-pty": "1.2.0-beta.15",
|
|
101
101
|
"@mistralai/mistralai": "^2.6.4",
|
|
102
102
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
103
|
-
"@openai/codex-sdk": "^0.
|
|
103
|
+
"@openai/codex-sdk": "^0.153.3",
|
|
104
104
|
"cors": "^2.8.6",
|
|
105
105
|
"dotenv": "^17.4.2",
|
|
106
106
|
"express": "^5.2.1",
|
|
107
107
|
"lru-cache": "^11.5.2",
|
|
108
108
|
"nanoid": "^6.0.1",
|
|
109
|
-
"openai": "^7.
|
|
109
|
+
"openai": "^7.10.0",
|
|
110
110
|
"p-limit": "^7.3.2",
|
|
111
111
|
"vite": "^8.2.2"
|
|
112
112
|
},
|
|
113
113
|
"devDependencies": {
|
|
114
|
-
"@vitest/coverage-v8": "^
|
|
114
|
+
"@vitest/coverage-v8": "^5.0.0",
|
|
115
115
|
"cross-env": "^10.1.0",
|
|
116
|
-
"eslint": "^10.
|
|
116
|
+
"eslint": "^10.10.0",
|
|
117
117
|
"rimraf": "^6.1.3",
|
|
118
|
-
"vitest": "^
|
|
118
|
+
"vitest": "^5.0.0"
|
|
119
119
|
}
|
|
120
120
|
}
|
package/src/config.js
CHANGED
|
@@ -280,9 +280,9 @@ const CONFIG_SCHEMA = {
|
|
|
280
280
|
},
|
|
281
281
|
CODEX_MODEL: {
|
|
282
282
|
type: 'string',
|
|
283
|
-
default: 'gpt-
|
|
283
|
+
default: 'gpt-6-astra',
|
|
284
284
|
description:
|
|
285
|
-
'Default Codex model (e.g., gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna, gpt-5.5)',
|
|
285
|
+
'Default Codex backend model (e.g., gpt-6-astra, gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna, gpt-5.5)',
|
|
286
286
|
},
|
|
287
287
|
|
|
288
288
|
// Copilot configuration
|
package/src/providers/codex.js
CHANGED
|
@@ -17,35 +17,75 @@ import { debugLog, debugError } from '../utils/console.js';
|
|
|
17
17
|
import { ProviderError, ErrorCodes, StopReasons } from './interface.js';
|
|
18
18
|
import { normalizeExtendedPath } from '../utils/pathUtils.js';
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
/**
|
|
21
|
+
* Every Codex reasoning tier, weakest to strongest. Used to clamp a requested
|
|
22
|
+
* tier onto the set a given backend model accepts.
|
|
23
|
+
*
|
|
24
|
+
* Codex also exposes 'ultra' above 'max', but that tier turns on automatic
|
|
25
|
+
* sub-agent delegation — a change in how the run executes, not just how deep
|
|
26
|
+
* it reasons — so nothing at the tool level maps to it and it is kept off the
|
|
27
|
+
* ladder so the clamp can never select it.
|
|
28
|
+
*/
|
|
29
|
+
const EFFORT_LADDER = ['none', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max'];
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Backend models Codex can run, keyed by the slug passed to the CLI as
|
|
33
|
+
* --model. The reasoning tiers are the ones each model's API accepts, verified
|
|
34
|
+
* against the API's own rejection messages (gpt-6-astra: "Supported values
|
|
35
|
+
* are: 'low', 'medium', 'high', 'xhigh', and 'max'"). The SDK's
|
|
36
|
+
* ModelReasoningEffort type is the union across models, so the backend is the
|
|
37
|
+
* authority and requests are clamped per model.
|
|
38
|
+
*/
|
|
39
|
+
const CODEX_BACKEND_MODELS = {
|
|
40
|
+
'gpt-6-astra': {
|
|
41
|
+
aliases: ['astra', 'gpt-6', 'gpt6', 'gpt6-astra'],
|
|
42
|
+
contextWindow: 272000,
|
|
43
|
+
supportedEfforts: ['low', 'medium', 'high', 'xhigh', 'max'],
|
|
44
|
+
},
|
|
45
|
+
'gpt-5.6-sol': {
|
|
46
|
+
aliases: ['sol', 'gpt-5.6', 'gpt5.6', 'gpt-5.6-codex'],
|
|
47
|
+
contextWindow: 272000,
|
|
48
|
+
supportedEfforts: ['none', 'low', 'medium', 'high', 'xhigh', 'max'],
|
|
49
|
+
},
|
|
50
|
+
'gpt-5.6-terra': {
|
|
51
|
+
aliases: ['terra'],
|
|
52
|
+
contextWindow: 272000,
|
|
53
|
+
supportedEfforts: ['none', 'low', 'medium', 'high', 'xhigh', 'max'],
|
|
54
|
+
},
|
|
55
|
+
'gpt-5.6-luna': {
|
|
56
|
+
aliases: ['luna'],
|
|
57
|
+
contextWindow: 272000,
|
|
58
|
+
supportedEfforts: ['none', 'low', 'medium', 'high', 'xhigh', 'max'],
|
|
59
|
+
},
|
|
60
|
+
'gpt-5.5': {
|
|
61
|
+
aliases: ['gpt5.5'],
|
|
62
|
+
contextWindow: 272000,
|
|
63
|
+
supportedEfforts: ['low', 'medium', 'high', 'xhigh'],
|
|
64
|
+
},
|
|
65
|
+
'gpt-5.3-codex-spark': {
|
|
66
|
+
aliases: ['spark', 'codex-spark'],
|
|
67
|
+
contextWindow: 128000,
|
|
68
|
+
supportedEfforts: ['low', 'medium', 'high', 'xhigh'],
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const DEFAULT_BACKEND_MODEL = 'gpt-6-astra';
|
|
73
|
+
|
|
74
|
+
// The single user-facing model the router exposes. The backend model behind it
|
|
75
|
+
// comes from CODEX_MODEL, or from a `codex:<model>` spec.
|
|
21
76
|
const SUPPORTED_MODELS = {
|
|
22
77
|
codex: {
|
|
23
78
|
modelName: 'codex',
|
|
24
|
-
friendlyName: 'OpenAI Codex (GPT-
|
|
25
|
-
contextWindow:
|
|
79
|
+
friendlyName: 'OpenAI Codex (GPT-6 Astra)',
|
|
80
|
+
contextWindow: CODEX_BACKEND_MODELS[DEFAULT_BACKEND_MODEL].contextWindow,
|
|
26
81
|
maxOutputTokens: 128000,
|
|
27
82
|
supportsStreaming: true,
|
|
28
83
|
supportsImages: true, // Codex SDK 0.118+ supports images via --image (local_image input)
|
|
29
84
|
supportsWebSearch: false, // Codex accesses files directly, not web
|
|
30
|
-
// Reasoning tiers this model's backend actually accepts. GPT-5.6 dropped
|
|
31
|
-
// 'minimal' and added 'none', while the SDK's ModelReasoningEffort type
|
|
32
|
-
// still advertises the pre-5.6 set — the backend is the authority, so the
|
|
33
|
-
// accepted tiers are declared per model and requests are clamped onto them.
|
|
34
|
-
supportedEfforts: ['none', 'low', 'medium', 'high', 'xhigh'],
|
|
35
85
|
timeout: 1800000, // 30 minutes
|
|
36
86
|
description:
|
|
37
|
-
'OpenAI Codex agentic coding assistant with local file access and tool execution (GPT-
|
|
38
|
-
aliases: [
|
|
39
|
-
'gpt-5-codex',
|
|
40
|
-
'gpt5-codex',
|
|
41
|
-
'gpt-5.2-codex',
|
|
42
|
-
'gpt-5.3-codex',
|
|
43
|
-
'gpt5.3-codex',
|
|
44
|
-
'gpt-5.5',
|
|
45
|
-
'gpt5.5',
|
|
46
|
-
'gpt-5.6-codex',
|
|
47
|
-
'gpt5.6-codex',
|
|
48
|
-
],
|
|
87
|
+
'OpenAI Codex agentic coding assistant with local file access and tool execution (GPT-6 Astra by default; pick another backend with codex:<model> or CODEX_MODEL)',
|
|
88
|
+
aliases: [],
|
|
49
89
|
},
|
|
50
90
|
};
|
|
51
91
|
|
|
@@ -195,6 +235,57 @@ function extractPromptText(input) {
|
|
|
195
235
|
.join('\n\n');
|
|
196
236
|
}
|
|
197
237
|
|
|
238
|
+
/**
|
|
239
|
+
* Resolve a backend slug or alias (case-insensitive) to its catalog slug.
|
|
240
|
+
* @param {string} name
|
|
241
|
+
* @returns {string|null}
|
|
242
|
+
*/
|
|
243
|
+
function findBackendSlug(name) {
|
|
244
|
+
const lower = String(name || '').trim().toLowerCase();
|
|
245
|
+
if (!lower) {
|
|
246
|
+
return null;
|
|
247
|
+
}
|
|
248
|
+
if (CODEX_BACKEND_MODELS[lower]) {
|
|
249
|
+
return lower;
|
|
250
|
+
}
|
|
251
|
+
return (
|
|
252
|
+
Object.keys(CODEX_BACKEND_MODELS).find((slug) =>
|
|
253
|
+
CODEX_BACKEND_MODELS[slug].aliases.includes(lower),
|
|
254
|
+
) || null
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Catalog entry for a backend model, or null when the slug is not catalogued.
|
|
260
|
+
* @param {string} name - Backend slug or alias
|
|
261
|
+
* @returns {{ slug: string, aliases: string[], contextWindow: number, supportedEfforts: string[] }|null}
|
|
262
|
+
*/
|
|
263
|
+
export function getBackendModelConfig(name) {
|
|
264
|
+
const slug = findBackendSlug(name);
|
|
265
|
+
return slug ? { slug, ...CODEX_BACKEND_MODELS[slug] } : null;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Resolve the requested model spec to the backend slug passed to the CLI.
|
|
270
|
+
*
|
|
271
|
+
* `codex` uses CODEX_MODEL (default gpt-6-astra); `codex:<model>` names a
|
|
272
|
+
* backend directly, by slug or alias. Unknown names pass through verbatim so a
|
|
273
|
+
* newly released model works before it is catalogued here — the CLI rejects
|
|
274
|
+
* anything the backend does not know.
|
|
275
|
+
*
|
|
276
|
+
* @param {string} spec - Requested model, e.g. 'codex' or 'codex:sol'
|
|
277
|
+
* @param {Object} [config] - Loaded configuration
|
|
278
|
+
* @returns {string} Backend slug for the SDK's `model` option
|
|
279
|
+
*/
|
|
280
|
+
export function resolveBackendModel(spec, config) {
|
|
281
|
+
const raw = String(spec || '').trim();
|
|
282
|
+
const requested = raw.toLowerCase().startsWith('codex:')
|
|
283
|
+
? raw.slice('codex:'.length).trim()
|
|
284
|
+
: '';
|
|
285
|
+
const name = requested || config?.providers?.codexmodel || DEFAULT_BACKEND_MODEL;
|
|
286
|
+
return findBackendSlug(name) || name;
|
|
287
|
+
}
|
|
288
|
+
|
|
198
289
|
/**
|
|
199
290
|
* Get thread ID from continuation metadata.
|
|
200
291
|
* Codex thread IDs are stored per call-plan in `providerThreads`, keyed by a
|
|
@@ -216,12 +307,6 @@ async function getThreadIdFromContinuation(
|
|
|
216
307
|
}
|
|
217
308
|
}
|
|
218
309
|
|
|
219
|
-
/**
|
|
220
|
-
* Every Codex reasoning tier, weakest to strongest. Used to clamp a requested
|
|
221
|
-
* tier onto the set a given model actually accepts.
|
|
222
|
-
*/
|
|
223
|
-
const EFFORT_LADDER = ['none', 'minimal', 'low', 'medium', 'high', 'xhigh'];
|
|
224
|
-
|
|
225
310
|
/**
|
|
226
311
|
* Tool-level reasoning_effort values translated to their Codex equivalent.
|
|
227
312
|
* Tool enum: 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'max'
|
|
@@ -232,7 +317,7 @@ const EFFORT_ALIASES = {
|
|
|
232
317
|
low: 'low',
|
|
233
318
|
medium: 'medium',
|
|
234
319
|
high: 'high',
|
|
235
|
-
max: '
|
|
320
|
+
max: 'max',
|
|
236
321
|
};
|
|
237
322
|
|
|
238
323
|
/**
|
|
@@ -403,8 +488,9 @@ export const codexProvider = {
|
|
|
403
488
|
const approvalPolicy = config.providers?.codexapprovalpolicy || 'never';
|
|
404
489
|
|
|
405
490
|
// Create or resume thread
|
|
491
|
+
const backendModel = resolveBackendModel(model, config);
|
|
406
492
|
const threadOptions = {
|
|
407
|
-
model:
|
|
493
|
+
model: backendModel,
|
|
408
494
|
workingDirectory,
|
|
409
495
|
sandboxMode,
|
|
410
496
|
skipGitRepoCheck,
|
|
@@ -413,13 +499,12 @@ export const codexProvider = {
|
|
|
413
499
|
|
|
414
500
|
if (reasoning_effort) {
|
|
415
501
|
const supportedEfforts =
|
|
416
|
-
|
|
417
|
-
SUPPORTED_MODELS.codex.supportedEfforts;
|
|
502
|
+
getBackendModelConfig(backendModel)?.supportedEfforts || EFFORT_LADDER;
|
|
418
503
|
const mappedEffort = mapReasoningEffort(reasoning_effort, supportedEfforts);
|
|
419
504
|
threadOptions.modelReasoningEffort = mappedEffort;
|
|
420
505
|
if (mappedEffort !== EFFORT_ALIASES[reasoning_effort]) {
|
|
421
506
|
debugLog(
|
|
422
|
-
`[Codex] reasoning_effort "${reasoning_effort}" not supported by ${
|
|
507
|
+
`[Codex] reasoning_effort "${reasoning_effort}" not supported by ${backendModel} — using "${mappedEffort}"`,
|
|
423
508
|
);
|
|
424
509
|
}
|
|
425
510
|
}
|
|
@@ -470,6 +555,7 @@ export const codexProvider = {
|
|
|
470
555
|
metadata: {
|
|
471
556
|
provider: 'codex',
|
|
472
557
|
model,
|
|
558
|
+
backendModel,
|
|
473
559
|
threadId: threadIdFromStream || thread.id,
|
|
474
560
|
usage: usage
|
|
475
561
|
? {
|
|
@@ -138,9 +138,10 @@ function classifyModelSpec(spec, providers) {
|
|
|
138
138
|
}
|
|
139
139
|
|
|
140
140
|
// Other explicit namespaces pass the spec through unchanged; the target
|
|
141
|
-
// provider strips its own prefix (preserves current copilot/claude/gemini-cli
|
|
141
|
+
// provider strips its own prefix (preserves current codex/copilot/claude/gemini-cli
|
|
142
142
|
// behavior).
|
|
143
143
|
if (
|
|
144
|
+
lower.startsWith('codex:') ||
|
|
144
145
|
lower.startsWith('copilot:') ||
|
|
145
146
|
lower.startsWith('claude:') ||
|
|
146
147
|
lower.startsWith('gemini:')
|
|
@@ -308,8 +309,9 @@ export function mapModelToProvider(model, providers) {
|
|
|
308
309
|
return 'openai';
|
|
309
310
|
}
|
|
310
311
|
|
|
311
|
-
// Check Codex
|
|
312
|
-
|
|
312
|
+
// Check Codex: bare `codex` or the `codex:<backend>` namespace (e.g. codex:astra,
|
|
313
|
+
// codex:gpt-5.6-sol). Bare "gpt-*" names never route here — they are OpenAI API models.
|
|
314
|
+
if (modelLower === 'codex' || modelLower.startsWith('codex:')) {
|
|
313
315
|
return 'codex';
|
|
314
316
|
}
|
|
315
317
|
|