u-foo 2.4.10 → 2.4.11

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/bin/ufoo.js CHANGED
@@ -13,6 +13,21 @@ function hasGlobalModeFlag(args = []) {
13
13
  return args.includes("-g") || args.includes("--global");
14
14
  }
15
15
 
16
+ function printMcpHelp() {
17
+ console.log("Usage: ufoo mcp [options]");
18
+ console.log("");
19
+ console.log("Run the local global ufoo MCP bridge over stdio.");
20
+ console.log("");
21
+ console.log("Options:");
22
+ console.log(" --no-auto-start Do not auto-start the home-scoped global controller daemon");
23
+ console.log(" -h, --help Display help for the MCP bridge command");
24
+ console.log("");
25
+ console.log("Notes:");
26
+ console.log(" Configure MCP-capable clients with command: ufoo mcp");
27
+ console.log(" Example without daemon auto-start: ufoo mcp --no-auto-start");
28
+ console.log(" Human diagnostics are available in chat: /mcp status, /mcp tools, /mcp help");
29
+ }
30
+
16
31
  async function main() {
17
32
  const globalMode = hasGlobalModeFlag(rawArgv);
18
33
  const argv = rawArgv.filter((arg) => arg !== "-g" && arg !== "--global");
@@ -28,6 +43,10 @@ async function main() {
28
43
  return;
29
44
  }
30
45
  if (cmd === "mcp") {
46
+ if (argv.includes("--help") || argv.includes("-h")) {
47
+ printMcpHelp();
48
+ return;
49
+ }
31
50
  await runMcpServer({
32
51
  autoStart: !argv.includes("--no-auto-start"),
33
52
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "u-foo",
3
- "version": "2.4.10",
3
+ "version": "2.4.11",
4
4
  "description": "Multi-Agent Workspace Protocol. Just add u. claude → uclaude, codex → ucodex.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "homepage": "https://ufoo.dev",
@@ -24,6 +24,10 @@ const {
24
24
  inspectDirectAuthStatus,
25
25
  formatDirectAuthStatus,
26
26
  } = require("../../agents/providers/directAuthStatus");
27
+ const {
28
+ buildToolList: defaultBuildMcpToolList,
29
+ createUfooMcpServer: defaultCreateMcpServer,
30
+ } = require("../../runtime/daemon/mcpServer");
27
31
 
28
32
  function defaultCreateDoctor(projectRoot) {
29
33
  const UfooDoctor = require("../cli/features/doctor");
@@ -147,6 +151,8 @@ function createCommandExecutor(options = {}) {
147
151
  runGroupCore = runGroupCoreCommand,
148
152
  inspectDirectAuth = inspectDirectAuthStatus,
149
153
  formatDirectAuth = formatDirectAuthStatus,
154
+ buildMcpToolList = defaultBuildMcpToolList,
155
+ createMcpServer = defaultCreateMcpServer,
150
156
  requestCron = null,
151
157
  globalMode = false,
152
158
  listProjects = () => [],
@@ -335,6 +341,93 @@ function createCommandExecutor(options = {}) {
335
341
  );
336
342
  }
337
343
 
344
+ function logMcpHelp() {
345
+ logMessage("system", "{cyan-fg}MCP bridge:{/cyan-fg} local stdio bridge for external MCP-capable agents");
346
+ logMessage("system", " • Configure client command: ufoo mcp");
347
+ logMessage("system", " • Disable daemon auto-start: ufoo mcp --no-auto-start");
348
+ logMessage("system", " • Topology: one global bridge, project tools route through registered project daemons");
349
+ logMessage("system", " • Chat diagnostics: /mcp status, /mcp tools, /mcp help");
350
+ }
351
+
352
+ async function readMcpStatus() {
353
+ const server = createMcpServer({
354
+ autoStart: false,
355
+ validateProjectRoot: true,
356
+ });
357
+ const response = await server.handleRequest({
358
+ jsonrpc: "2.0",
359
+ id: "chat-mcp-status",
360
+ method: "tools/call",
361
+ params: {
362
+ name: "ufoo_mcp_status",
363
+ arguments: {},
364
+ },
365
+ });
366
+ if (response && response.error) {
367
+ const message = response.error.message || "MCP status request failed";
368
+ throw new Error(message);
369
+ }
370
+ return response && response.result ? response.result.structuredContent : null;
371
+ }
372
+
373
+ async function handleMcpCommand(args = []) {
374
+ const subcommand = String(args[0] || "status").trim().toLowerCase();
375
+
376
+ if (subcommand === "help") {
377
+ logMcpHelp();
378
+ renderScreen();
379
+ return;
380
+ }
381
+
382
+ if (subcommand === "tools") {
383
+ try {
384
+ const tools = buildMcpToolList();
385
+ logMessage("system", `{cyan-fg}MCP tools:{/cyan-fg} ${tools.length} exposed tool(s)`);
386
+ for (const tool of tools) {
387
+ const name = escapeBlessed(tool.name || "");
388
+ const desc = escapeBlessed(tool.description || "");
389
+ logMessage("system", ` • {cyan-fg}${name}{/cyan-fg}${desc ? ` - ${desc}` : ""}`);
390
+ }
391
+ } catch (err) {
392
+ logMessage("error", `{white-fg}✗{/white-fg} MCP tools failed: ${escapeBlessed(err.message)}`);
393
+ }
394
+ renderScreen();
395
+ return;
396
+ }
397
+
398
+ if (subcommand === "status") {
399
+ try {
400
+ const status = await readMcpStatus();
401
+ if (!status) {
402
+ throw new Error("empty MCP status response");
403
+ }
404
+ const projects = Array.isArray(status.projects) ? status.projects : [];
405
+ logMessage("system", "{cyan-fg}MCP bridge:{/cyan-fg} local stdio server");
406
+ logMessage("system", " • command: {cyan-fg}ufoo mcp{/cyan-fg}");
407
+ logMessage("system", ` • global controller: ${escapeBlessed(status.global_controller_root || "")}`);
408
+ logMessage("system", ` • daemon: ${status.global_controller_running ? "{green-fg}running{/green-fg}" : "{yellow-fg}not running{/yellow-fg}"}`);
409
+ logMessage("system", " • client auto-start: enabled by default");
410
+ logMessage("system", ` • status probe auto-start: ${status.auto_start ? "enabled" : "disabled"}`);
411
+ logMessage("system", ` • registered projects: ${projects.length}`);
412
+ for (const project of projects.slice(0, 5)) {
413
+ const label = project.project_name || project.name || project.project_root || "";
414
+ const root = project.project_root || "";
415
+ logMessage("system", ` - ${escapeBlessed(label)}${root && root !== label ? ` (${escapeBlessed(root)})` : ""}`);
416
+ }
417
+ if (projects.length > 5) {
418
+ logMessage("system", ` - ... ${projects.length - 5} more`);
419
+ }
420
+ } catch (err) {
421
+ logMessage("error", `{white-fg}✗{/white-fg} MCP status failed: ${escapeBlessed(err.message)}`);
422
+ }
423
+ renderScreen();
424
+ return;
425
+ }
426
+
427
+ logMessage("error", "{white-fg}✗{/white-fg} Unknown MCP command. Use: status, tools, help");
428
+ renderScreen();
429
+ }
430
+
338
431
  async function handleBusCommand(args = []) {
339
432
  const subcommand = args[0];
340
433
 
@@ -1608,6 +1701,9 @@ function createCommandExecutor(options = {}) {
1608
1701
  logMessage("error", "{white-fg}✗{/white-fg} Multi-window mode is not available");
1609
1702
  }
1610
1703
  return true;
1704
+ case "mcp":
1705
+ await handleMcpCommand(args);
1706
+ return true;
1611
1707
  case "doctor":
1612
1708
  await handleDoctorCommand();
1613
1709
  return true;
@@ -1670,6 +1766,7 @@ function createCommandExecutor(options = {}) {
1670
1766
  handleDoctorCommand,
1671
1767
  handleStatusCommand,
1672
1768
  handleDaemonCommand,
1769
+ handleMcpCommand,
1673
1770
  handleInitCommand,
1674
1771
  handleBusCommand,
1675
1772
  handleCtxCommand,
@@ -49,6 +49,14 @@ const COMMAND_TREE = {
49
49
  },
50
50
  "/init": { desc: "Initialize workspace" },
51
51
  "/multi": { desc: "Toggle multi-window agent view" },
52
+ "/mcp": {
53
+ desc: "MCP bridge diagnostics",
54
+ children: {
55
+ status: { desc: "Show global MCP bridge status", order: 1 },
56
+ tools: { desc: "List exposed MCP tools", order: 2 },
57
+ help: { desc: "Show MCP setup hints", order: 3 },
58
+ },
59
+ },
52
60
  "/open": { desc: "Open project path in global mode" },
53
61
  "/launch": {
54
62
  desc: "Launch new agent",
@@ -298,6 +306,13 @@ function describeCommandForChat(text) {
298
306
  return "Managing cron tasks";
299
307
  }
300
308
 
309
+ if (command === "mcp") {
310
+ if (!sub || sub === "status") return "Checking MCP bridge status";
311
+ if (sub === "tools") return "Listing MCP tools";
312
+ if (sub === "help") return "Showing MCP setup help";
313
+ return `Running /mcp ${sub}`;
314
+ }
315
+
301
316
  if (command === "settings") return !sub || sub === "show" ? "Showing settings" : "Updating settings";
302
317
  if (command === "ctx") return `Checking context${sub ? ` ${sub}` : ""}`;
303
318
  if (command === "doctor") return "Running ufoo diagnostics";