mcp-agents 0.8.0 → 0.9.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 +1 -1
- package/server.js +86 -17
package/package.json
CHANGED
package/server.js
CHANGED
|
@@ -29,10 +29,13 @@ const VERSION = JSON.parse(
|
|
|
29
29
|
const DEFAULT_TIMEOUT_MS = 300_000;
|
|
30
30
|
const DEFAULT_CODEX_MODEL = "gpt-5.5";
|
|
31
31
|
const DEFAULT_CODEX_MODEL_REASONING_EFFORT = "xhigh";
|
|
32
|
+
const DEFAULT_CODEX_SANDBOX_MODE = "workspace-write";
|
|
33
|
+
const DEFAULT_CODEX_APPROVAL_POLICY = "never";
|
|
32
34
|
const DEFAULT_CLAUDE_MODEL = "claude-opus-4-8";
|
|
33
35
|
const DEFAULT_CLAUDE_EFFORT = "xhigh";
|
|
34
36
|
// tools/call argument keys stripped from the codex pass-through so callers
|
|
35
|
-
// cannot override the pinned model/effort (or the
|
|
37
|
+
// cannot override the pinned model/effort (or the server's sandbox/approval
|
|
38
|
+
// config) for a single call.
|
|
36
39
|
const CODEX_STRIPPED_TOOL_ARGS = ["model", "config"];
|
|
37
40
|
const MAX_BUFFER_BYTES = 10 * 1024 * 1024;
|
|
38
41
|
const CLAUDE_EMPTY_OUTPUT_MAX_ATTEMPTS = 2;
|
|
@@ -141,6 +144,10 @@ Options:
|
|
|
141
144
|
--provider <name> CLI backend to use (${providers}) [default: codex]
|
|
142
145
|
--model <model> Codex model [default: ${DEFAULT_CODEX_MODEL}]
|
|
143
146
|
--model_reasoning_effort <e> Codex reasoning effort [default: ${DEFAULT_CODEX_MODEL_REASONING_EFFORT}]
|
|
147
|
+
--sandbox_mode <mode> Codex sandbox mode: read-only, workspace-write,
|
|
148
|
+
danger-full-access [default: ${DEFAULT_CODEX_SANDBOX_MODE}]
|
|
149
|
+
--approval_policy <policy> Codex approval policy: untrusted, on-failure,
|
|
150
|
+
on-request, never [default: ${DEFAULT_CODEX_APPROVAL_POLICY}]
|
|
144
151
|
--timeout <seconds> Default timeout per call [default: 300]
|
|
145
152
|
--help, -h Show this help message
|
|
146
153
|
--version, -v Show version number`);
|
|
@@ -148,14 +155,17 @@ Options:
|
|
|
148
155
|
|
|
149
156
|
/**
|
|
150
157
|
* Parse CLI flags from process.argv.
|
|
151
|
-
* Handles --help, --version, --provider, --model, --model_reasoning_effort,
|
|
152
|
-
*
|
|
158
|
+
* Handles --help, --version, --provider, --model, --model_reasoning_effort,
|
|
159
|
+
* --sandbox_mode, --approval_policy, and unknown flags.
|
|
160
|
+
* @returns {{ provider: string, model?: string, modelReasoningEffort?: string, sandboxMode?: string, approvalPolicy?: string, defaultTimeoutMs?: number }}
|
|
153
161
|
*/
|
|
154
162
|
function parseArgs() {
|
|
155
163
|
const args = process.argv.slice(2);
|
|
156
164
|
let provider = "codex";
|
|
157
165
|
let model;
|
|
158
166
|
let modelReasoningEffort;
|
|
167
|
+
let sandboxMode;
|
|
168
|
+
let approvalPolicy;
|
|
159
169
|
let defaultTimeoutMs;
|
|
160
170
|
|
|
161
171
|
for (let i = 0; i < args.length; i++) {
|
|
@@ -193,6 +203,20 @@ function parseArgs() {
|
|
|
193
203
|
}
|
|
194
204
|
modelReasoningEffort = args[++i];
|
|
195
205
|
break;
|
|
206
|
+
case "--sandbox_mode":
|
|
207
|
+
if (i + 1 >= args.length) {
|
|
208
|
+
process.stderr.write("error: --sandbox_mode requires a value\n");
|
|
209
|
+
process.exit(1);
|
|
210
|
+
}
|
|
211
|
+
sandboxMode = args[++i];
|
|
212
|
+
break;
|
|
213
|
+
case "--approval_policy":
|
|
214
|
+
if (i + 1 >= args.length) {
|
|
215
|
+
process.stderr.write("error: --approval_policy requires a value\n");
|
|
216
|
+
process.exit(1);
|
|
217
|
+
}
|
|
218
|
+
approvalPolicy = args[++i];
|
|
219
|
+
break;
|
|
196
220
|
case "--timeout": {
|
|
197
221
|
if (i + 1 >= args.length) {
|
|
198
222
|
process.stderr.write("error: --timeout requires a value\n");
|
|
@@ -212,7 +236,14 @@ function parseArgs() {
|
|
|
212
236
|
}
|
|
213
237
|
}
|
|
214
238
|
|
|
215
|
-
return {
|
|
239
|
+
return {
|
|
240
|
+
provider,
|
|
241
|
+
model,
|
|
242
|
+
modelReasoningEffort,
|
|
243
|
+
sandboxMode,
|
|
244
|
+
approvalPolicy,
|
|
245
|
+
defaultTimeoutMs,
|
|
246
|
+
};
|
|
216
247
|
}
|
|
217
248
|
|
|
218
249
|
/**
|
|
@@ -356,15 +387,20 @@ function toTomlString(value) {
|
|
|
356
387
|
|
|
357
388
|
/**
|
|
358
389
|
* Build the minimal config for the isolated Codex bridge runtime.
|
|
359
|
-
* @param {{ model: string, modelReasoningEffort: string }} opts
|
|
390
|
+
* @param {{ model: string, modelReasoningEffort: string, sandboxMode: string, approvalPolicy: string }} opts
|
|
360
391
|
* @returns {string}
|
|
361
392
|
*/
|
|
362
|
-
function buildCodexBridgeConfig({
|
|
393
|
+
function buildCodexBridgeConfig({
|
|
394
|
+
model,
|
|
395
|
+
modelReasoningEffort,
|
|
396
|
+
sandboxMode,
|
|
397
|
+
approvalPolicy,
|
|
398
|
+
}) {
|
|
363
399
|
return [
|
|
364
400
|
`model = ${toTomlString(model)}`,
|
|
365
401
|
`model_reasoning_effort = ${toTomlString(modelReasoningEffort)}`,
|
|
366
|
-
|
|
367
|
-
|
|
402
|
+
`approval_policy = ${toTomlString(approvalPolicy)}`,
|
|
403
|
+
`sandbox_mode = ${toTomlString(sandboxMode)}`,
|
|
368
404
|
"",
|
|
369
405
|
"[features]",
|
|
370
406
|
"multi_agent = false",
|
|
@@ -374,10 +410,15 @@ function buildCodexBridgeConfig({ model, modelReasoningEffort }) {
|
|
|
374
410
|
|
|
375
411
|
/**
|
|
376
412
|
* Create an isolated Codex home that preserves auth but strips inherited MCP servers.
|
|
377
|
-
* @param {{ model: string, modelReasoningEffort: string }} opts
|
|
413
|
+
* @param {{ model: string, modelReasoningEffort: string, sandboxMode: string, approvalPolicy: string }} opts
|
|
378
414
|
* @returns {string}
|
|
379
415
|
*/
|
|
380
|
-
function createIsolatedCodexHome({
|
|
416
|
+
function createIsolatedCodexHome({
|
|
417
|
+
model,
|
|
418
|
+
modelReasoningEffort,
|
|
419
|
+
sandboxMode,
|
|
420
|
+
approvalPolicy,
|
|
421
|
+
}) {
|
|
381
422
|
const codexHome = mkdtempSync(join(tmpdir(), "mcp-agents-codex-"));
|
|
382
423
|
const sourceAuthPath = join(resolveCodexHome(), "auth.json");
|
|
383
424
|
const targetAuthPath = join(codexHome, "auth.json");
|
|
@@ -389,7 +430,12 @@ function createIsolatedCodexHome({ model, modelReasoningEffort }) {
|
|
|
389
430
|
|
|
390
431
|
writeFileSync(
|
|
391
432
|
configPath,
|
|
392
|
-
buildCodexBridgeConfig({
|
|
433
|
+
buildCodexBridgeConfig({
|
|
434
|
+
model,
|
|
435
|
+
modelReasoningEffort,
|
|
436
|
+
sandboxMode,
|
|
437
|
+
approvalPolicy,
|
|
438
|
+
}),
|
|
393
439
|
"utf8",
|
|
394
440
|
);
|
|
395
441
|
|
|
@@ -399,7 +445,7 @@ function createIsolatedCodexHome({ model, modelReasoningEffort }) {
|
|
|
399
445
|
/**
|
|
400
446
|
* Filter a single newline-delimited JSON-RPC message on its way to the codex
|
|
401
447
|
* pass-through. Strips per-call model/config overrides from `tools/call` so the
|
|
402
|
-
* client cannot escape the pinned model/effort (or the
|
|
448
|
+
* client cannot escape the pinned model/effort (or the sandbox/approval config).
|
|
403
449
|
* Non-`tools/call` and unparseable lines are returned byte-for-byte unchanged so
|
|
404
450
|
* the MCP framing is preserved.
|
|
405
451
|
* @param {string} line
|
|
@@ -436,18 +482,27 @@ function filterCodexToolCall(line) {
|
|
|
436
482
|
* Spawn codex mcp-server as a pass-through. stdout/stderr flow straight back to
|
|
437
483
|
* the client, but the client's stdin is intercepted line-by-line so per-call
|
|
438
484
|
* model/config overrides are stripped before reaching codex.
|
|
439
|
-
* @param {{ model?: string, modelReasoningEffort?: string }} opts
|
|
485
|
+
* @param {{ model?: string, modelReasoningEffort?: string, sandboxMode?: string, approvalPolicy?: string }} opts
|
|
440
486
|
*/
|
|
441
|
-
function runCodexPassthrough({
|
|
487
|
+
function runCodexPassthrough({
|
|
488
|
+
model,
|
|
489
|
+
modelReasoningEffort,
|
|
490
|
+
sandboxMode,
|
|
491
|
+
approvalPolicy,
|
|
492
|
+
}) {
|
|
442
493
|
const resolvedModel = model || DEFAULT_CODEX_MODEL;
|
|
443
494
|
const resolvedModelReasoningEffort =
|
|
444
495
|
modelReasoningEffort || DEFAULT_CODEX_MODEL_REASONING_EFFORT;
|
|
496
|
+
const resolvedSandboxMode = sandboxMode || DEFAULT_CODEX_SANDBOX_MODE;
|
|
497
|
+
const resolvedApprovalPolicy = approvalPolicy || DEFAULT_CODEX_APPROVAL_POLICY;
|
|
445
498
|
let isolatedCodexHome;
|
|
446
499
|
|
|
447
500
|
try {
|
|
448
501
|
isolatedCodexHome = createIsolatedCodexHome({
|
|
449
502
|
model: resolvedModel,
|
|
450
503
|
modelReasoningEffort: resolvedModelReasoningEffort,
|
|
504
|
+
sandboxMode: resolvedSandboxMode,
|
|
505
|
+
approvalPolicy: resolvedApprovalPolicy,
|
|
451
506
|
});
|
|
452
507
|
} catch (err) {
|
|
453
508
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -472,7 +527,9 @@ function runCodexPassthrough({ model, modelReasoningEffort }) {
|
|
|
472
527
|
|
|
473
528
|
logErr(
|
|
474
529
|
`[mcp-agents] passthrough: codex ${args.join(" ")} ` +
|
|
475
|
-
`(model=${resolvedModel}, reasoning_effort=${resolvedModelReasoningEffort},
|
|
530
|
+
`(model=${resolvedModel}, reasoning_effort=${resolvedModelReasoningEffort}, ` +
|
|
531
|
+
`sandbox_mode=${resolvedSandboxMode}, approval_policy=${resolvedApprovalPolicy}, ` +
|
|
532
|
+
`isolated_home=true)`,
|
|
476
533
|
);
|
|
477
534
|
|
|
478
535
|
const child = spawn("codex", args, {
|
|
@@ -539,7 +596,14 @@ function runCodexPassthrough({ model, modelReasoningEffort }) {
|
|
|
539
596
|
// ---------------------------------------------------------------------------
|
|
540
597
|
|
|
541
598
|
async function main() {
|
|
542
|
-
const {
|
|
599
|
+
const {
|
|
600
|
+
provider: providerName,
|
|
601
|
+
model,
|
|
602
|
+
modelReasoningEffort,
|
|
603
|
+
sandboxMode,
|
|
604
|
+
approvalPolicy,
|
|
605
|
+
defaultTimeoutMs,
|
|
606
|
+
} = parseArgs();
|
|
543
607
|
const backend = CLI_BACKENDS[providerName];
|
|
544
608
|
|
|
545
609
|
if (!backend) {
|
|
@@ -550,7 +614,12 @@ async function main() {
|
|
|
550
614
|
}
|
|
551
615
|
|
|
552
616
|
if (backend.passthrough) {
|
|
553
|
-
runCodexPassthrough({
|
|
617
|
+
runCodexPassthrough({
|
|
618
|
+
model,
|
|
619
|
+
modelReasoningEffort,
|
|
620
|
+
sandboxMode,
|
|
621
|
+
approvalPolicy,
|
|
622
|
+
});
|
|
554
623
|
return;
|
|
555
624
|
}
|
|
556
625
|
|