jd-opensource/joyagent-jdgenie · error · Exception

调用工具 ' ' 失败

Error message

调用工具 '{name}' 失败: {str(e)}

What it means

`call_tool` wraps any exception raised during the SSE session or the MCP tool invocation into an Exception prefixed with the tool name. The root cause (connection failure, tool-side error, invalid arguments returned by the server) is chained via `from e`.

Solutions

  1. Read the appended inner message / `__cause__` for the real cause
  2. Verify the tool exists via list_tools and its input schema matches your arguments dict
  3. Retry on transient network errors with backoff
  4. Reproduce the call manually (curl / direct MCP session) to isolate client vs server

Example fix

// before
await client.call_tool("search", args)
// after
try:
    await client.call_tool("search", args)
except Exception as e:
    logger.exception(e.__cause__)  # unwrap the tool/server failure
    raise
Defensive patterns

Strategy: try-catch

Validate before calling

tools = {t.name for t in await client.list_tools()}
if name not in tools:
    raise ValueError(f"Tool '{name}' not available on server")

Type guard

async def tool_exists(client, name: str) -> bool:
    tools = await client.list_tools()
    return any(getattr(t, "name", None) == name for t in tools)

Try / catch

try:
    return await client.call_tool(name, args)
except Exception as e:
    cause = e.__cause__
    if isinstance(cause, (ConnectionError, TimeoutError)):
        retry_with_backoff()
    raise

Prevention

When it happens

Trigger: `client.call_tool(name, arguments)` where the SSE connection fails, the server rejects the call, or the tool itself raises during execution.

Common situations: Calling a tool that doesn't exist on the server; tool argument schema mismatch; transient connectivity drop mid-call; server-side tool bug.

Related errors


AI-assisted analysis of jd-opensource/joyagent-jdgenie@2417e0b8b6 (2026-09-08). Data as JSON: /api/errors/f60543aaa0aa0bd5. Report an issue: GitHub.

Appendix: source

Thrown at genie-client/app/client.py:335

        elif not isinstance(arguments, dict):
            raise ValueError("工具参数必须是字典类型")

        try:
            async with self._sse_connection() as session:
                logger.info(f"正在调用工具 '{name}',参数: {arguments}")

                # 调用工具
                response = await session.call_tool(name=name, arguments=arguments)

                logger.info(f"工具 '{name}' 执行成功")
                logger.debug(f"工具 '{name}' 返回结果类型: {type(response).__name__}")

                return response

        except Exception as e:
            error_msg = f"调用工具 '{name}' 失败: {str(e)}"
            logger.error(error_msg)
            raise Exception(error_msg) from e

    def __str__(self) -> str:
        """返回客户端的字符串表示"""
        return f"SseClient(server_url='{self.server_url}', timeout={self.timeout}s)"

    def __repr__(self) -> str:
        """返回客户端的详细字符串表示"""
        return (f"SseClient(server_url='{self.server_url}', "
                f"timeout={self.timeout}, "
                f"sse_read_timeout={self.sse_read_timeout}, "
                f"headers_count={len(self.headers)})")

View on GitHub (pinned to 2417e0b8b6)