open-agents-ai 0.187.179 → 0.187.180
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/dist/index.js +133 -132
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -302317,6 +302317,13 @@ async function handleMcp(subcommand, ctx3) {
|
|
|
302317
302317
|
}
|
|
302318
302318
|
await showMcpMainMenu(ctx3);
|
|
302319
302319
|
}
|
|
302320
|
+
function validateMcpConfigShape(parsed) {
|
|
302321
|
+
if (!parsed || typeof parsed !== "object") return "Config must be a JSON object";
|
|
302322
|
+
if (typeof parsed.command !== "string" && typeof parsed.url !== "string") {
|
|
302323
|
+
return "Config must have either 'command' (stdio) or 'url' (http)";
|
|
302324
|
+
}
|
|
302325
|
+
return null;
|
|
302326
|
+
}
|
|
302320
302327
|
async function showMcpMainMenu(ctx3) {
|
|
302321
302328
|
const manager = ctx3.getMcpManager?.();
|
|
302322
302329
|
if (!manager) return;
|
|
@@ -302354,19 +302361,76 @@ async function showMcpMainMenu(ctx3) {
|
|
|
302354
302361
|
}
|
|
302355
302362
|
items.push({ key: "hdr_actions", label: selectColors.dim("\u2500\u2500\u2500 Actions \u2500\u2500\u2500"), kind: "header" });
|
|
302356
302363
|
skipKeys.push("hdr_actions");
|
|
302357
|
-
items.push({ key: "act_add", label: c3.cyan("\u2795 Add new server"), detail: "
|
|
302364
|
+
items.push({ key: "act_add", label: c3.cyan("\u2795 Add new server"), detail: "Inline name + JSON intake", kind: "action" });
|
|
302358
302365
|
items.push({ key: "act_reload", label: c3.cyan("\u27F3 Reload all from config"), detail: "Re-read .oa/mcp.json + reconnect", kind: "action" });
|
|
302359
|
-
items.push({ key: "act_open", label: c3.cyan("\u{1F4DD}
|
|
302366
|
+
items.push({ key: "act_open", label: c3.cyan("\u{1F4DD} Show .oa/mcp.json path"), detail: "For external editing", kind: "action" });
|
|
302367
|
+
let pendingAdd = null;
|
|
302368
|
+
const postMessages = [];
|
|
302360
302369
|
const result = await tuiSelect({
|
|
302361
302370
|
items,
|
|
302362
302371
|
title: "MCP Server Registry",
|
|
302363
|
-
skipKeys
|
|
302372
|
+
skipKeys,
|
|
302373
|
+
onEnter: (item, helpers) => {
|
|
302374
|
+
if (item.key === "act_add") {
|
|
302375
|
+
helpers.getInput("Server name (e.g. memory):", "").then(async (name10) => {
|
|
302376
|
+
if (!name10 || name10.trim().length === 0) {
|
|
302377
|
+
postMessages.push({ kind: "info", text: "Add cancelled \u2014 no name entered." });
|
|
302378
|
+
helpers.render();
|
|
302379
|
+
return;
|
|
302380
|
+
}
|
|
302381
|
+
const cfgStr = await helpers.getInput(
|
|
302382
|
+
'Config JSON (e.g. {"command":"npx","args":["-y","@modelcontextprotocol/server-memory"]}):',
|
|
302383
|
+
""
|
|
302384
|
+
);
|
|
302385
|
+
if (!cfgStr || cfgStr.trim().length === 0) {
|
|
302386
|
+
postMessages.push({ kind: "info", text: "Add cancelled \u2014 no config entered." });
|
|
302387
|
+
helpers.render();
|
|
302388
|
+
return;
|
|
302389
|
+
}
|
|
302390
|
+
let parsed;
|
|
302391
|
+
try {
|
|
302392
|
+
parsed = JSON.parse(cfgStr);
|
|
302393
|
+
} catch (e2) {
|
|
302394
|
+
postMessages.push({ kind: "error", text: `Invalid JSON: ${e2 instanceof Error ? e2.message : String(e2)}` });
|
|
302395
|
+
helpers.render();
|
|
302396
|
+
return;
|
|
302397
|
+
}
|
|
302398
|
+
const shapeErr = validateMcpConfigShape(parsed);
|
|
302399
|
+
if (shapeErr) {
|
|
302400
|
+
postMessages.push({ kind: "error", text: shapeErr });
|
|
302401
|
+
helpers.render();
|
|
302402
|
+
return;
|
|
302403
|
+
}
|
|
302404
|
+
pendingAdd = { name: name10.trim(), config: parsed };
|
|
302405
|
+
helpers.resolve({ confirmed: true, key: "__pending_add__", index: -1 });
|
|
302406
|
+
});
|
|
302407
|
+
return true;
|
|
302408
|
+
}
|
|
302409
|
+
return false;
|
|
302410
|
+
}
|
|
302364
302411
|
});
|
|
302365
|
-
|
|
302366
|
-
|
|
302367
|
-
|
|
302412
|
+
for (const msg of postMessages) {
|
|
302413
|
+
if (msg.kind === "info") renderInfo(msg.text);
|
|
302414
|
+
else if (msg.kind === "warn") renderWarning(msg.text);
|
|
302415
|
+
else renderError(msg.text);
|
|
302416
|
+
}
|
|
302417
|
+
if (pendingAdd) {
|
|
302418
|
+
const { name: name10, config } = pendingAdd;
|
|
302419
|
+
try {
|
|
302420
|
+
const c22 = await manager.addServer(name10, config);
|
|
302421
|
+
await ctx3.refreshMcpTools?.();
|
|
302422
|
+
if (c22.status === "connected") {
|
|
302423
|
+
renderInfo(`\u2714 ${name10} added and connected (${c22.tools.length} tools)`);
|
|
302424
|
+
} else {
|
|
302425
|
+
renderWarning(`\u26A0 ${name10} saved to .oa/mcp.json but not connected: ${c22.error ?? "unknown"}`);
|
|
302426
|
+
}
|
|
302427
|
+
} catch (e2) {
|
|
302428
|
+
renderError(`Add failed: ${e2 instanceof Error ? e2.message : String(e2)}`);
|
|
302429
|
+
}
|
|
302430
|
+
await showMcpMainMenu(ctx3);
|
|
302368
302431
|
return;
|
|
302369
302432
|
}
|
|
302433
|
+
if (!result || !result.confirmed || !result.key) return;
|
|
302370
302434
|
if (result.key === "act_reload") {
|
|
302371
302435
|
renderInfo("Reloading MCP servers...");
|
|
302372
302436
|
await manager.disconnectAll().catch(() => {
|
|
@@ -302450,15 +302514,76 @@ async function showMcpDetailMenu(ctx3, serverName) {
|
|
|
302450
302514
|
}
|
|
302451
302515
|
items.push({ key: "hdr_actions", label: selectColors.dim("\u2500\u2500\u2500 Actions \u2500\u2500\u2500"), kind: "header" });
|
|
302452
302516
|
skipKeys.push("hdr_actions");
|
|
302453
|
-
items.push({ key: "act_edit", label: c3.cyan("\u270E Edit config"), detail: "Modify command/args/env/url/headers", kind: "action" });
|
|
302517
|
+
items.push({ key: "act_edit", label: c3.cyan("\u270E Edit config"), detail: "Modify command/args/env/url/headers (inline)", kind: "action" });
|
|
302454
302518
|
items.push({ key: "act_reconnect", label: c3.cyan("\u27F3 Reconnect"), detail: "Disconnect + reconnect this server", kind: "action" });
|
|
302455
302519
|
items.push({ key: "act_delete", label: c3.red("\u{1F5D1} Delete"), detail: "Remove from config + disconnect", kind: "action" });
|
|
302456
302520
|
items.push({ key: "act_back", label: c3.dim("\u2190 Back to server list"), kind: "action" });
|
|
302521
|
+
let pendingEdit = null;
|
|
302522
|
+
const postMessages = [];
|
|
302457
302523
|
const result = await tuiSelect({
|
|
302458
302524
|
items,
|
|
302459
302525
|
title: `MCP: ${serverName}`,
|
|
302460
|
-
skipKeys
|
|
302526
|
+
skipKeys,
|
|
302527
|
+
onEnter: (item, helpers) => {
|
|
302528
|
+
if (item.key === "act_edit") {
|
|
302529
|
+
const currentJson = JSON.stringify(persisted ?? {});
|
|
302530
|
+
helpers.getInput(
|
|
302531
|
+
`New JSON config for ${serverName} (current shown \u2014 edit then Enter; Esc to cancel):`,
|
|
302532
|
+
currentJson
|
|
302533
|
+
).then(async (newJson) => {
|
|
302534
|
+
if (newJson === null || newJson.trim().length === 0) {
|
|
302535
|
+
postMessages.push({ kind: "info", text: "Edit cancelled \u2014 no change." });
|
|
302536
|
+
helpers.render();
|
|
302537
|
+
return;
|
|
302538
|
+
}
|
|
302539
|
+
if (newJson.trim() === currentJson.trim()) {
|
|
302540
|
+
postMessages.push({ kind: "info", text: "Edit cancelled \u2014 config unchanged." });
|
|
302541
|
+
helpers.render();
|
|
302542
|
+
return;
|
|
302543
|
+
}
|
|
302544
|
+
let parsed;
|
|
302545
|
+
try {
|
|
302546
|
+
parsed = JSON.parse(newJson);
|
|
302547
|
+
} catch (e2) {
|
|
302548
|
+
postMessages.push({ kind: "error", text: `Invalid JSON: ${e2 instanceof Error ? e2.message : String(e2)}` });
|
|
302549
|
+
helpers.render();
|
|
302550
|
+
return;
|
|
302551
|
+
}
|
|
302552
|
+
const shapeErr = validateMcpConfigShape(parsed);
|
|
302553
|
+
if (shapeErr) {
|
|
302554
|
+
postMessages.push({ kind: "error", text: shapeErr });
|
|
302555
|
+
helpers.render();
|
|
302556
|
+
return;
|
|
302557
|
+
}
|
|
302558
|
+
pendingEdit = parsed;
|
|
302559
|
+
helpers.resolve({ confirmed: true, key: "__pending_edit__", index: -1 });
|
|
302560
|
+
});
|
|
302561
|
+
return true;
|
|
302562
|
+
}
|
|
302563
|
+
return false;
|
|
302564
|
+
}
|
|
302461
302565
|
});
|
|
302566
|
+
for (const msg of postMessages) {
|
|
302567
|
+
if (msg.kind === "info") renderInfo(msg.text);
|
|
302568
|
+
else if (msg.kind === "warn") renderWarning(msg.text);
|
|
302569
|
+
else renderError(msg.text);
|
|
302570
|
+
}
|
|
302571
|
+
if (pendingEdit) {
|
|
302572
|
+
try {
|
|
302573
|
+
await manager.disconnect(serverName);
|
|
302574
|
+
const c22 = await manager.addServer(serverName, pendingEdit);
|
|
302575
|
+
await ctx3.refreshMcpTools?.();
|
|
302576
|
+
if (c22.status === "connected") {
|
|
302577
|
+
renderInfo(`\u2714 ${serverName} updated and reconnected (${c22.tools.length} tools)`);
|
|
302578
|
+
} else {
|
|
302579
|
+
renderWarning(`\u26A0 ${serverName} saved but not connected: ${c22.error ?? "unknown"}`);
|
|
302580
|
+
}
|
|
302581
|
+
} catch (e2) {
|
|
302582
|
+
renderError(`Save failed: ${e2 instanceof Error ? e2.message : String(e2)}`);
|
|
302583
|
+
}
|
|
302584
|
+
await showMcpDetailMenu(ctx3, serverName);
|
|
302585
|
+
return;
|
|
302586
|
+
}
|
|
302462
302587
|
if (!result || !result.confirmed || !result.key) {
|
|
302463
302588
|
await showMcpMainMenu(ctx3);
|
|
302464
302589
|
return;
|
|
@@ -302467,10 +302592,6 @@ async function showMcpDetailMenu(ctx3, serverName) {
|
|
|
302467
302592
|
await showMcpMainMenu(ctx3);
|
|
302468
302593
|
return;
|
|
302469
302594
|
}
|
|
302470
|
-
if (result.key === "act_edit") {
|
|
302471
|
-
await mcpEditServer(ctx3, serverName, persisted);
|
|
302472
|
-
return;
|
|
302473
|
-
}
|
|
302474
302595
|
if (result.key === "act_reconnect") {
|
|
302475
302596
|
renderInfo(`Reconnecting ${serverName}...`);
|
|
302476
302597
|
try {
|
|
@@ -302503,126 +302624,6 @@ async function showMcpDetailMenu(ctx3, serverName) {
|
|
|
302503
302624
|
return;
|
|
302504
302625
|
}
|
|
302505
302626
|
}
|
|
302506
|
-
async function mcpEditServer(ctx3, serverName, current) {
|
|
302507
|
-
const manager = ctx3.getMcpManager?.();
|
|
302508
|
-
if (!manager) return;
|
|
302509
|
-
const ask2 = (prompt) => new Promise((res) => {
|
|
302510
|
-
process.stdout.write(prompt);
|
|
302511
|
-
let buf = "";
|
|
302512
|
-
const onData = (d2) => {
|
|
302513
|
-
const s2 = d2.toString();
|
|
302514
|
-
if (s2.includes("\n")) {
|
|
302515
|
-
process.stdin.removeListener("data", onData);
|
|
302516
|
-
process.stdin.pause();
|
|
302517
|
-
res((buf + s2).split("\n")[0]);
|
|
302518
|
-
} else {
|
|
302519
|
-
buf += s2;
|
|
302520
|
-
}
|
|
302521
|
-
};
|
|
302522
|
-
process.stdin.resume();
|
|
302523
|
-
process.stdin.on("data", onData);
|
|
302524
|
-
});
|
|
302525
|
-
process.stdout.write(`
|
|
302526
|
-
${c3.cyan("Current config for ")}${c3.bold(serverName)}:
|
|
302527
|
-
`);
|
|
302528
|
-
process.stdout.write(` ${c3.dim(JSON.stringify(current ?? {}, null, 2).split("\n").join("\n "))}
|
|
302529
|
-
|
|
302530
|
-
`);
|
|
302531
|
-
process.stdout.write(` ${c3.cyan("Paste a new JSON config (single line) or press Enter to keep current.")}
|
|
302532
|
-
`);
|
|
302533
|
-
const newConfigJson = await ask2(" > ");
|
|
302534
|
-
if (!newConfigJson || newConfigJson.trim().length === 0) {
|
|
302535
|
-
renderInfo("No change.");
|
|
302536
|
-
await showMcpDetailMenu(ctx3, serverName);
|
|
302537
|
-
return;
|
|
302538
|
-
}
|
|
302539
|
-
let parsed;
|
|
302540
|
-
try {
|
|
302541
|
-
parsed = JSON.parse(newConfigJson);
|
|
302542
|
-
} catch (e2) {
|
|
302543
|
-
renderError(`Invalid JSON: ${e2 instanceof Error ? e2.message : String(e2)}`);
|
|
302544
|
-
await showMcpDetailMenu(ctx3, serverName);
|
|
302545
|
-
return;
|
|
302546
|
-
}
|
|
302547
|
-
if (!parsed || typeof parsed.command !== "string" && typeof parsed.url !== "string") {
|
|
302548
|
-
renderError("Config must have either 'command' (stdio) or 'url' (http)");
|
|
302549
|
-
await showMcpDetailMenu(ctx3, serverName);
|
|
302550
|
-
return;
|
|
302551
|
-
}
|
|
302552
|
-
try {
|
|
302553
|
-
await manager.disconnect(serverName);
|
|
302554
|
-
const c22 = await manager.addServer(serverName, parsed);
|
|
302555
|
-
await ctx3.refreshMcpTools?.();
|
|
302556
|
-
if (c22.status === "connected") {
|
|
302557
|
-
renderInfo(`\u2714 ${serverName} updated and reconnected (${c22.tools.length} tools)`);
|
|
302558
|
-
} else {
|
|
302559
|
-
renderWarning(`\u26A0 ${serverName} saved but not connected: ${c22.error}`);
|
|
302560
|
-
}
|
|
302561
|
-
} catch (e2) {
|
|
302562
|
-
renderError(`Save failed: ${e2 instanceof Error ? e2.message : String(e2)}`);
|
|
302563
|
-
}
|
|
302564
|
-
await showMcpMainMenu(ctx3);
|
|
302565
|
-
}
|
|
302566
|
-
async function mcpAddServerInteractive(ctx3) {
|
|
302567
|
-
const ask2 = (prompt) => new Promise((res) => {
|
|
302568
|
-
process.stdout.write(prompt);
|
|
302569
|
-
let buf = "";
|
|
302570
|
-
const onData = (d2) => {
|
|
302571
|
-
const s2 = d2.toString();
|
|
302572
|
-
if (s2.includes("\n")) {
|
|
302573
|
-
process.stdin.removeListener("data", onData);
|
|
302574
|
-
process.stdin.pause();
|
|
302575
|
-
res((buf + s2).split("\n")[0]);
|
|
302576
|
-
} else {
|
|
302577
|
-
buf += s2;
|
|
302578
|
-
}
|
|
302579
|
-
};
|
|
302580
|
-
process.stdin.resume();
|
|
302581
|
-
process.stdin.on("data", onData);
|
|
302582
|
-
});
|
|
302583
|
-
process.stdout.write(`
|
|
302584
|
-
${c3.cyan("Add MCP server")}
|
|
302585
|
-
`);
|
|
302586
|
-
process.stdout.write(` ${c3.dim("Tip: drag-drop a markdown file with an MCP config block onto the terminal for auto-intake.")}
|
|
302587
|
-
|
|
302588
|
-
`);
|
|
302589
|
-
const name10 = await ask2(` ${c3.cyan("Server name:")} `);
|
|
302590
|
-
if (!name10 || name10.trim().length === 0) {
|
|
302591
|
-
renderInfo("Cancelled.");
|
|
302592
|
-
return;
|
|
302593
|
-
}
|
|
302594
|
-
process.stdout.write(` ${c3.cyan('Config JSON (one line, e.g. {"command":"npx","args":["-y","@modelcontextprotocol/server-memory"]}):')}
|
|
302595
|
-
`);
|
|
302596
|
-
const cfgStr = await ask2(" > ");
|
|
302597
|
-
let parsed;
|
|
302598
|
-
try {
|
|
302599
|
-
parsed = JSON.parse(cfgStr);
|
|
302600
|
-
} catch (e2) {
|
|
302601
|
-
renderError(`Invalid JSON: ${e2 instanceof Error ? e2.message : String(e2)}`);
|
|
302602
|
-
return;
|
|
302603
|
-
}
|
|
302604
|
-
if (!parsed || typeof parsed.command !== "string" && typeof parsed.url !== "string") {
|
|
302605
|
-
renderError("Config must have either 'command' (stdio) or 'url' (http)");
|
|
302606
|
-
return;
|
|
302607
|
-
}
|
|
302608
|
-
const manager = ctx3.getMcpManager?.();
|
|
302609
|
-
if (!manager) {
|
|
302610
|
-
renderError("MCP manager not available");
|
|
302611
|
-
return;
|
|
302612
|
-
}
|
|
302613
|
-
try {
|
|
302614
|
-
const c22 = await manager.addServer(name10.trim(), parsed);
|
|
302615
|
-
await ctx3.refreshMcpTools?.();
|
|
302616
|
-
if (c22.status === "connected") {
|
|
302617
|
-
renderInfo(`\u2714 ${name10.trim()} added and connected (${c22.tools.length} tools)`);
|
|
302618
|
-
} else {
|
|
302619
|
-
renderWarning(`\u26A0 ${name10.trim()} saved but not connected: ${c22.error}`);
|
|
302620
|
-
}
|
|
302621
|
-
} catch (e2) {
|
|
302622
|
-
renderError(`Add failed: ${e2 instanceof Error ? e2.message : String(e2)}`);
|
|
302623
|
-
}
|
|
302624
|
-
await showMcpMainMenu(ctx3);
|
|
302625
|
-
}
|
|
302626
302627
|
async function handleUpdate(subcommand, ctx3) {
|
|
302627
302628
|
const repoRoot = ctx3.repoRoot;
|
|
302628
302629
|
if (subcommand === "auto") {
|
package/package.json
CHANGED