t8y2/dbx · error · Error

DBX MCP tool failed: ${tool.name}

Error message

DBX MCP tool failed: ${tool.name}

What it means

When a tools/call response has isError set, execute() throws the tool's own text content if present, otherwise a generic 'DBX MCP tool failed: <tool.name>'. This surfaces MCP-server-side tool failures as host tool errors.

Source

Thrown at crates/dbx-core/assets/pi-mcp-bridge.mjs:182

  send({ jsonrpc: "2.0", method: "notifications/initialized", params: {} });

  const toolList = await request("tools/list");
  const tools = (toolList?.tools ?? []).filter((tool) => enabledTools.has(tool.name));
  const missing = [...enabledTools].filter((name) => !tools.some((tool) => tool.name === name));
  if (missing.length > 0) {
    throw new Error(`DBX MCP did not expose required tools: ${missing.join(", ")}`);
  }

  for (const tool of tools) {
    pi.registerTool({
      name: tool.name,
      label: tool.title ?? tool.name,
      description: tool.description ?? "",
      parameters: tool.inputSchema ?? { type: "object", properties: {} },
      async execute(_toolCallId, params, signal) {
        const result = await request("tools/call", { name: tool.name, arguments: params ?? {} }, signal);
        if (result?.isError) {
          throw new Error(textFromContent(result.content) || `DBX MCP tool failed: ${tool.name}`);
        }
        return {
          content: piContent(result?.content),
          details: result ?? null,
        };
      },
    });
  }

  await writeFile(readyFile, "ready", "utf8");

  pi.on("session_shutdown", async () => {
    if (closed) return;
    closed = true;
    lines.close();
    child.stdin.end();
    child.kill();
  });

View on GitHub (pinned to c0390bff16)

Solutions

  1. Read the returned error text (result.content) for the server's message and fix the arguments accordingly
  2. Validate params against the tool's inputSchema (tool.parameters) before calling
  3. Check the MCP server logs for the underlying exception; fix or upgrade the server if content is empty

Example fix

// before
await bridge.callTool("dbx_search", { q: 42 }); // wrong param type
// after
await bridge.callTool("dbx_search", { query: "foo", limit: 10 }); // matches inputSchema
Defensive patterns

Strategy: try-catch

Validate before calling

function validateParams(schema, params) {
  for (const key of Object.keys(schema?.properties ?? {})) {
    if (schema.required?.includes(key) && params?.[key] === undefined) {
      throw new Error('missing required param: ' + key);
    }
  }
}

Type guard

function isToolError(result) {
  return result != null && typeof result === 'object' && result.isError === true;
}

Try / catch

try {
  const result = await request('tools/call', { name, arguments: params }, signal);
  if (isToolError(result)) {
    const detail = textFromContent(result.content);
    console.error(`tool ${name} failed: ${detail || 'no detail'}`);
  }
} catch (e) {
  console.error(`tool ${name} rpc error:`, e.message);
}

Prevention

When it happens

Trigger: The child MCP server returns { isError: true } for a tool call — e.g. invalid arguments against inputSchema, server-side exception, resource not found — and the result has no text content.

Common situations: Caller passed params not matching the tool's inputSchema; the underlying operation the tool wraps failed (bad query, missing file, permissions); server bug returning isError with empty content.

Related errors


AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05). Data as JSON: /api/errors/7ab8e16d98872d34. Report an issue: GitHub.