You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Address review: keep three anticipated failures out of the crash path, docs sweep
- pre_parse_json leaves a string alone when json.loads refuses it with
something other than JSONDecodeError (over-long integer, deep nesting),
so validation rejects it as a bad argument instead of it surfacing as a
crash with a traceback per request.
- convert_result skips output-schema validation for a returned
CallToolResult(is_error=True); an error result has no structured content
to check, and the author's message now reaches the client as written.
- read_resource checks that Resource.read() returned str or bytes, so a
mistyped custom resource is logged as a crash and answered with -32603
rather than "Invalid request parameters" with no log record.
- Docs and examples that still said "raise any exception and the model
reads it" now say ToolError; deprecated.md lists the deprecated
FuncMetadata helper; docstrings spell out the MCPError carve-out and the
nested-crash __cause__.
- Two tests tightened: the prompt argument-validation test proves the body
never ran, and the invalid-types check asserts on validate_arguments.
Copy file name to clipboardExpand all lines: docs/deprecated.md
+10-1Lines changed: 10 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,6 @@
1
1
# Deprecated features
2
2
3
-
The 2026-07-28 spec retires five things. The SDK still implements every one of them, and every one of them now carries a **deprecation warning**.
3
+
The 2026-07-28 spec retires five things. The SDK still implements every one of them, and every one of them now carries a **deprecation warning**. One SDK helper is deprecated on its own account and is listed [at the end](#deprecated-sdk-helpers).
4
4
5
5
The table below names each deprecated feature, why it is going away, and the replacement to build on.
6
6
@@ -129,13 +129,22 @@ That is the whole API. There is no per-method switch, and you don't want one: th
129
129
One line of pytest configuration, and a deprecated call can never sneak back into your
130
130
codebase without failing a test.
131
131
132
+
## Deprecated SDK helpers
133
+
134
+
These are not spec changes, only SDK internals with a better replacement. They warn with the same `MCPDeprecationWarning` and will be removed in 3.0.
135
+
136
+
| Deprecated | What you do instead |
137
+
|---|---|
138
+
|`FuncMetadata.call_fn_with_arg_validation()`|`FuncMetadata.validate_arguments()` and then `FuncMetadata.call_fn()`. Only code that drives `FuncMetadata` directly (a custom `Tool` subclass, say) ever called it. |
139
+
132
140
## Recap
133
141
134
142
* The 2026-07-28 spec deprecates **roots**, server-initiated **sampling**, and protocol **logging** (all [SEP-2577](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2577)), restricts **progress** to server-to-client, and removes **`ping`**.
135
143
* The replacement column points you onward: **[Multi-round-trip requests](handlers/multi-round-trip.md)** for sampling and roots, **[Logging](handlers/logging.md)** for logging, **[Progress](handlers/progress.md)** for progress. `ping` needs nothing at all.
136
144
* Deprecated is advisory: no wire changes, everything keeps working against pre-2026 sessions, and you get a visible `MCPDeprecationWarning` (a `UserWarning`, so it is on by default).
137
145
* Sampling and roots additionally need a back-channel that a 2026-07-28 session does not have. On a modern connection they warn and then they raise.
138
146
*`warnings.filterwarnings("ignore", category=MCPDeprecationWarning)` silences the whole category; `"error::mcp.MCPDeprecationWarning"` in pytest turns it into a test failure.
147
+
* One SDK helper, `FuncMetadata.call_fn_with_arg_validation()`, is deprecated separately for removal in 3.0.
139
148
* New code should not be built on any of these.
140
149
141
150
Every other page in these docs teaches the current API.
The fix is in your client: **check `result.is_error`**. A `try/except` around `call_tool` catches none of these, because there is nothing to catch. This is deliberate, and it is the single most useful thing on this page to internalise: the *model* chose the call, so the model gets the message and a chance to try again. **[Handling errors](servers/handling-errors.md)** is the whole story, including the `MCPError` path that *does* raise.
94
94
95
-
The bare form, `Error executing tool <name>` with no message, means the tool **crashed**: something other than `ToolError` was raised while running it (or its return value failed the output schema), and that exception's text is kept off the wire. The traceback is in the **server's log** at `ERROR`, as `Tool '<name>' raised an unexpected exception`.
95
+
The bare form, `Error executing tool <name>` with no message, means the tool **crashed**: an exception it didn't anticipate escaped it (or its return value failed the output schema), and that exception's text is kept off the wire. The traceback is in the **server's log** at `ERROR`, as `Tool '<name>' raised an unexpected exception`.
96
96
97
97
## `TypeError: The @tool decorator was used incorrectly. Did you forget to call it? Use @tool() instead of @tool`
0 commit comments