agentscope-ai/agentscope · error · ValueError
Tool {name!r} not found in MCP {self.name!r}.
Error message
Tool {name!r} not found in MCP {self.name!r}. What it means
Raised by GatewayMCPClient.get_tool(name) when no upstream tool with that exact name exists in the cached tool list (after a list_raw_tools() refresh on cache miss). This is a plain lookup miss: the name doesn't match any raw.name from the MCP server's advertised tools. Note enable_tools/disable_tools filtering does NOT hide tools from get_tool — it searches the unfiltered cache — so a mismatch means the upstream server genuinely doesn't expose that name.
Source
Thrown at src/agentscope/workspace/_gateway_client.py:369
name: str,
) -> GatewayMCPTool:
"""Look up a single tool by upstream name and wrap it.
Falls back to :meth:`list_raw_tools` on cache miss, then
searches the unfiltered cache so tools that ``enable_tools`` /
``disable_tools`` would have hidden are still resolvable —
matching :meth:`MCPClient.get_tool`.
Raises:
`ValueError`:
No tool with that upstream name exists on the gateway.
"""
if self._cached_tools is None:
await self.list_raw_tools()
for raw in self._cached_tools or []:
if raw.name == name:
return self._wrap_tool(raw)
raise ValueError(
f"Tool {name!r} not found in MCP {self.name!r}.",
)
# ── helpers ───────────────────────────────────────────────────
def _wrap_tool(self, tool: mcp.types.Tool) -> GatewayMCPTool:
"""Build a :class:`GatewayMCPTool` bound to this client's
gateway facade.
"""
assert self._gateway is not None
return GatewayMCPTool(
mcp_name=self.name,
tool=tool,
gateway=self._gateway,
agent_id=self._agent_id,
session_id=self._session_id,
)
View on GitHub (pinned to e90f1c7592)
Solutions
- Print `await client.list_raw_tools()` (or `[t.name for t in ...]`) and use the exact upstream name shown
- Drop any `mcp__<name>__` prefix — get_tool expects the bare upstream tool name
- Catch ValueError and skip/fallback when the tool is optional
- Pin or verify the upstream MCP server version if tools were renamed
Example fix
// before
tool = await client.get_tool("mcp__fetch__fetch")
// after
tool = await client.get_tool("fetch") # bare upstream name Defensive patterns
Strategy: validation
Validate before calling
tools = await client.list_raw_tools()
names = {t.name for t in tools}
if name not in names:
raise KeyError(f"available: {sorted(names)}")
tool = await client.get_tool(name) Type guard
def tool_exists(client: GatewayMCPClient, name: str) -> bool:
return any(t.name == name for t in client._cached_tools or []) Try / catch
try:
tool = await client.get_tool(name)
except ValueError:
tool = None # optional tool, skip Prevention
- List tools once and derive names dynamically instead of hardcoding
- Use bare upstream names (no mcp__ prefix)
- Treat optional tools with a ValueError catch-and-skip
When it happens
Trigger: `await client.get_tool("fetch")` when the MCP server exposes e.g. "web_fetch" or an mcp__-prefixed name; calling get_tool before connect/list succeeded but the MCP exposes zero tools; typos or renamed tools after an upstream MCP server version change.
Common situations: Using the mcp__servername__tool prefixed name instead of the upstream bare name; upstream MCP server upgraded and renamed tools; typo in the tool name; assuming a tool exists without checking list_raw_tools() output.
Related errors
- STDIO MCP does not support ephemeral mode. Use 'shared' or '
- Invalid values for MCP {card.name!r}: {e.message}
- MCP {card.name!r} needs a value for: {', '.join(sorted(missi
- MCP {card.name!r} produced an invalid client: {e}
- An MCP named {mcp_record.name!r} already exists for this use
AI-assisted analysis of agentscope-ai/agentscope@e90f1c7592 (2026-08-28).
Data as JSON: /api/errors/c2fd1f2f02cb1b18.
Report an issue: GitHub.