Repository navigation
Expand file tree
/
Copy pathexceptions.py
More file actions
90 lines (65 loc) · 3.85 KB
/
Copy pathexceptions.py
File metadata and controls
90 lines (65 loc) · 3.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
"""Custom exceptions for MCPServer."""
class MCPServerError(Exception):
"""Base error for MCPServer."""
class ResourceError(MCPServerError):
"""A resource failure you anticipated.
Raise this from a resource or resource template handler for a failure you saw
coming: the client receives a `-32603` protocol error carrying your message
(`ResourceNotFoundError` below is the `-32602` variant), and the server logs it
at INFO without a traceback. Any other exception (bar `MCPError`, which is a
protocol error) is treated as a crash: the client gets a generic message naming
only the URI, and the server logs the traceback at ERROR.
The SDK raises it too, and `UnexpectedResourceError` subclasses it, so
`except ResourceError` around `MCPServer.read_resource()` catches every read
failure, crash or not.
"""
class ResourceNotFoundError(ResourceError):
"""Resource does not exist.
Raise this from a resource handler to signal that the requested instance does not exist.
Clients receive `-32602` (invalid params) per
[SEP-2164](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2164).
"""
class UnexpectedResourceError(ResourceError):
"""A resource read failed with something other than `ResourceError` or `MCPError`.
The SDK raises this itself, around a crash in a resource or resource template
handler. You never raise it. `__cause__` is the original exception, which the
server logs with its traceback. The message names only the URI, so the
original text is withheld from the client.
"""
class ToolError(MCPServerError):
"""A tool failure you anticipated.
Raise this from a tool (or a resolver) for a failure you saw coming: the
call returns `is_error=True` with your message in `content` for the model to
read, and the server logs it at INFO without a traceback. A `ResourceError`
that escapes the tool (say from `ctx.read_resource()`) counts the same. Any
other exception bar `MCPError` (a protocol error) is treated as a crash: the
model sees only `Error executing tool <name>`, and the server logs the
traceback at ERROR. Inside a pydantic validator, raise `ValueError` as pydantic
expects; it arrives as an argument-validation failure, which is anticipated too.
The SDK raises it too, for an unknown tool name and for arguments that fail
the input schema, and `UnexpectedToolError` subclasses it, so `except ToolError`
around `MCPServer.call_tool()` catches every tool failure, crash or not.
For a missing name, the SDK raises `ToolNotFoundError`; the request boundary
translates that lookup miss to a JSON-RPC `INVALID_PARAMS` error.
"""
class ToolNotFoundError(ToolError):
"""The requested tool does not exist.
Direct calls remain catchable as `ToolError`. At the request boundary, a
missing requested tool becomes a JSON-RPC `INVALID_PARAMS` error.
"""
def __init__(self, name: str) -> None:
self.name = name
super().__init__(f"Unknown tool: {name}")
class UnexpectedToolError(ToolError):
"""A tool call failed with something other than `ToolError`, `ResourceError`, or `MCPError`.
The SDK raises this itself, around a crash in the tool (or a resolver) or a
return value that fails output conversion. You never raise it. The message is
only `Error executing tool <name>` (followed by the same for a nested tool or
resource that crashed), so nothing from the original reaches the client.
`__cause__` is the original exception (or, for a nested tool or resource
crash, its `Unexpected...Error` wrapper), which the server logs with its
traceback before returning the `is_error=True` result. Catch it around
`MCPServer.call_tool()` to tell a crash from a deliberate `ToolError`.
"""
class InvalidSignature(Exception):
"""Invalid signature for use with MCPServer."""