Error executing tool get_order
Python · updated 2026-11-11
The text an MCP client (Claude Desktop, Claude Code, Cursor) shows when a tool in a Python server built on the official mcp SDK raises. On mcp 2.x the client gets only "Error executing tool get_order" with isError true; the server logs "Tool 'get_order' raised an unexpected exception" and the traceback (UnexpectedToolError raised from your exception) to its stderr. On mcp 1.x the client gets "Error executing tool get_order: 'missing-42'", the exception's message without its type, and the server logs nothing about it. Either way the cause is on the machine running the server, which for a local stdio server is your user's.
Tool 'get_order' raised an unexpected exception
Traceback (most recent call last):
File "server.py", line 9, in get_order
return rows["missing-" + order_id]
KeyError: 'missing-42'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File ".../mcp/server/mcpserver/tools/base.py", line 213, in run
raise UnexpectedToolError(f"Error executing tool {self.name}") from exc
mcp.server.mcpserver.exceptions.UnexpectedToolError: Error executing tool get_orderQuick fix
Find the real exception: it is the cause in the server's traceback (the first exception, before "The above exception was the direct cause"). For a local server, open the client's MCP log; for a remote one, the server's own logs. To see it without asking users for logs, report it: on mcp 2.x the SDK logs it, so an error tracker with a logging integration records it with the line in your tool; on mcp 1.x catch it in the tool and report it yourself.
- Read the cause, not the wrapper: KeyError, TypeError or whatever your code raised, and the line in your tool.
- Local server: Claude Desktop writes each server's stderr to the mcp*.log files in ~/Library/Logs/Claude on macOS; Claude Code shows it with claude --debug=mcp.
- Fix the tool, and return a clear message for expected failures (a missing order) instead of letting them raise.
- On mcp 1.x, wrap the body in try/except, report the exception, then raise so the client still gets an error result.
- Raise ToolError (from mcp.server.mcpserver.exceptions on 2.x) with a message when you want the model to see a specific reason.
import os, runheed
from mcp.server.mcpserver import MCPServer
runheed.init(dsn=os.environ["RUNHEED_DSN"]) # the logging integration reports what the SDK logs
mcp = MCPServer("orders")
@mcp.tool()
def get_order(order_id: str) -> str:
"""Look up an order by id."""
order = ORDERS.get(order_id)
if order is None:
return f"No order {order_id}" # an expected miss is an answer, not an error
return format_order(order)Paste this into Claude Code, Cursor or Codex in the project that throws it. The agent reads this guide in plain text and applies the fix that matches your stack.
Read https://runheed.com/errors/mcp-error-executing-tool.md and fix this error in this project.Why it happens
A bug in the tool
A KeyError, TypeError or AttributeError on data the model passed that you did not expect: an ID that does not exist, an empty string, a different shape.
A dependency failing
The database, an API or a file the tool reads is down, slow or missing in the environment the client started the server in.
Missing configuration
An environment variable that is set in your shell but not in the client's MCP config, so the tool reads None.
Other fixes
- Argument validation failures are different: the message lists the fields that failed ("validation errors for get_orderArguments"), and your tool never ran.
- With Runheed's Python SDK 0.1.6 or later, the 2.x wrapper is reported with your tool's line first and grouped per tool; the original exception is listed under causes.
Same error, other wording
- Error executing tool get_order: 'missing-42' (mcp 1.x)
- mcp.server.mcpserver.exceptions.UnexpectedToolError: Error executing tool get_order
- Tool 'get_order' raised an unexpected exception
Let your coding agent catch the next one
Runheed records this error in production with the stack trace, the breadcrumbs before it and, when you set it, the agent session that shipped the code, and serves it to Claude Code, Cursor or any MCP client. With it connected, you can ask:
> Find the MCP tool errors in my Python server, show me the real exception behind each "Error executing tool", fix the tool and resolve the error with the commit.
Setup for Python and FastAPI, Django or Flask, then have your agent fix and resolve it.
Building an MCP server? Track the errors your tools raise, in TypeScript or Python, so a failing tool shows up with its line instead of only in your users' client logs.
Related errors
- ModuleNotFoundError: No module named 'mcp.server.fastmcp'
- KeyError: 'email'
- McpError: MCP error -32000: Connection closed
More in MCP servers and clients
- McpError: MCP error -32001: Request timed outNode.js
- MCP error -32602: Input validation error: Invalid arguments for tool get_orderNode.js
- Error: spawn npx ENOENTNode.js
- Bad Request: No valid session ID providedNode.js
- Not Acceptable: Client must accept both application/json and text/event-streamNode.js
- Bad Request: Unsupported protocol version: 2026-07-28Node.js
References: MCP Python SDK v2 migration guide, MCP specification: tools (error handling), mcp on PyPI
Spotted a mistake? Email hello@greatwork.company. About Runheed.