jd-opensource/joyagent-jdgenie · error · Exception
获取工具列表失败
Error message
{self.server_url} 获取工具列表失败: {str(e)} What it means
`list_tools` wraps any exception from opening the SSE session or executing the MCP `list_tools` request into an Exception prefixed with the server URL. Like ping_server, it is a labeling wrapper over the underlying auth/network/protocol error.
Solutions
- Check the appended inner message / `__cause__` to identify the root cause (auth, network, or protocol)
- Confirm the server actually implements the MCP tools capability and a compatible protocol version
- Verify connectivity and credentials (same checks as ping_server)
- Capture and inspect server logs for the corresponding request
Example fix
// before
tools = await client.list_tools() # no error context surfaced
// after
try:
tools = await client.list_tools()
except Exception as e:
logger.exception(e.__cause__) # inspect the wrapped root cause
raise Defensive patterns
Strategy: try-catch
Validate before calling
try:
await client.ping_server() # connectivity/auth precheck
except Exception:
raise RuntimeError("server unavailable; skip list_tools")
typeGuard = None Try / catch
try:
tools = await client.list_tools()
except Exception as e:
logger.error(f"list_tools failed: {e.__cause__}")
tools = [] # or re-raise depending on criticality Prevention
- Confirm server MCP protocol/capability compatibility on upgrades
- Precheck with ping_server before listing tools
- Keep client and server versions aligned
When it happens
Trigger: Calling `await client.list_tools()` when the SSE connection fails (auth/network) or the server returns an invalid tools payload.
Common situations: Server doesn't implement the tools capability; MCP protocol version mismatch; same connectivity/auth misconfigurations as ping failures.
Related errors
AI-assisted analysis of jd-opensource/joyagent-jdgenie@2417e0b8b6 (2026-09-08).
Data as JSON: /api/errors/a4edc8bcb8727c44.
Report an issue: GitHub.
Appendix: source
Thrown at genie-client/app/client.py:294
try:
async with self._sse_connection() as session:
logger.info(f"{self.server_url} 正在获取工具列表...")
response = await session.list_tools()
tools = response.tools if hasattr(response, 'tools') else []
tool_count = len(tools)
logger.info(f"成功获取 {tool_count} 个工具")
# 记录工具名称(如果工具有name属性)
if tools and hasattr(tools[0], 'name'):
tool_names = [tool.name for tool in tools if hasattr(tool, 'name')]
logger.debug(f"工具列表: {', '.join(tool_names)}")
return tools
except Exception as e:
error_msg = f"{self.server_url} 获取工具列表失败: {str(e)}"
logger.error(error_msg)
raise Exception(error_msg) from e
async def call_tool(self, name: str, arguments: Optional[Dict[str, Any]] = None) -> Any:
"""
调用指定的工具
Args:
name: 工具名称
arguments: 工具参数字典,默认为空字典
Returns:
Any: 工具执行结果
Raises:
ValueError: 当工具名称无效时抛出
Exception: 当工具调用失败时抛出异常
"""
# 参数验证
if not name or not isinstance(name, str):View on GitHub (pinned to 2417e0b8b6)