agentscope-ai/agentscope · error · RuntimeError
gateway failed to list tools for MCP {self.name!r}: {_safe_d
Error message
gateway failed to list tools for MCP {self.name!r}: {_safe_detail(status, body)} What it means
Raised by GatewayMCPClient.list_raw_tools() when GET /mcps/{name}/tools through the sandbox gateway returns HTTP >= 400. The gateway could not fetch the tool list from the upstream MCP server — usually because the MCP is not connected/registered, the upstream MCP server died, or the agent/session ids don't match. Note this method is also called lazily by get_tool() on cache miss.
Source
Thrown at src/agentscope/workspace/_gateway_client.py:330
re-wrap them like a local :class:`MCPClient`. The unfiltered
list is cached; the returned list has ``enable_tools`` /
``disable_tools`` applied.
Raises:
`RuntimeError`:
Gateway returned non-2xx.
"""
assert self._gateway is not None
status, body = await self._gateway.exec_request(
"GET",
f"/mcps/{self.name}/tools",
params={
"agent_id": self._agent_id,
"session_id": self._session_id,
},
)
if status >= 400:
raise RuntimeError(
f"gateway failed to list tools for MCP {self.name!r}: "
f"{_safe_detail(status, body)}",
)
data = json.loads(body)
raw_tools = [mcp.types.Tool.model_validate(d) for d in data]
self._cached_tools = raw_tools
# Gateway returns the unfiltered upstream view; honour the same
# enable/disable filtering ``MCPClient`` applies locally.
if self.enable_tools is not None:
raw_tools = [t for t in raw_tools if t.name in self.enable_tools]
if self.disable_tools is not None:
raw_tools = [
t for t in raw_tools if t.name not in self.disable_tools
]
return raw_tools
View on GitHub (pinned to e90f1c7592)
Solutions
- Ensure `await client.connect()` completed successfully before listing tools / calling get_tool
- Call `await gateway.health()` to confirm the gateway is alive, then `list_mcps()` to confirm the MCP is registered
- Check the status/body detail in the message: 404 means unregistered, 500 usually means the upstream MCP server died — inspect gateway logs (gateway_log_path)
- Re-create the client with correct agent_id/session_id if the gateway was restarted
Example fix
// before client = gateway.make_client(spec) tools = await client.list_raw_tools() # RuntimeError // after client = gateway.make_client(spec) await client.connect() tools = await client.list_raw_tools()
Defensive patterns
Strategy: try-catch
Validate before calling
tools = await client.list_raw_tools()
names = {t.name for t in tools}
if want not in names: ... Try / catch
try:
tools = await client.list_raw_tools()
except RuntimeError as e:
if "gateway failed to list tools" in str(e):
# reconnect or re-register the MCP
await client.connect()
raise Prevention
- Always `await client.connect()` before tool discovery
- Use list_mcps() to verify registration before listing tools
- Wrap get_tool calls since they lazily trigger list_raw_tools
When it happens
Trigger: `await client.list_raw_tools()` or `await client.get_tool(name)` (cache miss triggers list) when the MCP was never connect()-ed on the gateway, the upstream MCP server process exited, or the gateway returned 404/500 for the tools listing.
Common situations: Forgetting `await client.connect()` before tool discovery; using a GatewayMCPClient built via make_client(connected=False) without connecting; upstream MCP server (stdio/sse) crashed inside the sandbox; stale agent_id/session_id after gateway restart.
Related errors
- gateway failed to remove MCP {self.name!r}: {_safe_detail(st
- gateway failed to list MCPs: {_safe_detail(status, body)}
- {name!r} not found for agent={agent_id!r} session={session_i
- name required
- {name!r} already exists for agent={agent_id!r} session={sess
AI-assisted analysis of agentscope-ai/agentscope@e90f1c7592 (2026-08-28).
Data as JSON: /api/errors/b983ac65bdafe68e.
Report an issue: GitHub.