Feedback

Chat Icon

Practical MCP with FastMCP & LangChain

Engineering the Agentic Experience

Error Handling in FastMCP Servers
48%

So what does the LLM actually understand?

Only the text of the error message. If you raise ToolError("amount must be positive"), the LLM sees "amount must be positive". It doesn't know it was a ToolError and doesn't care about the exception type. For a developer, this means some important things:

  • Write error messages for the LLM (not necessarily for developers).

  • Use plain language that the LLM can understand and act on, rather than relying on exception types or structured data.

  • Don't rely on exception type to communicate meaning; the type is lost

  • Regular Python exceptions (caught internally and re-raised, or unhandled) work too, but their full message including the class name may leak internals, thus ToolError is recommended for controlled messages.

In practice, for server-side errors you control:

from fastmcp.exceptions import ToolError

@mcp.tool()
def divide(a: float, b: float) -> float:
    """Divide two numbers."""
    if b == 0:
        # LLM reads: "Cannot divide by zero. Please provide a non-zero divisor."
        raise ToolError("Cannot divide by zero. Please provide a non-zero divisor.")
    return a / b

For errors you don't control (third-party libraries, I/O failures), catch the exception and convert it to a ToolError with a clean message:

@mcp.tool()
async def fetch_data(url

Practical MCP with FastMCP & LangChain

Engineering the Agentic Experience

Enroll now to unlock current content and receive all future updates for free. Your purchase supports the author and fuels the creation of more exciting content. Act fast, as the price will rise as the course nears completion!