Skip to content

FastMCP read_resource() returns incorrect error code when resource not found #1579

@fennb

Description

@fennb

Initial Checks

Description

It appears to be unclear as to how an MCP server should respond to a read resource request if the resource is not found, however, FastMCP returns error code 0, which seems likely incorrect regardless.

In the Error Handling part of the protocol specification it states:

Resource not found: -32002

However, the python SDK's FastMCP attempts to raise a ResourceError, except it appears that code would never get executed because a ValueError is raised in ResourceManager first.

The net result of this is that servers implemented using FastMCP return the following for resource-not-found:

{"jsonrpc":"2.0","id":7,"error":{"code":0,"message":"Unknown resource: https://example.com/does-not-exist"}}

For the purposes of comparison, I compared this to the (presumably reference) typescript implementation, which raises an MCP error with InvalidParams: code -32602 - see here

-32602 is notably similar to -32002, but also seemingly incorrect (though in a different way ☹).

As things stand today, it is rather difficult to reliably write clients that behave predictably due to this. I understand this may be more of a protocol specification problem than a python-sdk problem, but error code 0 seems incorrect either way, so thought I'd report it.

Example Code

Basic server (anything will do):

from mcp.server.fastmcp import FastMCP

mcp = FastMCP('Pydantic AI MCP Server')
log_level = 'unset'


@mcp.resource('resource://user_name.txt', mime_type='text/plain')
async def user_name_resource() -> str:
    return 'Alice'


if __name__ == '__main__':
    mcp.run(transport='streamable-http')

Then try to fetch any resource via whatever MCP client you like, eg (manual curl):

MCP_URL="http://localhost:8000/mcp"
SESSION_ID=""

# Step 1: Initialize and get session ID
echo "1. Initializing MCP server..."
INIT_RESPONSE=$(curl -s -D - -X POST "$MCP_URL" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{
    "jsonrpc": "2.0",
    "method": "initialize",
    "params": {
      "protocolVersion": "2024-11-05",
      "capabilities": {},
      "clientInfo": {
        "name": "test-mcp-script",
        "version": "1.0.0"
      }
    },
    "id": 1
  }')

# Extract session ID from headers
SESSION_ID=$(echo "$INIT_RESPONSE" | grep -i 'mcp-session-id:' | cut -d' ' -f2 | tr -d '\r')

# Try to read resource:
curl -s -X POST "$MCP_URL" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "Mcp-Session-Id: $SESSION_ID" \
  -d '{
    "jsonrpc": "2.0",
    "method": "resources/read",
    "params": {
      "uri": "https://example.com/does-not-exist"
    },
    "id": 7
  }'

# > event: message
# > data: {"jsonrpc":"2.0","id":7,"error":{"code":0,"message":"Unknown resource: https://example.com/does-not-exist"}}

Python & MCP Python SDK

`main`

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3Nice to haves, rare edge casesbugSomething isn't workingready for workEnough information for someone to start working onspecSpecification compliance

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions