koala73/worldmonitor · error

tools/call error: ${callResp.error.message}

Error message

tools/call error: ${callResp.error.message}

What it means

After a successful initialize, mcp-proxy sends JSON-RPC `tools/call` (id 2) with the requested toolName and arguments (defaulting to {}). This error means the server accepted the session but rejected the call itself: unknown tool, arguments failing the tool's input schema, or the tool executed and reported its own failure through the RPC error channel.

Source

Thrown at api/mcp-proxy.ts:541

  } finally {
    session.close();
  }
}

async function mcpCallToolSse(serverUrl, toolName, toolArgs, customHeaders) {
  const headers = buildHeaders(customHeaders);
  const session = new SseSession(serverUrl.toString(), headers);
  try {
    await session.connect();
    const initResp = await session.send(1, 'initialize', {
      protocolVersion: MCP_PROTOCOL_VERSION,
      capabilities: {},
      clientInfo: { name: 'worldmonitor', version: '1.0' },
    });
    if (initResp.error) throw new Error(`Initialize error: ${initResp.error.message}`);
    await session.notify('notifications/initialized', {});
    const callResp = await session.send(2, 'tools/call', { name: toolName, arguments: toolArgs || {} });
    if (callResp.error) throw new Error(`tools/call error: ${callResp.error.message}`);
    return callResp.result;
  } finally {
    session.close();
  }
}

// --- Request handler ---

interface ProxyMeta {
  targetHost: string;
  targetPath: string;
  headerNames: string[];
}

function captureMeta(serverUrl: URL, customHeaders: unknown, meta: ProxyMeta): void {
  meta.targetHost = serverUrl.hostname;
  meta.targetPath = serverUrl.pathname;
  meta.headerNames = Object.keys((customHeaders as Record<string, unknown>) || {})

View on GitHub (pinned to 9361220cc0)

Solutions

  1. List the server's tools (tools/list through the proxy, or `worldmonitor tools`) and copy the exact name
  2. Validate toolArgs against the tool's inputSchema — fill every required field with the right primitive type
  3. Decode the embedded message: -32602 invalid params, -32601 unknown tool/method, other codes are tool-specific failures
  4. If the tool itself failed, correct the inputs it names (bad country code, unknown id) and retry

Example fix

// before
const callResp = await session.send(2, 'tools/call', { name: toolName, arguments: toolArgs || {} });
if (callResp.error) throw new Error(`tools/call error: ${callResp.error.message}`);

// after — list tools first and fail with the available names
const listResp = await session.send(2, 'tools/list', {});
const tools = (listResp.result && listResp.result.tools) || [];
if (!tools.some((t) => t.name === toolName)) {
  throw new Error(`Unknown tool: ${toolName}. Available: ${tools.map((t) => t.name).join(', ')}`);
}
Defensive patterns

Strategy: validation

Validate before calling

// Fetch tools/list once, then validate name + required args before calling
const { result } = await mcpCallToolSse(serverUrl, '__list__', undefined, headers); // or a tools/list helper
const tool = tools.find((t) => t.name === toolName);
if (!tool) throw new UsageError(`Unknown tool ${toolName}`);
const required = tool.inputSchema?.required ?? [];
const missing = required.filter((k) => args?.[k] === undefined);
if (missing.length) throw new UsageError(`Missing args: ${missing.join(', ')}`);

Type guard

function isToolDescriptor(v: unknown): v is { name: string; inputSchema?: { required?: string[] } } {
  return typeof v === 'object' && v !== null && typeof (v as any).name === 'string';
}

Try / catch

try {
  await mcpCallToolSse(serverUrl, toolName, args, headers);
} catch (err) {
  if (err instanceof Error && err.message.startsWith('tools/call error:')) {
    // server-side rejection: unknown tool or invalid args — fix inputs, do not blind-retry
    return { retryable: false, reason: err.message };
  }
  throw err;
}

Prevention

When it happens

Trigger: toolName does not exist on the server (typo, renamed tool, different server version); toolArgs missing required fields or with wrong types per the tool's inputSchema; calling a tool with {} when it requires parameters; the tool ran and failed server-side, returning its error via the RPC layer.

Common situations: Frontend hardcodes a tool name that changed after a server update; callers assume the proxy validates arguments; passing nested objects as strings; one-shot SSE sessions used for tools that need prior session state.

Related errors


AI-assisted analysis of koala73/worldmonitor@9361220cc0 (2026-08-21). Data as JSON: /api/errors/6dc83c7a825ed6a3. Report an issue: GitHub.