Skip to content

Commit 0a221a0

Browse files
committed
fix: Raise resource not found error
1 parent 202af49 commit 0a221a0

File tree

4 files changed

+42
-7
lines changed

4 files changed

+42
-7
lines changed

src/mcp/server/fastmcp/exceptions.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
"""Custom exceptions for FastMCP."""
22

3+
from typing import Any
4+
5+
from mcp.types import INTERNAL_ERROR, ErrorData
6+
37

48
class FastMCPError(Exception):
59
"""Base error for FastMCP."""
@@ -10,7 +14,23 @@ class ValidationError(FastMCPError):
1014

1115

1216
class ResourceError(FastMCPError):
13-
"""Error in resource operations."""
17+
"""Error in resource operations.
18+
19+
Defaults to INTERNAL_ERROR (-32603), but can be set to RESOURCE_NOT_FOUND (-32002)
20+
for resource not found errors per MCP spec.
21+
"""
22+
23+
error: ErrorData
24+
25+
def __init__(self, message: str, code: int = INTERNAL_ERROR, data: Any | None = None):
26+
"""Initialize ResourceError with error code and message.
27+
28+
Args:
29+
message: Error message
30+
code: Error code (defaults to INTERNAL_ERROR -32603, use RESOURCE_NOT_FOUND -32002 for not found)
31+
"""
32+
super().__init__(message)
33+
self.error = ErrorData(code=code, message=message, data=data)
1434

1535

1636
class ToolError(FastMCPError):

src/mcp/server/fastmcp/resources/resource_manager.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@
77

88
from pydantic import AnyUrl
99

10+
from mcp.server.fastmcp.exceptions import ResourceError
1011
from mcp.server.fastmcp.resources.base import Resource
1112
from mcp.server.fastmcp.resources.templates import ResourceTemplate
1213
from mcp.server.fastmcp.utilities.logging import get_logger
13-
from mcp.types import Annotations, Icon
14+
from mcp.types import RESOURCE_NOT_FOUND, Annotations, Icon
1415

1516
if TYPE_CHECKING:
1617
from mcp.server.fastmcp.server import Context
@@ -98,9 +99,9 @@ async def get_resource(
9899
try:
99100
return await template.create_resource(uri_str, params, context=context)
100101
except Exception as e:
101-
raise ValueError(f"Error creating resource from template: {e}")
102+
raise ResourceError(f"Error creating resource from template: {e}")
102103

103-
raise ValueError(f"Unknown resource: {uri}")
104+
raise ResourceError(f"Unknown resource: {uri}", code=RESOURCE_NOT_FOUND)
104105

105106
def list_resources(self) -> list[Resource]:
106107
"""List all registered resources."""

src/mcp/server/fastmcp/server.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,17 @@
6161
from mcp.server.streamable_http_manager import StreamableHTTPSessionManager
6262
from mcp.server.transport_security import TransportSecuritySettings
6363
from mcp.shared.context import LifespanContextT, RequestContext, RequestT
64-
from mcp.types import Annotations, AnyFunction, ContentBlock, GetPromptResult, Icon, ToolAnnotations
64+
from mcp.shared.exceptions import McpError
65+
from mcp.types import (
66+
RESOURCE_NOT_FOUND,
67+
Annotations,
68+
AnyFunction,
69+
ContentBlock,
70+
ErrorData,
71+
GetPromptResult,
72+
Icon,
73+
ToolAnnotations,
74+
)
6575
from mcp.types import Prompt as MCPPrompt
6676
from mcp.types import PromptArgument as MCPPromptArgument
6777
from mcp.types import Resource as MCPResource
@@ -367,9 +377,12 @@ async def read_resource(self, uri: AnyUrl | str) -> Iterable[ReadResourceContent
367377
"""Read a resource by URI."""
368378

369379
context = self.get_context()
370-
resource = await self._resource_manager.get_resource(uri, context=context)
380+
try:
381+
resource = await self._resource_manager.get_resource(uri, context=context)
382+
except ResourceError as e:
383+
raise McpError(error=e.error)
371384
if not resource:
372-
raise ResourceError(f"Unknown resource: {uri}")
385+
raise McpError(error=ErrorData(code=RESOURCE_NOT_FOUND, message=f"Unknown resource: {uri}"))
373386

374387
try:
375388
content = await resource.read()

src/mcp/types.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ class JSONRPCResponse(BaseModel):
156156
METHOD_NOT_FOUND = -32601
157157
INVALID_PARAMS = -32602
158158
INTERNAL_ERROR = -32603
159+
RESOURCE_NOT_FOUND = -32002
159160

160161

161162
class ErrorData(BaseModel):

0 commit comments

Comments
 (0)