can1357/oh-my-pi · error

${name}: ${message} (joined by "; ")

Error message

${name}: ${message} (joined by "; ")

What it means

After connecting the configured MCP servers, manager.connectServers returns an errors map of server name → failure message. If any server failed, AcpAgent aggregates all entries into one message joined by "; " and throws, so the ACP client sees every failing server at once. It surfaces MCP infrastructure problems that would otherwise silently leave tools unavailable.

Source

Thrown at packages/coding-agent/src/modes/acp/acp-agent.ts:2678

		manager.setOnToolsChanged(() => {
			// Failures are logged once via the stored chain's catch above.
			enqueueMcpToolsRefresh().catch(() => {});
		});
		const configs: MCPConfigMap = {};
		const sources: MCPSourceMap = {};
		for (const server of servers) {
			configs[server.name] = this.#toMcpConfig(server);
			sources[server.name] = {
				provider: "acp",
				providerName: "ACP Client",
				path: `acp://${server.name}`,
				level: "project",
			};
		}

		const result = await manager.connectServers(configs, sources);
		if (result.errors.size > 0) {
			throw new Error(
				Array.from(result.errors.entries())
					.map(([name, message]) => `${name}: ${message}`)
					.join("; "),
			);
		}

		record.mcpManager = manager;
		await enqueueMcpToolsRefresh();
	}

	#toMcpConfig(server: McpServer): MCPServerConfig {
		if ("command" in server) {
			return {
				type: "stdio",
				command: server.command,
				args: server.args,
				env: this.#toNameValueMap(server.env),
			};

View on GitHub (pinned to 9690622007)

Solutions

  1. Read the per-server messages in the error (format 'name: message; ...') and fix each named server's command/URL/auth in the MCP config.
  2. Verify server executables are installed and on PATH, and HTTP servers are reachable (curl the URL).
  3. Temporarily remove the failing server from config to unblock the session, then repair it separately.

Example fix

// before (config)
{ "mcpServers": { "fs": { "command": "mcp-fs", "args": [] } } }
// after
{ "mcpServers": { "fs": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"] } } }
Defensive patterns

Strategy: try-catch

Validate before calling

for (const [name, cfg] of Object.entries(configs)) {
  if (cfg.command && !(await which(cfg.command).catch(() => null))) {
    logger.warn("MCP command not found, skipping", { name, command: cfg.command });
    delete configs[name];
  }
}
await manager.connectServers(configs, sources);

Try / catch

try {
  await manager.connectServers(configs, sources);
} catch (err) {
  const failures = err.message.split("; ").map(s => s.split(":")[0]);
  logger.error("MCP servers failed to connect", { failures });
  // proceed with degraded tool set or rethrow
}

Prevention

When it happens

Trigger: Calling the ACP MCP-server configuration RPC where connectServers reports a non-empty errors map — any per-server connect failure (bad command, unreachable URL, auth failure) triggers it.

Common situations: An MCP server command is not on PATH; an HTTP/SSE server URL is wrong or down; a header token expired; project vs user config points at conflicting server definitions.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/f240e0e4cfa73f35. Report an issue: GitHub.