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
Make mcp.types a permanent alias, not a deprecation shim
A deprecation is a permanent commitment (a v3 removal) spent on a
transient goal (nudging the v1->v2 migration wave), and the second
break would cost every remaining user again for no functional gain:
the module is a star re-export that cannot drift. `import mcp.types as
types` is also baked into years of tutorials and generated code, and
is a genuinely clean types-only namespace for SDK users, while
`mcp_types` remains the spelling that installs without the SDK stack.
So drop the MCPDeprecationWarning and every "removed in v3" phrase.
Removed names now raise AttributeError from `__getattr__` as PEP 562
requires, keeping hasattr() and getattr(name, default) on their
fallback paths; the tradeoff is that `from mcp.types import <removed>`
falls back to CPython's generic ImportError, which is still fail-fast.
Fix two doc claims that still said mcp.types no longer exists.
Copy file name to clipboardExpand all lines: docs/migration.md
+18-15Lines changed: 18 additions & 15 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -14,7 +14,7 @@ Every section heading below names the API it affects, so searching this page for
14
14
|---|---|---|
15
15
|`FastMCP` renamed to `MCPServer`|`ModuleNotFoundError: No module named 'mcp.server.fastmcp'`|[`FastMCP` renamed](#fastmcp-renamed-to-mcpserver)|
16
16
| Fields renamed from camelCase to snake_case |`AttributeError: 'Tool' object has no attribute 'inputSchema'`|[snake_case fields](#field-names-changed-from-camelcase-to-snake_case)|
17
-
|`mcp.types`moved to the `mcp-types` package |`MCPDeprecationWarning: mcp.types is deprecated; import from mcp_types.`|[`mcp.types` moved](#mcptypes-moved-to-the-mcp-types-package)|
17
+
|`mcp.types`names removed |`AttributeError: mcp.types.Content was removed in v2; use ContentBlock.`|[Removed types](#removed-type-aliases-and-classes)|
18
18
|`McpError` renamed to `MCPError`|`ImportError: cannot import name 'McpError' from 'mcp'`|[`McpError` renamed](#mcperror-renamed-to-mcperror)|
19
19
| Resource URIs are `str`, not `AnyUrl`|`AttributeError: 'str' object has no attribute 'host'`|[URI type](#resource-uri-type-changed-from-anyurl-to-str)|
20
20
|`streamablehttp_client` removed |`ImportError: cannot import name 'streamablehttp_client'`|[`streamablehttp_client`](#streamablehttp_client-removed)|
@@ -170,18 +170,19 @@ nothing on PyPI to pin to, keep the unpinned form.
170
170
171
171
The protocol wire types now live in a standalone distribution, `mcp-types`, imported as
172
172
`mcp_types`. Its only runtime dependencies are `pydantic` and `typing-extensions`, so code
173
-
that just needs to (de)serialize MCP traffic can install it without the full SDK. The `mcp` package depends on `mcp-types` and
174
-
continues to re-export the type names at the top level, so`from mcp import Tool` is
175
-
unchanged. `mcp.shared.version` was removed. The package's API reference is at
173
+
that just needs to (de)serialize MCP traffic can install it without the full SDK. The `mcp`
174
+
package depends on `mcp-types` and continues to re-export the type names at the top level, so
175
+
`from mcp import Tool` is unchanged. The package's API reference is at
176
176
[`mcp_types`](api/mcp_types/index.md).
177
177
178
-
`import mcp.types` still works in v2, as a compatibility shim that mirrors `mcp_types` and
179
-
emits an `MCPDeprecationWarning` on first import; it will be removed in v3, so switch to
180
-
`mcp_types` now. The shim only restores the import: the field renames below still apply, so
181
-
code that imports through it can go on to fail on camelCase attribute access. The 23 names
182
-
that no longer exist (listed under
183
-
[Removed type aliases and classes](#removed-type-aliases-and-classes)) raise an
184
-
`ImportError` from the shim that names their replacement.
178
+
`import mcp.types` and `from mcp.types import ...` keep working: `mcp.types` is a permanent
179
+
alias that mirrors `mcp_types` exactly (every name is the same object), so v1's most common
180
+
import line needs no change if you already depend on `mcp`. Only `mcp.shared.version` was
181
+
removed; import from `mcp_types.version` instead. Reading a name that no longer exists (listed
182
+
under [Removed type aliases and classes](#removed-type-aliases-and-classes)) as
183
+
`mcp.types.Content` raises an `AttributeError` that names its replacement; a
184
+
`from mcp.types import Content` of one raises a plain `ImportError` (Python discards the hint on
185
+
that path, but it still fails fast).
185
186
186
187
**Why:** keeping the wire types in their own package lets tooling and lightweight clients
187
188
depend on the protocol schema without pulling in `httpx2`, `starlette`, `uvicorn`, and the
@@ -197,11 +198,13 @@ from mcp.shared.version import LATEST_PROTOCOL_VERSION
197
198
**After (v2):**
198
199
199
200
```python
201
+
# Unchanged if you depend on the SDK:
202
+
from mcp.types import Tool, Resource
203
+
from mcp import Tool, Resource
204
+
205
+
# Or the standalone package, which installs without the SDK's transport stack:
200
206
from mcp_types import Tool, Resource
201
207
from mcp_types.version importLATEST_PROTOCOL_VERSION
202
-
203
-
# Names `mcp` already re-exported at the top level are unchanged:
204
-
from mcp import Tool, Resource
205
208
```
206
209
207
210
### Removed type aliases and classes
@@ -1711,7 +1714,7 @@ except MCPError as e:
1711
1714
raise
1712
1715
```
1713
1716
1714
-
`e.error.code` also still works; `e.code` is the v2 convenience property. `mcp.types` no longer exists, so the constant comes from `mcp_types`. The example uses the high-level `Client`; `ClientSession.call_tool()` raises the same `MCPError`.
1717
+
`e.error.code` also still works; `e.code` is the v2 convenience property. The constant is importable from `mcp_types` or, equivalently, `mcp.types`. The example uses the high-level `Client`; `ClientSession.call_tool()` raises the same `MCPError`.
1715
1718
1716
1719
### `ClientSession` now runs on `JSONRPCDispatcher`; `BaseSession` removed
Copy file name to clipboardExpand all lines: docs/whats-new.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -117,7 +117,7 @@ Underneath, the v1 `BaseSession` receive loop was replaced by a dispatcher engin
117
117
118
118
### The wire types moved to `mcp-types`, and every field is snake_case
119
119
120
-
The protocol types now live in their own distribution, `mcp-types`, imported as `mcp_types`. It depends on nothing but pydantic and typing-extensions, so a gateway, a proxy, or a code generator can consume MCP's wire shapes without installing an HTTP stack. `mcp` depends on it at an exact version and re-exports the common names, so`from mcp import Tool`still works; `import mcp.types`does not.
120
+
The protocol types now live in their own distribution, `mcp-types`, imported as `mcp_types`. It depends on nothing but pydantic and typing-extensions, so a gateway, a proxy, or a code generator can consume MCP's wire shapes without installing an HTTP stack. `mcp` depends on it at an exact version, and both v1 spellings keep working:`from mcp import Tool`for the common names, and `import mcp.types`as a permanent alias that mirrors `mcp_types` exactly.
121
121
122
122
On those types, every Python attribute is now snake_case: `result.is_error`, `tool.input_schema`, `listing.next_cursor`. The JSON on the wire is camelCase, exactly as before; only the attribute spelling changed. Two stricter defaults ride along: unknown fields are ignored instead of round-tripped (put extras in `_meta`), and both sides validate traffic against the protocol version they negotiated. See the **[Migration Guide](migration.md#field-names-changed-from-camelcase-to-snake_case)** for the rename table.
123
123
@@ -146,7 +146,7 @@ Each of these is a section in the **[Migration Guide](migration.md)**:
146
146
147
147
* The **WebSocket transport**, both sides, and the `mcp[ws]` extra. It was never part of the MCP specification.
148
148
* The **experimental Tasks** API (`mcp.*.experimental`). 2026-07-28 moves tasks out of the core protocol and into an official extension ([SEP-2663](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2663)), which this SDK does not implement yet.
149
-
*`mcp.types`, `mcp.shared.version`, `mcp.shared.progress`, and `mcp.shared.session` (with the `RequestResponder` stub v1 `message_handler` annotations imported) as import paths.
149
+
*`mcp.shared.version`, `mcp.shared.progress`, and `mcp.shared.session` (with the `RequestResponder` stub v1 `message_handler` annotations imported) as import paths. (`mcp.types` is *not* removed: it remains as a permanent alias for the standalone `mcp_types` package.)
150
150
* The deprecated `streamablehttp_client` spelling, and the `get_session_id` callback from `streamable_http_client` (which now yields exactly two streams).
151
151
*`McpError`, renamed **`MCPError`** with a direct `(code, message, data)` constructor.
152
152
*`MCPServer.get_context()`, `mount_path=`, and the lowlevel `Server`'s decorator methods, ContextVar, and handler dicts.
0 commit comments