From b7c9a916d672d543917fcbd11e0dc9df2efa99c7 Mon Sep 17 00:00:00 2001 From: Max <224885523+maxisbey@users.noreply.github.com> Date: Mon, 27 Jul 2026 23:47:04 +0100 Subject: [PATCH] Add mcp.types as a permanent alias for mcp_types (#3190) --- docs/advanced/extensions.md | 10 +- docs/advanced/low-level-server.md | 10 +- docs/advanced/middleware.md | 2 +- docs/advanced/pagination.md | 4 +- docs/client/caching.md | 4 +- docs/client/callbacks.md | 4 +- docs/client/index.md | 6 +- docs/client/session-groups.md | 2 +- docs/client/subscriptions.md | 2 +- docs/get-started/installation.md | 4 +- docs/get-started/testing.md | 2 +- docs/handlers/dependencies.md | 2 +- docs/handlers/elicitation.md | 2 +- docs/handlers/multi-round-trip.md | 8 +- docs/handlers/sampling-and-roots.md | 4 +- docs/handlers/subscriptions.md | 4 +- docs/migration.md | 115 +++++++++++------- docs/run/deploy.md | 4 +- docs/servers/completions.md | 4 +- docs/servers/handling-errors.md | 6 +- docs/servers/media.md | 4 +- docs/servers/tools.md | 2 +- docs/servers/uri-templates.md | 4 +- docs/troubleshooting.md | 2 +- docs/whats-new.md | 4 +- docs_src/caching/tutorial002.py | 3 +- docs_src/caching/tutorial003.py | 3 +- docs_src/client/tutorial003.py | 2 +- docs_src/client/tutorial004.py | 3 +- docs_src/client/tutorial006.py | 3 +- docs_src/client/tutorial007.py | 3 +- docs_src/client_callbacks/tutorial002.py | 3 +- docs_src/client_callbacks/tutorial003.py | 2 +- docs_src/client_callbacks/tutorial004.py | 2 +- docs_src/completions/tutorial002.py | 3 +- docs_src/completions/tutorial003.py | 3 +- docs_src/dependencies/tutorial004.py | 3 +- docs_src/deploy/tutorial002.py | 3 +- docs_src/deploy/tutorial003.py | 3 +- docs_src/elicitation/tutorial003.py | 3 +- docs_src/extensions/tutorial004.py | 2 +- docs_src/extensions/tutorial005.py | 3 +- docs_src/extensions/tutorial006.py | 3 +- docs_src/extensions/tutorial007.py | 3 +- docs_src/handling_errors/tutorial002.py | 3 +- docs_src/legacy_clients/tutorial001.py | 2 +- docs_src/lowlevel/tutorial001.py | 5 +- docs_src/lowlevel/tutorial002.py | 5 +- docs_src/lowlevel/tutorial003.py | 5 +- docs_src/lowlevel/tutorial004.py | 5 +- docs_src/lowlevel/tutorial005.py | 5 +- docs_src/lowlevel/tutorial006.py | 8 +- docs_src/media/tutorial004.py | 3 +- docs_src/middleware/tutorial001.py | 7 +- docs_src/mrtr/tutorial001.py | 5 +- docs_src/mrtr/tutorial002.py | 3 +- docs_src/mrtr/tutorial003.py | 3 +- docs_src/mrtr/tutorial004.py | 3 +- docs_src/pagination/tutorial001.py | 3 +- docs_src/pagination/tutorial002.py | 3 +- docs_src/sampling_and_roots/tutorial001.py | 3 +- docs_src/sampling_and_roots/tutorial002.py | 3 +- docs_src/session_groups/tutorial004.py | 3 +- docs_src/subscriptions/tutorial002.py | 3 +- docs_src/subscriptions/tutorial003.py | 3 +- docs_src/tools/tutorial005.py | 3 +- docs_src/uri_templates/tutorial004.py | 5 +- docs_src/uri_templates/tutorial005.py | 9 +- docs_src/whats_new/tutorial001.py | 7 +- .../direct_call_tool_result_return.py | 2 +- .../mcp_everything_server/server.py | 4 +- .../mcp_simple_pagination/server.py | 2 +- .../simple-prompt/mcp_simple_prompt/server.py | 2 +- .../mcp_simple_resource/server.py | 2 +- .../server.py | 2 +- .../mcp_simple_streamablehttp/event_store.py | 2 +- .../mcp_simple_streamablehttp/server.py | 2 +- .../simple-tool/mcp_simple_tool/server.py | 2 +- .../mcp_sse_polling_demo/event_store.py | 2 +- .../mcp_sse_polling_demo/server.py | 2 +- .../__main__.py | 3 +- .../snippets/clients/completion_client.py | 3 +- .../snippets/clients/pagination_client.py | 3 +- .../snippets/clients/parsing_tool_results.py | 3 +- examples/snippets/clients/stdio_client.py | 3 +- .../clients/url_elicitation_client.py | 5 +- examples/snippets/servers/completion.py | 5 +- .../servers/direct_call_tool_result.py | 2 +- examples/snippets/servers/elicitation.py | 2 +- examples/snippets/servers/lowlevel/basic.py | 3 +- .../lowlevel/direct_call_tool_result.py | 3 +- .../snippets/servers/lowlevel/lifespan.py | 3 +- .../servers/lowlevel/structured_output.py | 3 +- .../snippets/servers/pagination_example.py | 3 +- examples/snippets/servers/sampling.py | 3 +- examples/stories/_harness.py | 2 +- examples/stories/apps/client.py | 3 +- .../stories/bearer_auth/server_lowlevel.py | 2 +- examples/stories/custom_methods/client.py | 3 +- examples/stories/custom_methods/server.py | 3 +- examples/stories/dual_era/client.py | 5 +- examples/stories/dual_era/server.py | 3 +- examples/stories/dual_era/server_lowlevel.py | 5 +- examples/stories/error_handling/client.py | 3 +- examples/stories/error_handling/server.py | 3 +- .../stories/error_handling/server_lowlevel.py | 3 +- examples/stories/extensions/client.py | 5 +- examples/stories/extensions/server.py | 2 +- .../identity_assertion/server_lowlevel.py | 2 +- examples/stories/json_response/client.py | 6 +- .../stories/json_response/server_lowlevel.py | 2 +- examples/stories/legacy_elicitation/client.py | 3 +- .../legacy_elicitation/server_lowlevel.py | 3 +- examples/stories/legacy_routing/client.py | 7 +- examples/stories/legacy_routing/server.py | 4 +- .../stories/legacy_routing/server_lowlevel.py | 4 +- examples/stories/lifespan/client.py | 3 +- examples/stories/lifespan/server_lowlevel.py | 3 +- examples/stories/middleware/server.py | 3 +- examples/stories/mrtr/client.py | 3 +- examples/stories/mrtr/server.py | 3 +- examples/stories/mrtr/server_lowlevel.py | 3 +- examples/stories/oauth/server_lowlevel.py | 2 +- .../server_lowlevel.py | 2 +- .../stories/pagination/server_lowlevel.py | 3 +- examples/stories/parallel_calls/client.py | 2 +- .../stories/parallel_calls/server_lowlevel.py | 2 +- examples/stories/prompts/client.py | 3 +- examples/stories/prompts/server.py | 3 +- examples/stories/prompts/server_lowlevel.py | 3 +- examples/stories/reconnect/client.py | 5 +- examples/stories/reconnect/server_lowlevel.py | 3 +- examples/stories/refund_desk/client.py | 3 +- examples/stories/resources/client.py | 3 +- examples/stories/resources/server_lowlevel.py | 5 +- examples/stories/roots/client.py | 2 +- examples/stories/roots/server_lowlevel.py | 3 +- examples/stories/sampling/client.py | 3 +- examples/stories/sampling/server.py | 3 +- examples/stories/sampling/server_lowlevel.py | 3 +- examples/stories/schema_validators/client.py | 3 +- .../schema_validators/server_lowlevel.py | 3 +- examples/stories/serve_one/client.py | 5 +- examples/stories/serve_one/server.py | 4 +- examples/stories/sse_polling/client.py | 2 +- examples/stories/sse_polling/event_store.py | 3 +- .../stories/sse_polling/server_lowlevel.py | 2 +- examples/stories/standalone_get/client.py | 2 +- .../stories/standalone_get/server_lowlevel.py | 3 +- examples/stories/starlette_mount/client.py | 3 +- examples/stories/stateless_legacy/client.py | 5 +- .../stateless_legacy/server_lowlevel.py | 2 +- examples/stories/stickynotes/client.py | 4 +- .../stories/stickynotes/server_lowlevel.py | 3 +- examples/stories/streaming/client.py | 2 +- examples/stories/streaming/server.py | 2 +- examples/stories/streaming/server_lowlevel.py | 2 +- examples/stories/subscriptions/client.py | 2 +- .../stories/subscriptions/server_lowlevel.py | 3 +- examples/stories/tools/client.py | 3 +- examples/stories/tools/server.py | 2 +- examples/stories/tools/server_lowlevel.py | 3 +- pyproject.toml | 2 + scripts/docs/gen_ref_pages.py | 8 ++ src/mcp-types/mcp_types/jsonrpc.py | 23 ++++ src/mcp-types/mcp_types/version.py | 12 ++ src/mcp/__init__.py | 3 + src/mcp/types/__init__.py | 31 +++++ src/mcp/types/jsonrpc.py | 13 ++ src/mcp/types/methods.py | 13 ++ src/mcp/types/version.py | 13 ++ tests/test_types.py | 58 +++++++++ 172 files changed, 466 insertions(+), 363 deletions(-) create mode 100644 src/mcp/types/__init__.py create mode 100644 src/mcp/types/jsonrpc.py create mode 100644 src/mcp/types/methods.py create mode 100644 src/mcp/types/version.py diff --git a/docs/advanced/extensions.md b/docs/advanced/extensions.md index 715c5bbd..de7937fc 100644 --- a/docs/advanced/extensions.md +++ b/docs/advanced/extensions.md @@ -128,7 +128,7 @@ The same file's `main()` is the whole client story, both halves of it: The one interceptive hook. Override `intercept_tool_call` to observe, short-circuit, or veto a tool call: -```python title="server.py" hl_lines="18-25" +```python title="server.py" hl_lines="17-24" --8<-- "docs_src/extensions/tutorial005.py" ``` @@ -158,7 +158,7 @@ A **client extension** is the same contract from the consuming side: a bundle of client-side behaviour behind one identifier. Pass instances to `Client(extensions=[...])` and call tools normally: -```python title="client.py" hl_lines="67-69" +```python title="client.py" hl_lines="66-68" --8<-- "docs_src/extensions/tutorial006.py" ``` @@ -188,7 +188,7 @@ client = Client(mcp, extensions=[advertise("com.example/search")]) Subclass `ClientExtension` and override only what you need. Three contribution kinds, each with a default: `settings()`, `claims()`, and `notifications()`. -```python title="client.py" hl_lines="18-19 44-45 47-48" +```python title="client.py" hl_lines="17-18 43-44 46-47" --8<-- "docs_src/extensions/tutorial006.py" ``` @@ -226,12 +226,12 @@ claimed shape reaching a session-tier caller raises `UnexpectedClaimedResult`. ### Extension verbs An extension's own request methods need no client-side registration. A vendor request -type subclasses `mcp_types.Request` and goes through `client.session.send_request`, +type subclasses `mcp.types.Request` and goes through `client.session.send_request`, as in [Serving your own methods](#serving-your-own-methods). One addition: when a params key must ride the `Mcp-Name` header (extension specs such as tasks require this for their verbs), the request type declares `name_param`: -```python title="client.py" hl_lines="23-26 47-48" +```python title="client.py" hl_lines="22-25 46-47" --8<-- "docs_src/extensions/tutorial007.py" ``` diff --git a/docs/advanced/low-level-server.md b/docs/advanced/low-level-server.md index dd5fb427..083e03cd 100644 --- a/docs/advanced/low-level-server.md +++ b/docs/advanced/low-level-server.md @@ -14,7 +14,7 @@ For everything else, stay on `MCPServer`. This is the `search_books` tool that **[Tools](../servers/tools.md)** writes in nine lines of `@mcp.tool()`, with the sugar removed: -```python title="server.py" hl_lines="23 27 33" +```python title="server.py" hl_lines="22 26 32" --8<-- "docs_src/lowlevel/tutorial001.py" ``` @@ -80,7 +80,7 @@ That generalises. An exception raised from a low-level handler is **always** a p `on_call_tool` is the single entry point for every tool on the server. You route on `params.name`: -```python title="server.py" hl_lines="39-44" +```python title="server.py" hl_lines="38-43" --8<-- "docs_src/lowlevel/tutorial002.py" ``` @@ -91,7 +91,7 @@ That generalises. An exception raised from a low-level handler is **always** a p Declare `output_schema` on the `Tool` and put `structured_content` on the result. Both are yours: -```python title="server.py" hl_lines="20-24 37" +```python title="server.py" hl_lines="19-23 36" --8<-- "docs_src/lowlevel/tutorial003.py" ``` @@ -117,7 +117,7 @@ The server never compares the two fields. This SDK's `Client` does: return `stru Use it for record IDs, trace IDs, anything your UI needs and your prompt doesn't: -```python title="server.py" hl_lines="38" +```python title="server.py" hl_lines="37" --8<-- "docs_src/lowlevel/tutorial004.py" ``` @@ -144,7 +144,7 @@ No `resources`, no `prompts`: there is nothing to back them. Pass `on_list_promp `Server` is generic in the type its lifespan yields. Annotate it once and the object is typed everywhere it surfaces: -```python title="server.py" hl_lines="25-27 45-46 51" +```python title="server.py" hl_lines="24-26 44-45 50" --8<-- "docs_src/lowlevel/tutorial005.py" ``` diff --git a/docs/advanced/middleware.md b/docs/advanced/middleware.md index 3d580855..3a5fa142 100644 --- a/docs/advanced/middleware.md +++ b/docs/advanced/middleware.md @@ -16,7 +16,7 @@ If `Server(name, on_call_tool=...)` is new to you, read **[The low-level Server] One server, one tool, one middleware that logs how long each message took: -```python title="server.py" hl_lines="40-46 50" +```python title="server.py" hl_lines="39-45 49" --8<-- "docs_src/middleware/tutorial001.py" ``` diff --git a/docs/advanced/pagination.md b/docs/advanced/pagination.md index 381f7fae..9f807a8e 100644 --- a/docs/advanced/pagination.md +++ b/docs/advanced/pagination.md @@ -10,7 +10,7 @@ Pagination is for the server whose resource list is really a database: thousands ## A server that pages -```python title="server.py" hl_lines="13 16-17" +```python title="server.py" hl_lines="12 15-16" --8<-- "docs_src/pagination/tutorial001.py" ``` @@ -38,7 +38,7 @@ The tenth page comes back with `next_cursor` set to `None`. Done. Every `list_*` method on `Client` (`list_tools`, `list_resources`, `list_resource_templates`, `list_prompts`) takes a `cursor=` keyword. Draining a paged list is one `while True`: -```python title="client.py" hl_lines="27-33" +```python title="client.py" hl_lines="26-32" --8<-- "docs_src/pagination/tutorial002.py" ``` diff --git a/docs/client/caching.md b/docs/client/caching.md index 78de2a59..5d83cfa9 100644 --- a/docs/client/caching.md +++ b/docs/client/caching.md @@ -25,7 +25,7 @@ Out of the box every result says `ttlMs: 0, cacheScope: "private"`: immediately On the low-level `Server`, handlers build their results by hand, and `ttl_ms` / `cache_scope` are just fields on the result models. A handler that sets them explicitly always wins over the constructor map, field by field: -```python title="server.py" hl_lines="11 17" +```python title="server.py" hl_lines="10 16" --8<-- "docs_src/caching/tutorial002.py" ``` @@ -39,7 +39,7 @@ One caveat on paginated lists: the protocol requires the **same `cacheScope` on On a 2026-07-28 session, `Client` honors the hints for you: it has a built-in response cache, on by default. A result that arrives carrying a `ttlMs` is stored, and an identical call within that TTL is served from the cache with no round trip. A result that carries *no* hint is not cached: hint-less results get `CacheConfig.default_ttl_ms`, which defaults to `0` (immediately stale), so a server that declares nothing sees exactly the call-for-call traffic it always did. -```python title="client.py" hl_lines="34 36 39" +```python title="client.py" hl_lines="33 35 38" --8<-- "docs_src/caching/tutorial003.py" ``` diff --git a/docs/client/callbacks.md b/docs/client/callbacks.md index 53f6e563..1ac633be 100644 --- a/docs/client/callbacks.md +++ b/docs/client/callbacks.md @@ -19,7 +19,7 @@ That is the server half, and the **[Elicitation](../handlers/elicitation.md)** p ## The elicitation callback -```python title="client.py" hl_lines="7-11 17-18" +```python title="client.py" hl_lines="6-10 16-17" --8<-- "docs_src/client_callbacks/tutorial002.py" ``` @@ -55,7 +55,7 @@ result.content # [TextContent(type='text', text='Card issued to Ada Lovelace.') One `tools/call` from you, one `elicitation/create` back from the server, answered by your function, all inside a single tool call. !!! info - `mode="legacy"` on line 17 is doing real work. By default `Client(...)` negotiates the modern + `mode="legacy"` on the `Client(...)` call is doing real work. By default `Client(...)` negotiates the modern protocol path, and that path has no back-channel for server-to-client requests: `ctx.elicit` fails before your callback ever runs. The transport doesn't decide that; the negotiated protocol does, in-memory and over a URL alike. Pin `mode="legacy"` whenever your client has diff --git a/docs/client/index.md b/docs/client/index.md index f70966e1..1e1df3c0 100644 --- a/docs/client/index.md +++ b/docs/client/index.md @@ -135,7 +135,7 @@ A tool that raises does **not** raise in your client. It comes back as an ordina The resource verbs come in pairs: two ways to list, one way to read. -```python title="client.py" hl_lines="23-32" +```python title="client.py" hl_lines="22-31" --8<-- "docs_src/client/tutorial004.py" ``` @@ -174,7 +174,7 @@ A host hands those messages straight to the model. That is the whole feature. A server with a completion handler can autocomplete prompt and resource-template arguments as the user types. -```python title="client.py" hl_lines="28-32" +```python title="client.py" hl_lines="27-31" --8<-- "docs_src/client/tutorial006.py" ``` @@ -187,7 +187,7 @@ The answer is in `result.completion.values`. Type `"p"` and the server comes bac Every `list_*` method takes a `cursor=` keyword and every result carries a `next_cursor`. When `next_cursor` is `None`, you have everything. -```python title="client.py" hl_lines="23-31" +```python title="client.py" hl_lines="22-30" --8<-- "docs_src/client/tutorial007.py" ``` diff --git a/docs/client/session-groups.md b/docs/client/session-groups.md index 70ad8683..70ac02e8 100644 --- a/docs/client/session-groups.md +++ b/docs/client/session-groups.md @@ -42,7 +42,7 @@ Create a `ClientSessionGroup` and call **`connect_to_server`** once per server: You fix this at the group, not at the servers. Pass a function of `(name, server_info)` and the group runs it on every name it registers: -```python title="client.py" hl_lines="8-9 16" +```python title="client.py" hl_lines="7-8 15" --8<-- "docs_src/session_groups/tutorial004.py" ``` diff --git a/docs/client/subscriptions.md b/docs/client/subscriptions.md index fc7d0130..fa72634c 100644 --- a/docs/client/subscriptions.md +++ b/docs/client/subscriptions.md @@ -8,7 +8,7 @@ This page is the client end: opening the stream, watching it beside your main fl A subscription is one context manager. Entering it sends the request, with your keyword arguments as the subscription filter, and waits for the server's acknowledgment, so the stream is live by the time the block starts. -```python title="client.py" hl_lines="16 19 29" +```python title="client.py" hl_lines="15 18 28" --8<-- "docs_src/subscriptions/tutorial003.py" ``` diff --git a/docs/get-started/installation.md b/docs/get-started/installation.md index a0c6100f..46e0f9b9 100644 --- a/docs/get-started/installation.md +++ b/docs/get-started/installation.md @@ -31,9 +31,9 @@ These docs describe **v2**, currently a release candidate, so the version pin is You don't need to know any of this to use the SDK, but if you're wondering what each dependency is for: -* `mcp-types`: every protocol type (requests, results, content blocks) as its own package, versioned in lockstep with the SDK. Every `from mcp_types import ...` in these docs is this package. +* `mcp-types`: every protocol type (requests, results, content blocks) as its own package, versioned in lockstep with the SDK. Code that depends on `mcp` imports it through the `mcp.types` alias (every `from mcp.types import ...` in these docs); import `mcp_types` directly only in a project that installs `mcp-types` without the SDK. * [`anyio`](https://anyio.readthedocs.io/): the async runtime. The whole SDK is written against anyio, so it runs on either `asyncio` or `trio`. -* [`pydantic`](https://docs.pydantic.dev/): what every `mcp_types` model is built on, plus all schema generation and validation. +* [`pydantic`](https://docs.pydantic.dev/): what every `mcp.types` model is built on, plus all schema generation and validation. * [`httpx2`](https://pypi.org/project/httpx2/): the HTTP client behind the Streamable HTTP and SSE *client* transports, with server-sent events support built in. * [`starlette`](https://www.starlette.io/), [`uvicorn`](https://www.uvicorn.org/), [`sse-starlette`](https://pypi.org/project/sse-starlette/), and [`python-multipart`](https://pypi.org/project/python-multipart/): the HTTP *server* transports. * [`jsonschema`](https://pypi.org/project/jsonschema/): validates a tool's structured output against its declared output schema. diff --git a/docs/get-started/testing.md b/docs/get-started/testing.md index 2c3f9fca..9abd281c 100644 --- a/docs/get-started/testing.md +++ b/docs/get-started/testing.md @@ -40,7 +40,7 @@ Now the test: import pytest from inline_snapshot import snapshot from mcp import Client -from mcp_types import CallToolResult, TextContent +from mcp.types import CallToolResult, TextContent from server import mcp diff --git a/docs/handlers/dependencies.md b/docs/handlers/dependencies.md index 509b2635..b347e1b7 100644 --- a/docs/handlers/dependencies.md +++ b/docs/handlers/dependencies.md @@ -138,7 +138,7 @@ That's the right default for a precondition: no answer, no order. When declining Elicitation is one of the three questions a resolver can ask, and the multi-round-trip flow allows no others. The other two go to the **client** rather than the user: return `Sample(...)` to run an LLM call through the client (a `sampling/createMessage` request), or `ListRoots()` to fetch the client's current roots. Neither has an accept/decline outcome; the consumer annotates the result type directly, `CreateMessageResult` (`CreateMessageResultWithTools` when the request carries `tools` or `tool_choice`) or `ListRootsResult`: -```python title="server.py" hl_lines="11-16 22" +```python title="server.py" hl_lines="10-15 21" --8<-- "docs_src/dependencies/tutorial004.py" ``` diff --git a/docs/handlers/elicitation.md b/docs/handlers/elicitation.md index 3f3f5a6c..c9a0a4fa 100644 --- a/docs/handlers/elicitation.md +++ b/docs/handlers/elicitation.md @@ -128,7 +128,7 @@ Look at the second tool. When your server learns the out-of-band flow finished ( Servers ask. Clients answer by passing an **`elicitation_callback`** to `Client(...)`: -```python title="client.py" hl_lines="7-8 19" +```python title="client.py" hl_lines="6-7 18" --8<-- "docs_src/elicitation/tutorial003.py" ``` diff --git a/docs/handlers/multi-round-trip.md b/docs/handlers/multi-round-trip.md index e0890344..1d5b9f52 100644 --- a/docs/handlers/multi-round-trip.md +++ b/docs/handlers/multi-round-trip.md @@ -21,7 +21,7 @@ That's the whole protocol. Every leg is an ordinary request from the client to t On `@mcp.tool()` you rarely build this by hand: declare a dependency that asks the user (`Elicit`), samples the client's LLM (`Sample`), or lists its roots (`ListRoots`) and the SDK returns the `InputRequiredResult` for you; that form is the **[Dependencies](dependencies.md)** page. The two forms don't mix: a call has one `input_responses`/`request_state` channel, so a tool that uses `Resolve(...)` parameters cannot also return `InputRequiredResult` from its body. A declared `InputRequiredResult` return is rejected at registration (`InvalidSignature`), and an undeclared one fails the call at runtime. The manual form is the **low-level** `Server`, whose `on_call_tool` handler is allowed to return either result type: -```python title="server.py" hl_lines="44-47" +```python title="server.py" hl_lines="43-46" --8<-- "docs_src/mrtr/tutorial001.py" ``` @@ -35,7 +35,7 @@ Everything else in that file (the explicit `input_schema`, the hand-built `CallT `tools/call` is not special: at 2026-07-28 a server may answer `prompts/get` and `resources/read` the same way. On `MCPServer`, an `@mcp.prompt()` function — or an `@mcp.resource()` **template** function — returns the `InputRequiredResult` itself and reads the retry's answers off the context: -```python title="server.py" hl_lines="21 23 25" +```python title="server.py" hl_lines="20 22 24" --8<-- "docs_src/mrtr/tutorial004.py" ``` @@ -51,7 +51,7 @@ Everything else in that file (the explicit `input_schema`, the hand-built `CallT Register the callbacks the server might ask for (`elicitation_callback`, `sampling_callback`, `list_roots_callback`) and call the tool. When an `InputRequiredResult` arrives, `Client` dispatches each entry in `input_requests` to the matching callback, retries with the answers and the echoed `request_state`, and keeps going until a `CallToolResult` comes back: -```python title="client.py" hl_lines="12 13" +```python title="client.py" hl_lines="11 12" --8<-- "docs_src/mrtr/tutorial003.py" ``` @@ -76,7 +76,7 @@ The auto-loop is enough for a single-process client. Own the loop instead when: Drop to the underlying session, where `allow_input_required=True` hands you the union directly: -```python title="client.py" hl_lines="13 14 20" +```python title="client.py" hl_lines="12 13 19" --8<-- "docs_src/mrtr/tutorial002.py" ``` diff --git a/docs/handlers/sampling-and-roots.md b/docs/handlers/sampling-and-roots.md index 6174f425..f7c192f0 100644 --- a/docs/handlers/sampling-and-roots.md +++ b/docs/handlers/sampling-and-roots.md @@ -11,7 +11,7 @@ Both still work, on every protocol version the SDK speaks. But read the warning A resolver returns `Sample(...)` and the tool receives the completion, through the same dependency mechanism that runs `Elicit` in **[Dependencies](dependencies.md)**: -```python title="server.py" hl_lines="11-16 20" +```python title="server.py" hl_lines="10-15 19" --8<-- "docs_src/sampling_and_roots/tutorial001.py" ``` @@ -24,7 +24,7 @@ A resolver returns `Sample(...)` and the tool receives the completion, through t Roots are the folders the client says the server may operate on. They are informational guidance, not an access-control mechanism. A resolver returns `ListRoots()`: -```python title="server.py" hl_lines="11-12 16" +```python title="server.py" hl_lines="10-11 15" --8<-- "docs_src/sampling_and_roots/tutorial002.py" ``` diff --git a/docs/handlers/subscriptions.md b/docs/handlers/subscriptions.md index 99b1bc98..c0e48511 100644 --- a/docs/handlers/subscriptions.md +++ b/docs/handlers/subscriptions.md @@ -56,7 +56,7 @@ Two things the stream is *not*: Here is a client on the other side of that stream, following the board: -```python title="client.py" hl_lines="16" +```python title="client.py" hl_lines="15" --8<-- "docs_src/subscriptions/tutorial003.py" ``` @@ -119,7 +119,7 @@ async def tools_reloaded() -> None: Down on the low-level `Server` there is no pre-wired anything, and the same parts assemble in three lines: -```python title="server.py" hl_lines="9-10 48" +```python title="server.py" hl_lines="8-9 47" --8<-- "docs_src/subscriptions/tutorial002.py" ``` diff --git a/docs/migration.md b/docs/migration.md index 7b5950e7..11569680 100644 --- a/docs/migration.md +++ b/docs/migration.md @@ -14,7 +14,7 @@ Every section heading below names the API it affects, so searching this page for |---|---|---| | `FastMCP` renamed to `MCPServer` | `ModuleNotFoundError: No module named 'mcp.server.fastmcp'` | [`FastMCP` renamed](#fastmcp-renamed-to-mcpserver) | | 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) | -| `mcp.types` moved to the `mcp-types` package | `ModuleNotFoundError: No module named 'mcp.types'` | [`mcp.types` moved](#mcptypes-moved-to-the-mcp-types-package) | +| `mcp.types` names removed | `ImportError: cannot import name 'Content' from 'mcp.types'` | [Removed types](#removed-type-aliases-and-classes) | | `McpError` renamed to `MCPError` | `ImportError: cannot import name 'McpError' from 'mcp'` | [`McpError` renamed](#mcperror-renamed-to-mcperror) | | Resource URIs are `str`, not `AnyUrl` | `AttributeError: 'str' object has no attribute 'host'` | [URI type](#resource-uri-type-changed-from-anyurl-to-str) | | Message unions (`ServerNotification`, `JSONRPCMessage`, ...) are plain unions, not `RootModel` | `AttributeError: 'LoggingMessageNotification' object has no attribute 'root'` | [`RootModel` → unions](#replace-rootmodel-by-union-types-with-typeadapter-validation) | @@ -196,21 +196,38 @@ nothing on PyPI to pin to, keep the unpinned form. ### `mcp.types` moved to the `mcp-types` package -The protocol wire types now live in a standalone distribution, `mcp-types`, imported as -`mcp_types`. Its only runtime dependencies are `pydantic` and `typing-extensions`, so code -that just needs to (de)serialize MCP traffic can install it without the full SDK. The `mcp` package depends on `mcp-types` and -continues to re-export the type names at the top level, so `from mcp import Tool` is -unchanged. Only the `mcp.types` submodule and `mcp.shared.version` were removed. The -package's API reference is at [`mcp_types`](api/mcp_types/index.md). +The protocol wire types now live in a standalone distribution, `mcp-types` (import package +`mcp_types`). Its only runtime dependencies are `pydantic` and `typing-extensions`, so code +that just needs to (de)serialize MCP traffic can install it without the full SDK. Its API +reference is at [`mcp_types`](api/mcp_types/index.md). -The supported import surface is `mcp_types`, `mcp_types.jsonrpc`, `mcp_types.methods`, and -`mcp_types.version`. Underscore-prefixed submodules (`mcp_types._types`, and the generated +**If your project depends on `mcp`, nothing changes for you.** `import mcp.types`, +`from mcp.types import ...`, `from mcp import types`, and `import mcp` followed by +`mcp.types.Tool` all keep working: `mcp.types` is a permanent alias that mirrors `mcp_types` +exactly (every name is the same object), and `mcp.types.version` mirrors +`mcp_types.version` the same way. Keep importing through `mcp` — the package you actually +depend on — rather than writing `import mcp_types`, which would reach past your declared +dependency into a transitive one. The old `mcp.shared.version` module was removed; import the +version registry from `mcp.types.version` instead. The top-level `from mcp import Tool` +re-exports are unchanged too. + +**Import `mcp_types` directly only in a project that depends on `mcp-types` without the +SDK.** That is the point of the split: tooling and lightweight clients can depend on the +protocol schema without pulling in `httpx2`, `starlette`, `uvicorn`, and the rest of the +server/transport stack. + +Names that no longer exist (listed under +[Removed type aliases and classes](#removed-type-aliases-and-classes)) fail on import or +attribute access with an ordinary `ImportError` / `AttributeError`; the table below names each +replacement. + +The supported import surface is the package plus its `jsonrpc`, `methods`, and `version` +submodules, and each has both spellings: `mcp.types` / `mcp_types`, `mcp.types.jsonrpc` / +`mcp_types.jsonrpc`, `mcp.types.methods` / `mcp_types.methods`, and `mcp.types.version` / +`mcp_types.version` (each `mcp.types` module mirrors its `mcp_types` counterpart, name for +name, the same objects). Underscore-prefixed submodules (`mcp_types._types`, and the generated per-protocol-version packages `mcp_types._v2025_11_25` / `mcp_types._v2026_07_28`) are internal -validators with unstable class names; don't import from them. - -**Why:** keeping the wire types in their own package lets tooling and lightweight clients -depend on the protocol schema without pulling in `httpx2`, `starlette`, `uvicorn`, and the -rest of the server/transport stack. +validators with unstable class names; don't import from them, under either spelling. **Before (v1):** @@ -219,19 +236,23 @@ from mcp.types import Tool, Resource from mcp.shared.version import LATEST_PROTOCOL_VERSION ``` -**After (v2):** +**After (v2), depending on `mcp`:** + +```python +from mcp.types import Tool, Resource # unchanged +from mcp.types.version import LATEST_PROTOCOL_VERSION +``` + +**After (v2), depending only on `mcp-types` (no SDK):** ```python from mcp_types import Tool, Resource from mcp_types.version import LATEST_PROTOCOL_VERSION - -# Names `mcp` already re-exported at the top level are unchanged: -from mcp import Tool, Resource ``` ### Removed type aliases and classes -The following type aliases and classes have been removed from `mcp_types`: +The following type aliases and classes have been removed from the protocol types (`mcp.types` / `mcp_types`): | Removed | Replacement | |---------|-------------| @@ -254,13 +275,13 @@ from mcp.types import Content, ResourceReference, Cursor **After (v2):** ```python -from mcp_types import ContentBlock, ResourceTemplateReference +from mcp.types import ContentBlock, ResourceTemplateReference # Use `str` instead of `Cursor` for pagination cursors ``` ### Field names changed from camelCase to snake_case -All Pydantic model fields in `mcp_types` now use snake_case names for Python attribute access. The JSON wire format is unchanged — traffic the SDK sends still uses camelCase via Pydantic aliases, but your own `model_dump()` calls now need `by_alias=True` to produce it. +All Pydantic model fields in the protocol types now use snake_case names for Python attribute access. The JSON wire format is unchanged — traffic the SDK sends still uses camelCase via Pydantic aliases, but your own `model_dump()` calls now need `by_alias=True` to produce it. **Before (v1):** @@ -320,7 +341,7 @@ In v1, MCP protocol types were configured with `extra="allow"`: unknown fields p In v2, MCP types silently ignore extra fields. Unknown constructor keyword arguments and unknown keys in wire data are dropped during validation — no error is raised, and the values do not round-trip: ```python -from mcp_types import CallToolRequestParams +from mcp.types import CallToolRequestParams params = CallToolRequestParams( name="my_tool", @@ -356,7 +377,7 @@ resource = Resource(name="test", uri=AnyUrl("users/me")) # Would fail validatio **After (v2):** ```python -from mcp_types import Resource +from mcp.types import Resource # Plain strings accepted resource = Resource(name="test", uri="users/me") # Works @@ -426,7 +447,7 @@ actual_notification = notification.root **After (v2):** ```python -from mcp_types import client_request_adapter, server_notification_adapter +from mcp.types import client_request_adapter, server_notification_adapter # Using TypeAdapter.validate_python() request = client_request_adapter.validate_python(data) @@ -469,7 +490,7 @@ await session.send_notification( | `ServerResult` | `server_result_adapter` | | `JSONRPCMessage` | `jsonrpc_message_adapter` | -All adapters are exported from `mcp_types`. +All adapters are exported from `mcp.types`. These are ordinary `X | Y` unions of the concrete pydantic classes, so `isinstance(msg, ServerNotification)`, `isinstance(msg, LoggingMessageNotification)`, and `match`/`case` on the member classes keep working (unlike `ElicitationResult`, which became a `TypeAliasType` — see [`isinstance()` checks against `ElicitationResult` raise `TypeError`](#isinstance-checks-against-elicitationresult-raise-typeerror)). @@ -525,7 +546,7 @@ attribute access. The JSON wire format is unchanged. ### `SUPPORTED_PROTOCOL_VERSIONS` deprecated; `LATEST_PROTOCOL_VERSION` changed meaning -`SUPPORTED_PROTOCOL_VERSIONS` is deprecated — it's now the union of `HANDSHAKE_PROTOCOL_VERSIONS` (initialize-handshake versions) and `MODERN_PROTOCOL_VERSIONS` (per-request-envelope versions). If you were using it to mean "versions the initialize handshake accepts", switch to `HANDSHAKE_PROTOCOL_VERSIONS`. Named scalars derived from these tuples are now exported alongside them — `LATEST_HANDSHAKE_VERSION`, `LATEST_MODERN_VERSION`, `OLDEST_SUPPORTED_VERSION` — so prefer those over indexing the tuples directly. All of these live in `mcp_types.version` (previously `mcp.shared.version`): `from mcp_types.version import HANDSHAKE_PROTOCOL_VERSIONS`. +`SUPPORTED_PROTOCOL_VERSIONS` is deprecated — it's now the union of `HANDSHAKE_PROTOCOL_VERSIONS` (initialize-handshake versions) and `MODERN_PROTOCOL_VERSIONS` (per-request-envelope versions). If you were using it to mean "versions the initialize handshake accepts", switch to `HANDSHAKE_PROTOCOL_VERSIONS`. Named scalars derived from these tuples are now exported alongside them — `LATEST_HANDSHAKE_VERSION`, `LATEST_MODERN_VERSION`, `OLDEST_SUPPORTED_VERSION` — so prefer those over indexing the tuples directly. All of these live in `mcp.types.version` (an alias of `mcp_types.version`; previously `mcp.shared.version`): `from mcp.types.version import HANDSHAKE_PROTOCOL_VERSIONS`. `LATEST_PROTOCOL_VERSION` also changed value and meaning. In v1 it was `"2025-11-25"`, the version the client offered during initialization. In v2 it is the newest revision the SDK speaks in any era, currently `"2026-07-28"`, which the initialize handshake cannot negotiate. If you offered it in a hand-built `initialize` request or compared the negotiated version against it, use `LATEST_HANDSHAKE_VERSION` instead. These tuples really are tuples now (`SUPPORTED_PROTOCOL_VERSIONS` was a `list` in v1), so list-only operations such as concatenating with a list raise `TypeError`. @@ -576,7 +597,7 @@ raise McpError(ErrorData(code=INVALID_REQUEST, message="bad input")) ```python from mcp.shared.exceptions import MCPError -from mcp_types import INVALID_REQUEST +from mcp.types import INVALID_REQUEST raise MCPError(INVALID_REQUEST, "bad input") # or, if you already have an ErrorData: @@ -601,7 +622,7 @@ JSONRPCMessage.model_validate( **After (v2):** ```python -from mcp_types import PARSE_ERROR, ErrorData, JSONRPCError, jsonrpc_message_adapter +from mcp.types import PARSE_ERROR, ErrorData, JSONRPCError, jsonrpc_message_adapter message = jsonrpc_message_adapter.validate_python( {"jsonrpc": "2.0", "id": None, "error": {"code": -32700, "message": "Parse error"}} @@ -641,7 +662,7 @@ mcp = MCPServer("Demo") All submodules under `mcp.server.fastmcp.*` are now under `mcp.server.mcpserver.*` with the same structure. Common imports: - `Image`, `Audio` — from `mcp.server.mcpserver` (or `.utilities.types`) -- `Icon` — from `mcp.server.mcpserver` or `mcp_types` (not a top-level `mcp` export); its `mimeType` field is now `mime_type` per the [snake_case renames](#field-names-changed-from-camelcase-to-snake_case), though the `mimeType=` kwarg still constructs +- `Icon` — from `mcp.server.mcpserver` or `mcp.types` (not a top-level `mcp` export); its `mimeType` field is now `mime_type` per the [snake_case renames](#field-names-changed-from-camelcase-to-snake_case), though the `mimeType=` kwarg still constructs - `Message`, `UserMessage`, `AssistantMessage` — from `mcp.server.mcpserver.prompts.base` - `ToolError`, `ResourceError` — from `mcp.server.mcpserver.exceptions` - `MCPServerError` (renamed from `FastMCPError`) — from `mcp.server.mcpserver.exceptions` @@ -844,7 +865,7 @@ Lifespans that set up process-wide state (connection pools, caches, background t Beyond the constructor parameters that moved to `run()`/`streamable_http_app()` and the lifespan change above, the server-side Streamable HTTP machinery is as in v1: -- `mcp.server.streamable_http` still exports the `EventStore` ABC (`store_event()`, `replay_events_after()`), `EventMessage`, `EventCallback`, `EventId`, and `StreamId` with unchanged signatures; a custom `EventStore` only needs `JSONRPCMessage` imported from `mcp_types` instead of `mcp.types`. +- `mcp.server.streamable_http` still exports the `EventStore` ABC (`store_event()`, `replay_events_after()`), `EventMessage`, `EventCallback`, `EventId`, and `StreamId` with unchanged signatures; a custom `EventStore` keeps importing `JSONRPCMessage` from `mcp.types`, unchanged. - `StreamableHTTPSessionManager` keeps its constructor and its `run()` / `handle_request()` methods (see [Lowlevel `Server`: what did not change](#lowlevel-server-what-did-not-change)); its `stateless=` parameter is unrelated to the removed [`Server.run(stateless=)` flag](#serverrun-no-longer-takes-a-stateless-flag). - `mcp.session_manager` still returns the manager once `streamable_http_app()` has been called, with the same `stateless`, `json_response`, `event_store`, and `retry_interval` attributes. - `stateless_http=True` still serves each request with a fresh transport, no `Mcp-Session-Id`, and no state carried between requests; `ctx.close_sse_stream()` and `ctx.close_standalone_sse_stream()` are still available on the handler `Context`. @@ -1205,7 +1226,7 @@ if isinstance(result, AcceptedElicitation): ... # result.data is a Confirm ``` -Narrowing on `result.action` (`"accept"` / `"decline"` / `"cancel"`) is unaffected. The `TypeError` is specific to `TypeAliasType` aliases like `ElicitationResult`; the `mcp_types` message unions (`ClientRequest`, `ServerNotification`, `JSONRPCMessage`, ...) are ordinary unions and stay `isinstance`-compatible (see [Replace `RootModel` by union types with `TypeAdapter` validation](#replace-rootmodel-by-union-types-with-typeadapter-validation)). +Narrowing on `result.action` (`"accept"` / `"decline"` / `"cancel"`) is unaffected. The `TypeError` is specific to `TypeAliasType` aliases like `ElicitationResult`; the `mcp.types` message unions (`ClientRequest`, `ServerNotification`, `JSONRPCMessage`, ...) are ordinary unions and stay `isinstance`-compatible (see [Replace `RootModel` by union types with `TypeAdapter` validation](#replace-rootmodel-by-union-types-with-typeadapter-validation)). ### Registering lowlevel handlers from `MCPServer` @@ -1227,7 +1248,7 @@ In v2, the lowlevel `Server` supports arbitrary request handlers directly via `a ```python from mcp.server import ServerRequestContext -from mcp_types import EmptyResult, SetLevelRequestParams, SubscribeRequestParams +from mcp.types import EmptyResult, SetLevelRequestParams, SubscribeRequestParams async def handle_set_logging_level(ctx: ServerRequestContext, params: SetLevelRequestParams) -> EmptyResult: @@ -1296,7 +1317,7 @@ async def handle_call_tool(name: str, arguments: dict): ```python from mcp.server import Server, ServerRequestContext -from mcp_types import ( +from mcp.types import ( CallToolRequestParams, CallToolResult, ListToolsResult, @@ -1345,13 +1366,13 @@ All handlers receive `ctx: ServerRequestContext` as the first argument. The seco | `@server.progress_notification()` | `on_progress` | `ProgressNotificationParams` | `None` | | — | `on_roots_list_changed` | `NotificationParams \| None` | `None` | -All `params` and return types are importable from `mcp_types`. +All `params` and return types are importable from `mcp.types`. **Notification handlers:** ```python from mcp.server import Server, ServerRequestContext -from mcp_types import ProgressNotificationParams +from mcp.types import ProgressNotificationParams async def handle_progress(ctx: ServerRequestContext, params: ProgressNotificationParams) -> None: @@ -1474,7 +1495,7 @@ async def call_tool(name: str, arguments: dict): ```python from mcp.server import Server -from mcp_types import CallToolResult, TextContent +from mcp.types import CallToolResult, TextContent async def handle_call_tool(ctx, params) -> CallToolResult: @@ -1618,7 +1639,7 @@ async def handle_call_tool(name: str, arguments: dict): ```python from mcp.server import ServerRequestContext -from mcp_types import CallToolRequestParams, CallToolResult, TextContent +from mcp.types import CallToolRequestParams, CallToolResult, TextContent async def handle_call_tool(ctx: ServerRequestContext, params: CallToolRequestParams) -> CallToolResult: @@ -1813,7 +1834,7 @@ result = await session.list_tools(cursor="next_page_token") **After (v2):** ```python -from mcp_types import PaginatedRequestParams +from mcp.types import PaginatedRequestParams result = await session.list_resources(params=PaginatedRequestParams(cursor="next_page_token")) result = await session.list_tools(params=PaginatedRequestParams(cursor="next_page_token")) @@ -1901,7 +1922,7 @@ To migrate, replace `timedelta(...)` with plain seconds, or mechanically append ### Client request timeouts now raise `-32001` (`REQUEST_TIMEOUT`) instead of `408` -A client request that exceeds `read_timeout_seconds` still raises the SDK's protocol error (`MCPError`, previously `McpError`), but the error code changed from the HTTP status `408` (`httpx.codes.REQUEST_TIMEOUT`) to the JSON-RPC code `-32001` (`REQUEST_TIMEOUT`, importable from `mcp_types`), matching the TypeScript SDK. The message changed too: v1 said `"Timed out while waiting for response to ClientRequest. Waited 5.0 seconds."`, v2 says `"Request 'tools/call' timed out"`. `MCPError.error` still exists, so a migrated `e.error.code == 408` check runs without error and silently never matches; timeouts fall through to whatever generic-error handling follows. Code that matched on the old message text breaks too. Compare against `REQUEST_TIMEOUT` instead. +A client request that exceeds `read_timeout_seconds` still raises the SDK's protocol error (`MCPError`, previously `McpError`), but the error code changed from the HTTP status `408` (`httpx.codes.REQUEST_TIMEOUT`) to the JSON-RPC code `-32001` (`REQUEST_TIMEOUT`, importable from `mcp.types`), matching the TypeScript SDK. The message changed too: v1 said `"Timed out while waiting for response to ClientRequest. Waited 5.0 seconds."`, v2 says `"Request 'tools/call' timed out"`. `MCPError.error` still exists, so a migrated `e.error.code == 408` check runs without error and silently never matches; timeouts fall through to whatever generic-error handling follows. Code that matched on the old message text breaks too. Compare against `REQUEST_TIMEOUT` instead. **Before (v1):** @@ -1922,7 +1943,7 @@ except McpError as e: ```python from mcp.shared.exceptions import MCPError -from mcp_types import REQUEST_TIMEOUT # -32001 +from mcp.types import REQUEST_TIMEOUT # -32001 try: result = await client.call_tool("slow_tool", {}) @@ -1933,7 +1954,7 @@ except MCPError as e: raise ``` -`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`. +`e.error.code` also still works; `e.code` is the v2 convenience property. The constant is importable from `mcp.types` (or from `mcp_types` in a project that uses that package without the SDK). The example uses the high-level `Client`; `ClientSession.call_tool()` raises the same `MCPError`. ### `ClientSession` now runs on `JSONRPCDispatcher`; `BaseSession` removed @@ -1951,7 +1972,7 @@ Behavior changes: - **Client callbacks now receive `mcp.client.ClientRequestContext`** (its `request_id` is always populated); the `mcp.shared.context.RequestContext` generic is deleted. Annotations spelled `RequestContext[ClientSession, Any]` become `ClientRequestContext` (details in [`RequestContext` type parameters simplified](#requestcontext-type-parameters-simplified)). Otherwise the callback surface is unchanged: the `sampling_callback=`, `elicitation_callback=`, `list_roots_callback=`, `logging_callback=`, and `message_handler=` keywords; the `SamplingFnT`, `ElicitationFnT`, `ListRootsFnT`, `LoggingFnT`, and `MessageHandlerFnT` protocols (still in `mcp.client.session`); and the params/result types (`CreateMessageRequestParams` → `CreateMessageResult | CreateMessageResultWithTools | ErrorData`, `ElicitRequestParams` → `ElicitResult | ErrorData`, `ListRootsResult | ErrorData` — returning `ErrorData` is not new). The `mcp.client.session`, `mcp.client.stdio`, `mcp.client.sse`, and `mcp.client.streamable_http` module paths are unchanged too, so `unittest.mock.patch` string targets still resolve. - **`message_handler` no longer receives requests.** Server-initiated requests are answered by the typed callbacks (`sampling_callback`, `elicitation_callback`, `list_roots_callback`), so the handler's parameter is now `IncomingMessage = ServerNotification | Exception`, exported from `mcp.client`. Replace the hand-written v1 union `RequestResponder[ServerRequest, ClientResult] | ServerNotification | Exception` with `IncomingMessage`; `RequestResponder` is gone (below), so the old annotation no longer imports. Delivered notifications are the concrete member instances rather than the v1 `RootModel` wrapper, so drop `.root` (`message.params`, not `message.root.params`); see [Replace `RootModel` by union types with `TypeAdapter` validation](#replace-rootmodel-by-union-types-with-typeadapter-validation). -The `mcp.shared.session` module is gone. `RequestResponder` is removed — `respond()`, the cancellation-tracking members (`cancel()`, the `cancelled` and `in_flight` properties, the `on_complete` constructor argument) and `BaseSession._in_flight` have no replacement; inbound cancellation is handled by `JSONRPCDispatcher`. `ProgressFnT` now lives only in `mcp.shared.dispatcher`, and `RequestId` in `mcp_types`. The module's generic typing helpers (`SendRequestT`, `SendResultT`, `SendNotificationT`, `ReceiveRequestT`, `ReceiveResultT`, `ReceiveNotificationT`) went with it and have no re-export — the sessions are no longer generic; `ClientSession.send_request` takes a concrete request model plus a result model class (or `pydantic.TypeAdapter`), so an override that needs a type parameter can declare its own `TypeVar` bound to `pydantic.BaseModel`. +The `mcp.shared.session` module is gone. `RequestResponder` is removed — `respond()`, the cancellation-tracking members (`cancel()`, the `cancelled` and `in_flight` properties, the `on_complete` constructor argument) and `BaseSession._in_flight` have no replacement; inbound cancellation is handled by `JSONRPCDispatcher`. `ProgressFnT` now lives only in `mcp.shared.dispatcher`, and `RequestId` in `mcp.types`. The module's generic typing helpers (`SendRequestT`, `SendResultT`, `SendNotificationT`, `ReceiveRequestT`, `ReceiveResultT`, `ReceiveNotificationT`) went with it and have no re-export — the sessions are no longer generic; `ClientSession.send_request` takes a concrete request model plus a result model class (or `pydantic.TypeAdapter`), so an override that needs a type parameter can declare its own `TypeVar` bound to `pydantic.BaseModel`. Subclassing `ClientSession` remains a valid interception point: every typed helper routes through `send_request`, and the notification helpers through `send_notification`, so overriding those two still sees that traffic (the 2026-era `discover()`/`send_discover()` are the exception — they call the dispatcher directly). For wire-level interception, use the `dispatcher=` argument instead (with the caveat above on hand-written dispatchers). @@ -1969,7 +1990,7 @@ async def elicitation_callback( ```python from mcp.client import ClientRequestContext -from mcp_types import ElicitRequestParams, ElicitResult, ErrorData +from mcp.types import ElicitRequestParams, ElicitResult, ErrorData async def elicitation_callback( @@ -1979,7 +2000,7 @@ async def elicitation_callback( ### Experimental Tasks support removed -Tasks ([SEP-1686](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1686)) have been removed from the MCP specification and are no longer part of this SDK. The `mcp.client.experimental`, `mcp.server.experimental`, `mcp.shared.experimental`, and `mcp.server.lowlevel.experimental` modules have been removed, along with the `experimental` properties on `ClientSession`, `ServerSession`, `Server`, and `ServerRequestContext`. The corresponding `Task*` types remain in `mcp_types` as types-only definitions, except the `TaskExecutionMode` alias, whose literal is now inlined on `ToolExecution.task_support`. +Tasks ([SEP-1686](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1686)) have been removed from the MCP specification and are no longer part of this SDK. The `mcp.client.experimental`, `mcp.server.experimental`, `mcp.shared.experimental`, and `mcp.server.lowlevel.experimental` modules have been removed, along with the `experimental` properties on `ClientSession`, `ServerSession`, `Server`, and `ServerRequestContext`. The corresponding `Task*` types remain in `mcp.types` as types-only definitions, except the `TaskExecutionMode` alias, whose literal is now inlined on `ToolExecution.task_support`. The 2026-07-28 revision reintroduces Tasks as an official extension: [SEP-2663](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2663), `io.modelcontextprotocol/tasks`, redesigned around polling (`tasks/get`) instead of a blocking `tasks/result`. This SDK does not implement the extension yet. @@ -2025,7 +2046,7 @@ result = await client.call_tool("long_running_task", {}, progress_callback=on_pr **Detached work** (create the task now, fetch its result on a later connection or after a client restart) has no v2 equivalent until the SEP-2663 extension is implemented. -Also drop `execution=ToolExecution(taskSupport=types.TASK_REQUIRED)` from tool definitions: the `TASK_REQUIRED` / `TASK_OPTIONAL` / `TASK_FORBIDDEN` constants are gone from `mcp_types` (`ToolExecution.task_support` takes the plain `"required"` / `"optional"` / `"forbidden"` literal), and no v2 client or server reads the field. +Also drop `execution=ToolExecution(taskSupport=types.TASK_REQUIRED)` from tool definitions: the `TASK_REQUIRED` / `TASK_OPTIONAL` / `TASK_FORBIDDEN` constants are gone from `mcp.types` (`ToolExecution.task_support` takes the plain `"required"` / `"optional"` / `"forbidden"` literal), and no v2 client or server reads the field. ## Transports @@ -2187,7 +2208,7 @@ while True: ```python from mcp import ClientSession, MCPError from mcp.client.streamable_http import streamable_http_client -from mcp_types import INVALID_REQUEST # -32600 +from mcp.types import INVALID_REQUEST # -32600 async with streamable_http_client(url) as (read, write): async with ClientSession(read, write) as session: @@ -2626,7 +2647,7 @@ Validation runs when the result is serialized onto the wire, not when the model ### Client validates inbound traffic against the protocol schema -`ClientSession` now validates server requests, notifications, and results against the negotiated protocol version's schema before parsing them into `mcp_types` models. Spec-invalid server output that the previous monolith parse tolerated may now raise `pydantic.ValidationError` from `list_tools()`, `call_tool()`, and similar calls. `_meta` remains the sanctioned place for result extras (and `experimental` for capability extras). +`ClientSession` now validates server requests, notifications, and results against the negotiated protocol version's schema before parsing them into `mcp.types` models. Spec-invalid server output that the previous monolith parse tolerated may now raise `pydantic.ValidationError` from `list_tools()`, `call_tool()`, and similar calls. `_meta` remains the sanctioned place for result extras (and `experimental` for capability extras). ### Unknown request methods now return `-32601` (Method not found) diff --git a/docs/run/deploy.md b/docs/run/deploy.md index 7cec5816..24f25c20 100644 --- a/docs/run/deploy.md +++ b/docs/run/deploy.md @@ -76,7 +76,7 @@ A **[multi-round-trip](../handlers/multi-round-trip.md)** tool needs something t Here is a tool that asks before it acts, on a server that configures nothing: -```python title="server.py" hl_lines="15 21" +```python title="server.py" hl_lines="14 20" --8<-- "docs_src/deploy/tutorial002.py" ``` @@ -111,7 +111,7 @@ The two rounds are two independent HTTP requests, and several ordinary things se The fix is one argument. It has **two** halves. -```python title="server.py" hl_lines="3 13 15" +```python title="server.py" hl_lines="1 12 14" --8<-- "docs_src/deploy/tutorial003.py" ``` diff --git a/docs/servers/completions.md b/docs/servers/completions.md index b7b8750f..1d7eca8e 100644 --- a/docs/servers/completions.md +++ b/docs/servers/completions.md @@ -21,7 +21,7 @@ Nothing here is about completions yet. Add **one** function decorated with `@mcp.completion()`: -```python title="server.py" hl_lines="22-30" +```python title="server.py" hl_lines="21-29" --8<-- "docs_src/completions/tutorial002.py" ``` @@ -91,7 +91,7 @@ You didn't list `completions` anywhere. The SDK saw the handler and declared the That's what `context` is for. It carries the arguments the user has **already resolved**: -```python title="server.py" hl_lines="9-12 35-39" +```python title="server.py" hl_lines="8-11 34-38" --8<-- "docs_src/completions/tutorial003.py" ``` diff --git a/docs/servers/handling-errors.md b/docs/servers/handling-errors.md index 0cb0a7df..4262f586 100644 --- a/docs/servers/handling-errors.md +++ b/docs/servers/handling-errors.md @@ -41,7 +41,7 @@ The model is the one calling your tool. It picked the arguments. So a tool error Now swap `ValueError` for `MCPError`. -```python title="server.py" hl_lines="1 3 15" +```python title="server.py" hl_lines="1 3 14" --8<-- "docs_src/handling_errors/tutorial002.py" ``` @@ -56,7 +56,7 @@ Now swap `ValueError` for `MCPError`. * There is **no result**. No `content`, no `is_error`: nothing for the model to read. * The **host** application gets the error instead, the same way it would if the tool didn't exist at all. -* `code`, `message`, and `data` arrive intact. `INVALID_PARAMS` is `-32602`; `mcp_types` exports it and the other JSON-RPC error codes (`INVALID_REQUEST`, `INTERNAL_ERROR`, ...) as constants so you never type a magic number. +* `code`, `message`, and `data` arrive intact. `INVALID_PARAMS` is `-32602`; `mcp.types` exports it and the other JSON-RPC error codes (`INVALID_REQUEST`, `INTERNAL_ERROR`, ...) as constants so you never type a magic number. !!! check Same lookup, same miss, but now the call *raises* on the client side instead of returning: @@ -127,7 +127,7 @@ It means a whole class of `raise` statements you don't write: don't re-validate * The deciding question: *could a smarter model have avoided this?* Yes -> exception. No -> `MCPError`. * `ResourceNotFoundError` from a resource handler -> the protocol's `-32602`, with the URI in `data`. * Bad arguments are rejected against the schema before your function runs; you don't `raise` for those. -* `from mcp import MCPError`; the error-code constants come from `mcp_types`. +* `from mcp import MCPError`; the error-code constants come from `mcp.types`. Errors handled. That is everything a server *exposes*. What every handler can read, and do back to the client while it runs, is the next section: **[Inside your handler](../handlers/index.md)**. diff --git a/docs/servers/media.md b/docs/servers/media.md index e8042b83..8655b77f 100644 --- a/docs/servers/media.md +++ b/docs/servers/media.md @@ -29,7 +29,7 @@ Two things to notice: * `structured_content` is `None`. An `Image` is content for the model to look at, not data for the application to parse: there is no output schema. (Contrast **[Structured Output](structured-output.md)**, where the return annotation *is* the schema.) !!! info - `ImageContent` and `AudioContent` live in `mcp_types`, right next to the `TextContent` + `ImageContent` and `AudioContent` live in `mcp.types`, right next to the `TextContent` that a plain `str` result becomes (**[Tools](tools.md)**). A tool result is a list of content blocks; `Image` and `Audio` are the shortest way to produce the two binary kinds. @@ -85,7 +85,7 @@ A suffix it doesn't recognise falls back to `application/octet-stream`. An `Icon` is metadata, not content. It doesn't carry the image; it points at one with a URI, and a client may fetch it and show it next to your server's name, a tool, a resource, or a prompt. -```python title="server.py" hl_lines="5-6 8 11 17" +```python title="server.py" hl_lines="4-5 7 10 16" --8<-- "docs_src/media/tutorial004.py" ``` diff --git a/docs/servers/tools.md b/docs/servers/tools.md index 8b7ee057..5b728cb7 100644 --- a/docs/servers/tools.md +++ b/docs/servers/tools.md @@ -142,7 +142,7 @@ There is nothing else to configure. Everything the SDK infers, you can override in the decorator: -```python title="server.py" hl_lines="8-11" +```python title="server.py" hl_lines="7-10" --8<-- "docs_src/tools/tutorial005.py" ``` diff --git a/docs/servers/uri-templates.md b/docs/servers/uri-templates.md index 6cda30eb..406a8fda 100644 --- a/docs/servers/uri-templates.md +++ b/docs/servers/uri-templates.md @@ -215,7 +215,7 @@ return the protocol types yourself. For fixed URIs, keep a registry and dispatch on exact match: -```python title="server.py" hl_lines="18 22 28" +```python title="server.py" hl_lines="17 21 27" --8<-- "docs_src/uri_templates/tutorial004.py" ``` @@ -229,7 +229,7 @@ The template engine `MCPServer` uses lives in `mcp.shared.uri_template` and works on its own. You get the same parsing and matching; you wire up the routing and security policy yourself. -```python title="server.py" hl_lines="14-17 23-26 30 34 46" +```python title="server.py" hl_lines="13-16 22-25 29 33 45" --8<-- "docs_src/uri_templates/tutorial005.py" ``` diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index 58c863f4..fda7e4bc 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -291,7 +291,7 @@ async def main() -> None: !!! info `-32021` is `MISSING_REQUIRED_CLIENT_CAPABILITY`, one of three error codes the 2026-07-28 spec adds. None of them is an exception class: they all arrive as `MCPError`, and - `e.error.code` is where to look. `mcp_types` exports the constants. The other two are + `e.error.code` is where to look. `mcp.types` exports the constants. The other two are `-32020` `HEADER_MISMATCH` (an HTTP header disagrees with the request body it accompanies) and `-32022` `UNSUPPORTED_PROTOCOL_VERSION` (the request named a version this server does not speak). A conforming SDK client cannot produce either, so if you see one, look at whatever is diff --git a/docs/whats-new.md b/docs/whats-new.md index 9826fa59..3107d2e8 100644 --- a/docs/whats-new.md +++ b/docs/whats-new.md @@ -117,7 +117,7 @@ Underneath, the v1 `BaseSession` receive loop was replaced by a dispatcher engin ### The wire types moved to `mcp-types`, and every field is snake_case -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. +The protocol types now live in their own distribution, `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: such a project installs `mcp-types` and imports `mcp_types`. `mcp` itself depends on that package at an exact version and re-exposes it, so code that depends on the SDK keeps writing `import mcp.types as types` and `from mcp.types import Tool` (a permanent alias, every name the same object) and declares only its one real dependency, `mcp`. The rule of thumb: import through whichever package you actually depend on. 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. @@ -146,7 +146,7 @@ Each of these is a section in the **[Migration Guide](migration.md)**: * The **WebSocket transport**, both sides, and the `mcp[ws]` extra. It was never part of the MCP specification. * 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. -* `mcp.types`, `mcp.shared.version`, `mcp.shared.progress`, and `mcp.shared.session` (with the `RequestResponder` stub v1 `message_handler` annotations imported) as import paths. +* `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.) * The deprecated `streamablehttp_client` spelling, and the `get_session_id` callback from `streamable_http_client` (which now yields exactly two streams). * `McpError`, renamed **`MCPError`** with a direct `(code, message, data)` constructor. * `MCPServer.get_context()`, `mount_path=`, and the lowlevel `Server`'s decorator methods, ContextVar, and handler dicts. diff --git a/docs_src/caching/tutorial002.py b/docs_src/caching/tutorial002.py index 6bbfec9e..e1722e81 100644 --- a/docs_src/caching/tutorial002.py +++ b/docs_src/caching/tutorial002.py @@ -1,8 +1,7 @@ from typing import Any -from mcp_types import ListToolsResult, PaginatedRequestParams, Tool - from mcp.server import CacheHint, Server, ServerRequestContext +from mcp.types import ListToolsResult, PaginatedRequestParams, Tool TOOLS = [Tool(name="forecast", input_schema={"type": "object"})] diff --git a/docs_src/caching/tutorial003.py b/docs_src/caching/tutorial003.py index 29c168c9..9ff3c361 100644 --- a/docs_src/caching/tutorial003.py +++ b/docs_src/caching/tutorial003.py @@ -1,11 +1,10 @@ from dataclasses import dataclass from typing import Any -from mcp_types import ListToolsResult, PaginatedRequestParams, Tool - from mcp import Client from mcp.client import CacheConfig from mcp.server import CacheHint, Server, ServerRequestContext +from mcp.types import ListToolsResult, PaginatedRequestParams, Tool @dataclass diff --git a/docs_src/client/tutorial003.py b/docs_src/client/tutorial003.py index 1aeab63a..bf74c467 100644 --- a/docs_src/client/tutorial003.py +++ b/docs_src/client/tutorial003.py @@ -1,8 +1,8 @@ -from mcp_types import TextContent from pydantic import BaseModel from mcp import Client from mcp.server import MCPServer +from mcp.types import TextContent mcp = MCPServer("Bookshop") diff --git a/docs_src/client/tutorial004.py b/docs_src/client/tutorial004.py index fddcde90..b0d62a77 100644 --- a/docs_src/client/tutorial004.py +++ b/docs_src/client/tutorial004.py @@ -1,7 +1,6 @@ -from mcp_types import TextResourceContents - from mcp import Client from mcp.server import MCPServer +from mcp.types import TextResourceContents mcp = MCPServer("Bookshop") diff --git a/docs_src/client/tutorial006.py b/docs_src/client/tutorial006.py index b76b6a0f..370e0b79 100644 --- a/docs_src/client/tutorial006.py +++ b/docs_src/client/tutorial006.py @@ -1,7 +1,6 @@ -from mcp_types import Completion, CompletionArgument, CompletionContext, PromptReference, ResourceTemplateReference - from mcp import Client from mcp.server import MCPServer +from mcp.types import Completion, CompletionArgument, CompletionContext, PromptReference, ResourceTemplateReference mcp = MCPServer("Bookshop") diff --git a/docs_src/client/tutorial007.py b/docs_src/client/tutorial007.py index 594b0520..c5c918bc 100644 --- a/docs_src/client/tutorial007.py +++ b/docs_src/client/tutorial007.py @@ -1,7 +1,6 @@ -from mcp_types import Tool - from mcp import Client from mcp.server import MCPServer +from mcp.types import Tool mcp = MCPServer("Bookshop") diff --git a/docs_src/client_callbacks/tutorial002.py b/docs_src/client_callbacks/tutorial002.py index 2bae985d..a37fbd63 100644 --- a/docs_src/client_callbacks/tutorial002.py +++ b/docs_src/client_callbacks/tutorial002.py @@ -1,7 +1,6 @@ -from mcp_types import ElicitRequestParams, ElicitResult - from mcp import Client from mcp.client import ClientRequestContext +from mcp.types import ElicitRequestParams, ElicitResult async def handle_elicitation( diff --git a/docs_src/client_callbacks/tutorial003.py b/docs_src/client_callbacks/tutorial003.py index c7a269a3..0ce615a6 100644 --- a/docs_src/client_callbacks/tutorial003.py +++ b/docs_src/client_callbacks/tutorial003.py @@ -1,8 +1,8 @@ -from mcp_types import ClientCapabilities, ElicitationCapability, RootsCapability, SamplingCapability from pydantic import BaseModel from mcp.server import MCPServer from mcp.server.mcpserver import Context +from mcp.types import ClientCapabilities, ElicitationCapability, RootsCapability, SamplingCapability mcp = MCPServer("Library") diff --git a/docs_src/client_callbacks/tutorial004.py b/docs_src/client_callbacks/tutorial004.py index 20c9b818..1c5fc2a6 100644 --- a/docs_src/client_callbacks/tutorial004.py +++ b/docs_src/client_callbacks/tutorial004.py @@ -1,7 +1,7 @@ -from mcp_types import CreateMessageRequestParams, CreateMessageResult, ListRootsResult, Root, TextContent from pydantic import FileUrl from mcp.client import ClientRequestContext +from mcp.types import CreateMessageRequestParams, CreateMessageResult, ListRootsResult, Root, TextContent async def handle_sampling( diff --git a/docs_src/completions/tutorial002.py b/docs_src/completions/tutorial002.py index 47152779..01ec02c5 100644 --- a/docs_src/completions/tutorial002.py +++ b/docs_src/completions/tutorial002.py @@ -1,6 +1,5 @@ -from mcp_types import Completion, CompletionArgument, CompletionContext, PromptReference, ResourceTemplateReference - from mcp.server import MCPServer +from mcp.types import Completion, CompletionArgument, CompletionContext, PromptReference, ResourceTemplateReference mcp = MCPServer("GitHub Explorer") diff --git a/docs_src/completions/tutorial003.py b/docs_src/completions/tutorial003.py index 3cbe21bc..13897a5e 100644 --- a/docs_src/completions/tutorial003.py +++ b/docs_src/completions/tutorial003.py @@ -1,6 +1,5 @@ -from mcp_types import Completion, CompletionArgument, CompletionContext, PromptReference, ResourceTemplateReference - from mcp.server import MCPServer +from mcp.types import Completion, CompletionArgument, CompletionContext, PromptReference, ResourceTemplateReference mcp = MCPServer("GitHub Explorer") diff --git a/docs_src/dependencies/tutorial004.py b/docs_src/dependencies/tutorial004.py index ff55e5ce..d08cc53b 100644 --- a/docs_src/dependencies/tutorial004.py +++ b/docs_src/dependencies/tutorial004.py @@ -1,9 +1,8 @@ from typing import Annotated -from mcp_types import CreateMessageResult, SamplingMessage, TextContent - from mcp.server import MCPServer from mcp.server.mcpserver import Resolve, Sample +from mcp.types import CreateMessageResult, SamplingMessage, TextContent mcp = MCPServer("Bookshop") diff --git a/docs_src/deploy/tutorial002.py b/docs_src/deploy/tutorial002.py index 8b61aaca..bb92fd90 100644 --- a/docs_src/deploy/tutorial002.py +++ b/docs_src/deploy/tutorial002.py @@ -1,6 +1,5 @@ -from mcp_types import ElicitRequest, ElicitRequestFormParams, ElicitResult, InputRequiredResult - from mcp.server.mcpserver import Context, MCPServer +from mcp.types import ElicitRequest, ElicitRequestFormParams, ElicitResult, InputRequiredResult CONFIRM = ElicitRequest( params=ElicitRequestFormParams( diff --git a/docs_src/deploy/tutorial003.py b/docs_src/deploy/tutorial003.py index 8d9d126c..f7ffc2e2 100644 --- a/docs_src/deploy/tutorial003.py +++ b/docs_src/deploy/tutorial003.py @@ -1,6 +1,5 @@ -from mcp_types import ElicitRequest, ElicitRequestFormParams, ElicitResult, InputRequiredResult - from mcp.server.mcpserver import Context, MCPServer, RequestStateSecurity +from mcp.types import ElicitRequest, ElicitRequestFormParams, ElicitResult, InputRequiredResult CONFIRM = ElicitRequest( params=ElicitRequestFormParams( diff --git a/docs_src/elicitation/tutorial003.py b/docs_src/elicitation/tutorial003.py index f6bb4020..c63c3e00 100644 --- a/docs_src/elicitation/tutorial003.py +++ b/docs_src/elicitation/tutorial003.py @@ -1,7 +1,6 @@ -from mcp_types import ElicitRequestParams, ElicitRequestURLParams, ElicitResult - from mcp import Client from mcp.client import ClientRequestContext +from mcp.types import ElicitRequestParams, ElicitRequestURLParams, ElicitResult async def handle_elicitation(context: ClientRequestContext, params: ElicitRequestParams) -> ElicitResult: diff --git a/docs_src/extensions/tutorial004.py b/docs_src/extensions/tutorial004.py index 7ad32052..d3e2ef3b 100644 --- a/docs_src/extensions/tutorial004.py +++ b/docs_src/extensions/tutorial004.py @@ -1,9 +1,9 @@ from collections.abc import Sequence from typing import Any, Literal -import mcp_types as types from pydantic import Field +import mcp.types as types from mcp import Client from mcp.client import advertise from mcp.server.context import ServerRequestContext diff --git a/docs_src/extensions/tutorial005.py b/docs_src/extensions/tutorial005.py index 61ec6c76..05b5210c 100644 --- a/docs_src/extensions/tutorial005.py +++ b/docs_src/extensions/tutorial005.py @@ -1,11 +1,10 @@ import logging from typing import Any -from mcp_types import CallToolRequestParams - from mcp.server.context import CallNext, HandlerResult, ServerRequestContext from mcp.server.extension import Extension from mcp.server.mcpserver import MCPServer +from mcp.types import CallToolRequestParams logger = logging.getLogger(__name__) diff --git a/docs_src/extensions/tutorial006.py b/docs_src/extensions/tutorial006.py index 05ffbcb9..88592af9 100644 --- a/docs_src/extensions/tutorial006.py +++ b/docs_src/extensions/tutorial006.py @@ -1,8 +1,7 @@ from collections.abc import Sequence from typing import Any, Literal -import mcp_types as types - +import mcp.types as types from mcp import Client from mcp.client import ClaimContext, ClientExtension, ResultClaim from mcp.server.context import CallNext, HandlerResult, ServerRequestContext diff --git a/docs_src/extensions/tutorial007.py b/docs_src/extensions/tutorial007.py index 37706ca2..182fc8f6 100644 --- a/docs_src/extensions/tutorial007.py +++ b/docs_src/extensions/tutorial007.py @@ -1,8 +1,7 @@ from collections.abc import Sequence from typing import Any, Literal -import mcp_types as types - +import mcp.types as types from mcp import Client from mcp.client import advertise from mcp.server.context import ServerRequestContext diff --git a/docs_src/handling_errors/tutorial002.py b/docs_src/handling_errors/tutorial002.py index b45c67e9..52c3a261 100644 --- a/docs_src/handling_errors/tutorial002.py +++ b/docs_src/handling_errors/tutorial002.py @@ -1,7 +1,6 @@ -from mcp_types import INVALID_PARAMS - from mcp import MCPError from mcp.server import MCPServer +from mcp.types import INVALID_PARAMS mcp = MCPServer("Bookshop") diff --git a/docs_src/legacy_clients/tutorial001.py b/docs_src/legacy_clients/tutorial001.py index 2f8b1191..2090201f 100644 --- a/docs_src/legacy_clients/tutorial001.py +++ b/docs_src/legacy_clients/tutorial001.py @@ -1,12 +1,12 @@ from typing import Annotated -from mcp_types import ElicitRequestParams, ElicitResult from pydantic import BaseModel from mcp import Client from mcp.client import ClientRequestContext from mcp.server import MCPServer from mcp.server.mcpserver import AcceptedElicitation, Elicit, ElicitationResult, Resolve +from mcp.types import ElicitRequestParams, ElicitResult mcp = MCPServer("Bookshop") diff --git a/docs_src/lowlevel/tutorial001.py b/docs_src/lowlevel/tutorial001.py index 999c707f..3b96aa2a 100644 --- a/docs_src/lowlevel/tutorial001.py +++ b/docs_src/lowlevel/tutorial001.py @@ -1,4 +1,5 @@ -from mcp_types import ( +from mcp.server import Server, ServerRequestContext +from mcp.types import ( CallToolRequestParams, CallToolResult, ListToolsResult, @@ -7,8 +8,6 @@ from mcp_types import ( Tool, ) -from mcp.server import Server, ServerRequestContext - SEARCH_BOOKS = Tool( name="search_books", description="Search the catalog by title or author.", diff --git a/docs_src/lowlevel/tutorial002.py b/docs_src/lowlevel/tutorial002.py index d3033f60..97eb4c4a 100644 --- a/docs_src/lowlevel/tutorial002.py +++ b/docs_src/lowlevel/tutorial002.py @@ -1,4 +1,5 @@ -from mcp_types import ( +from mcp.server import Server, ServerRequestContext +from mcp.types import ( CallToolRequestParams, CallToolResult, ListToolsResult, @@ -7,8 +8,6 @@ from mcp_types import ( Tool, ) -from mcp.server import Server, ServerRequestContext - SEARCH_BOOKS = Tool( name="search_books", description="Search the catalog by title or author.", diff --git a/docs_src/lowlevel/tutorial003.py b/docs_src/lowlevel/tutorial003.py index 65d89f19..68284858 100644 --- a/docs_src/lowlevel/tutorial003.py +++ b/docs_src/lowlevel/tutorial003.py @@ -1,4 +1,5 @@ -from mcp_types import ( +from mcp.server import Server, ServerRequestContext +from mcp.types import ( CallToolRequestParams, CallToolResult, ListToolsResult, @@ -7,8 +8,6 @@ from mcp_types import ( Tool, ) -from mcp.server import Server, ServerRequestContext - SEARCH_BOOKS = Tool( name="search_books", description="Search the catalog by title or author.", diff --git a/docs_src/lowlevel/tutorial004.py b/docs_src/lowlevel/tutorial004.py index 18b0bef8..cb8dfe4e 100644 --- a/docs_src/lowlevel/tutorial004.py +++ b/docs_src/lowlevel/tutorial004.py @@ -1,4 +1,5 @@ -from mcp_types import ( +from mcp.server import Server, ServerRequestContext +from mcp.types import ( CallToolRequestParams, CallToolResult, ListToolsResult, @@ -7,8 +8,6 @@ from mcp_types import ( Tool, ) -from mcp.server import Server, ServerRequestContext - SEARCH_BOOKS = Tool( name="search_books", description="Search the catalog by title or author.", diff --git a/docs_src/lowlevel/tutorial005.py b/docs_src/lowlevel/tutorial005.py index e33077ec..69e58024 100644 --- a/docs_src/lowlevel/tutorial005.py +++ b/docs_src/lowlevel/tutorial005.py @@ -2,7 +2,8 @@ from collections.abc import AsyncIterator from contextlib import asynccontextmanager from dataclasses import dataclass -from mcp_types import ( +from mcp.server import Server, ServerRequestContext +from mcp.types import ( CallToolRequestParams, CallToolResult, ListToolsResult, @@ -11,8 +12,6 @@ from mcp_types import ( Tool, ) -from mcp.server import Server, ServerRequestContext - @dataclass class Catalog: diff --git a/docs_src/lowlevel/tutorial006.py b/docs_src/lowlevel/tutorial006.py index 601fe5c5..158dca50 100644 --- a/docs_src/lowlevel/tutorial006.py +++ b/docs_src/lowlevel/tutorial006.py @@ -1,4 +1,7 @@ -from mcp_types import ( +from pydantic import BaseModel + +from mcp.server import Server, ServerRequestContext +from mcp.types import ( CallToolRequestParams, CallToolResult, ListToolsResult, @@ -7,9 +10,6 @@ from mcp_types import ( TextContent, Tool, ) -from pydantic import BaseModel - -from mcp.server import Server, ServerRequestContext SEARCH_BOOKS = Tool( name="search_books", diff --git a/docs_src/media/tutorial004.py b/docs_src/media/tutorial004.py index a06e6dfc..d0b717c8 100644 --- a/docs_src/media/tutorial004.py +++ b/docs_src/media/tutorial004.py @@ -1,6 +1,5 @@ -from mcp_types import Icon - from mcp.server import MCPServer +from mcp.types import Icon LOGO = Icon(src="https://example.com/brand-kit.png", mime_type="image/png", sizes=["48x48"]) PALETTE = Icon(src="https://example.com/palette.svg", mime_type="image/svg+xml", sizes=["any"]) diff --git a/docs_src/middleware/tutorial001.py b/docs_src/middleware/tutorial001.py index 71be62db..0c26c482 100644 --- a/docs_src/middleware/tutorial001.py +++ b/docs_src/middleware/tutorial001.py @@ -1,7 +1,9 @@ import logging import time -from mcp_types import ( +from mcp.server import Server, ServerRequestContext +from mcp.server.context import CallNext, HandlerResult +from mcp.types import ( CallToolRequestParams, CallToolResult, ListToolsResult, @@ -10,9 +12,6 @@ from mcp_types import ( Tool, ) -from mcp.server import Server, ServerRequestContext -from mcp.server.context import CallNext, HandlerResult - logger = logging.getLogger(__name__) diff --git a/docs_src/mrtr/tutorial001.py b/docs_src/mrtr/tutorial001.py index c0f4153c..9175ca4e 100644 --- a/docs_src/mrtr/tutorial001.py +++ b/docs_src/mrtr/tutorial001.py @@ -1,4 +1,5 @@ -from mcp_types import ( +from mcp.server import Server, ServerRequestContext +from mcp.types import ( CallToolRequestParams, CallToolResult, ElicitRequest, @@ -11,8 +12,6 @@ from mcp_types import ( Tool, ) -from mcp.server import Server, ServerRequestContext - ASK_REGION = ElicitRequest( params=ElicitRequestFormParams( message="Which region should the database live in?", diff --git a/docs_src/mrtr/tutorial002.py b/docs_src/mrtr/tutorial002.py index 0a140218..23cc1b19 100644 --- a/docs_src/mrtr/tutorial002.py +++ b/docs_src/mrtr/tutorial002.py @@ -1,6 +1,5 @@ -from mcp_types import CallToolResult, ElicitRequest, ElicitResult, InputRequest, InputRequiredResult, InputResponse - from mcp import Client +from mcp.types import CallToolResult, ElicitRequest, ElicitResult, InputRequest, InputRequiredResult, InputResponse def fulfil(request: InputRequest) -> InputResponse: diff --git a/docs_src/mrtr/tutorial003.py b/docs_src/mrtr/tutorial003.py index 03eb6bf7..6d7af85d 100644 --- a/docs_src/mrtr/tutorial003.py +++ b/docs_src/mrtr/tutorial003.py @@ -1,7 +1,6 @@ -from mcp_types import ElicitRequestParams, ElicitResult - from mcp import Client from mcp.client import ClientRequestContext +from mcp.types import ElicitRequestParams, ElicitResult async def handle_elicitation(context: ClientRequestContext, params: ElicitRequestParams) -> ElicitResult: diff --git a/docs_src/mrtr/tutorial004.py b/docs_src/mrtr/tutorial004.py index 05b94593..8cf90bee 100644 --- a/docs_src/mrtr/tutorial004.py +++ b/docs_src/mrtr/tutorial004.py @@ -1,7 +1,6 @@ -from mcp_types import ElicitRequest, ElicitRequestFormParams, ElicitResult, InputRequiredResult - from mcp.server.mcpserver import Context, MCPServer from mcp.server.mcpserver.prompts.base import UserMessage +from mcp.types import ElicitRequest, ElicitRequestFormParams, ElicitResult, InputRequiredResult mcp = MCPServer("Briefing") diff --git a/docs_src/pagination/tutorial001.py b/docs_src/pagination/tutorial001.py index 2ad4b945..3bc97540 100644 --- a/docs_src/pagination/tutorial001.py +++ b/docs_src/pagination/tutorial001.py @@ -1,8 +1,7 @@ from typing import Any -from mcp_types import ListResourcesResult, PaginatedRequestParams, Resource - from mcp.server import Server, ServerRequestContext +from mcp.types import ListResourcesResult, PaginatedRequestParams, Resource BOOKS = [f"book-{n}" for n in range(1, 101)] diff --git a/docs_src/pagination/tutorial002.py b/docs_src/pagination/tutorial002.py index cacb796e..f7284777 100644 --- a/docs_src/pagination/tutorial002.py +++ b/docs_src/pagination/tutorial002.py @@ -1,9 +1,8 @@ from typing import Any -from mcp_types import ListResourcesResult, PaginatedRequestParams, Resource - from mcp import Client from mcp.server import Server, ServerRequestContext +from mcp.types import ListResourcesResult, PaginatedRequestParams, Resource BOOKS = [f"book-{n}" for n in range(1, 101)] diff --git a/docs_src/sampling_and_roots/tutorial001.py b/docs_src/sampling_and_roots/tutorial001.py index c1e041c3..406d48d3 100644 --- a/docs_src/sampling_and_roots/tutorial001.py +++ b/docs_src/sampling_and_roots/tutorial001.py @@ -1,9 +1,8 @@ from typing import Annotated -from mcp_types import CreateMessageResult, SamplingMessage, TextContent - from mcp.server import MCPServer from mcp.server.mcpserver import Resolve, Sample +from mcp.types import CreateMessageResult, SamplingMessage, TextContent mcp = MCPServer("Bookshop") diff --git a/docs_src/sampling_and_roots/tutorial002.py b/docs_src/sampling_and_roots/tutorial002.py index 44a1d105..1646d432 100644 --- a/docs_src/sampling_and_roots/tutorial002.py +++ b/docs_src/sampling_and_roots/tutorial002.py @@ -1,9 +1,8 @@ from typing import Annotated -from mcp_types import ListRootsResult - from mcp.server import MCPServer from mcp.server.mcpserver import ListRoots, Resolve +from mcp.types import ListRootsResult mcp = MCPServer("Bookshop") diff --git a/docs_src/session_groups/tutorial004.py b/docs_src/session_groups/tutorial004.py index 7d107669..88fcec9c 100644 --- a/docs_src/session_groups/tutorial004.py +++ b/docs_src/session_groups/tutorial004.py @@ -1,8 +1,7 @@ import asyncio -from mcp_types import Implementation - from mcp import ClientSessionGroup, StdioServerParameters +from mcp.types import Implementation def by_server(name: str, server_info: Implementation) -> str: diff --git a/docs_src/subscriptions/tutorial002.py b/docs_src/subscriptions/tutorial002.py index 39e42dcc..b5e99d1e 100644 --- a/docs_src/subscriptions/tutorial002.py +++ b/docs_src/subscriptions/tutorial002.py @@ -1,7 +1,6 @@ from typing import Any -import mcp_types as types - +import mcp.types as types from mcp.server.context import ServerRequestContext from mcp.server.lowlevel import Server from mcp.server.subscriptions import InMemorySubscriptionBus, ListenHandler, ResourceUpdated diff --git a/docs_src/subscriptions/tutorial003.py b/docs_src/subscriptions/tutorial003.py index 811f6944..00abeacb 100644 --- a/docs_src/subscriptions/tutorial003.py +++ b/docs_src/subscriptions/tutorial003.py @@ -1,7 +1,6 @@ -from mcp_types import TextResourceContents - from mcp import Client from mcp.client.subscriptions import ResourceUpdated, ToolsListChanged +from mcp.types import TextResourceContents BOARD = "board://sprint" diff --git a/docs_src/tools/tutorial005.py b/docs_src/tools/tutorial005.py index f9fcbce9..9ba55129 100644 --- a/docs_src/tools/tutorial005.py +++ b/docs_src/tools/tutorial005.py @@ -1,6 +1,5 @@ -from mcp_types import ToolAnnotations - from mcp.server import MCPServer +from mcp.types import ToolAnnotations mcp = MCPServer("Bookshop") diff --git a/docs_src/uri_templates/tutorial004.py b/docs_src/uri_templates/tutorial004.py index c1920b3c..5abeb94d 100644 --- a/docs_src/uri_templates/tutorial004.py +++ b/docs_src/uri_templates/tutorial004.py @@ -1,4 +1,5 @@ -from mcp_types import ( +from mcp.server import Server, ServerRequestContext +from mcp.types import ( ListResourcesResult, PaginatedRequestParams, ReadResourceRequestParams, @@ -7,8 +8,6 @@ from mcp_types import ( TextResourceContents, ) -from mcp.server import Server, ServerRequestContext - RESOURCES = { "config://shop": '{"currency": "USD", "tax_rate": 0.08}', "status://health": "ok", diff --git a/docs_src/uri_templates/tutorial005.py b/docs_src/uri_templates/tutorial005.py index 716ff08d..94ac2fac 100644 --- a/docs_src/uri_templates/tutorial005.py +++ b/docs_src/uri_templates/tutorial005.py @@ -1,4 +1,7 @@ -from mcp_types import ( +from mcp.server import Server, ServerRequestContext +from mcp.shared.path_security import contains_path_traversal, is_absolute_path +from mcp.shared.uri_template import UriTemplate +from mcp.types import ( ListResourceTemplatesResult, PaginatedRequestParams, ReadResourceRequestParams, @@ -7,10 +10,6 @@ from mcp_types import ( TextResourceContents, ) -from mcp.server import Server, ServerRequestContext -from mcp.shared.path_security import contains_path_traversal, is_absolute_path -from mcp.shared.uri_template import UriTemplate - TEMPLATES = { "manuals": UriTemplate.parse("manuals://{+path}"), "books": UriTemplate.parse("books://{isbn}"), diff --git a/docs_src/whats_new/tutorial001.py b/docs_src/whats_new/tutorial001.py index 5e41ae1c..0a2426ca 100644 --- a/docs_src/whats_new/tutorial001.py +++ b/docs_src/whats_new/tutorial001.py @@ -1,4 +1,6 @@ -from mcp_types import ( +from mcp import MCPError +from mcp.server import Server, ServerRequestContext +from mcp.types import ( INVALID_PARAMS, CallToolRequestParams, CallToolResult, @@ -8,9 +10,6 @@ from mcp_types import ( Tool, ) -from mcp import MCPError -from mcp.server import Server, ServerRequestContext - SEARCH_BOOKS = Tool( name="search_books", description="Search the catalog by title or author.", diff --git a/examples/mcpserver/direct_call_tool_result_return.py b/examples/mcpserver/direct_call_tool_result_return.py index c73e6164..44a316bc 100644 --- a/examples/mcpserver/direct_call_tool_result_return.py +++ b/examples/mcpserver/direct_call_tool_result_return.py @@ -2,10 +2,10 @@ from typing import Annotated -from mcp_types import CallToolResult, TextContent from pydantic import BaseModel from mcp.server.mcpserver import MCPServer +from mcp.types import CallToolResult, TextContent mcp = MCPServer("Echo Server") diff --git a/examples/servers/everything-server/mcp_everything_server/server.py b/examples/servers/everything-server/mcp_everything_server/server.py index 4b03421f..b22e76ae 100644 --- a/examples/servers/everything-server/mcp_everything_server/server.py +++ b/examples/servers/everything-server/mcp_everything_server/server.py @@ -16,7 +16,8 @@ from mcp.server.mcpserver import Context, MCPServer, RequestStateSecurity from mcp.server.mcpserver.prompts.base import Prompt, UserMessage from mcp.server.streamable_http import EventCallback, EventMessage, EventStore from mcp.shared.exceptions import MCPError -from mcp_types import ( +from mcp.types import ( + MISSING_REQUIRED_CLIENT_CAPABILITY, AudioContent, Completion, CompletionArgument, @@ -44,7 +45,6 @@ from mcp_types import ( TextResourceContents, UnsubscribeRequestParams, ) -from mcp_types.jsonrpc import MISSING_REQUIRED_CLIENT_CAPABILITY from pydantic import BaseModel, Field logger = logging.getLogger(__name__) diff --git a/examples/servers/simple-pagination/mcp_simple_pagination/server.py b/examples/servers/simple-pagination/mcp_simple_pagination/server.py index 9aca87f7..b2bf0cc6 100644 --- a/examples/servers/simple-pagination/mcp_simple_pagination/server.py +++ b/examples/servers/simple-pagination/mcp_simple_pagination/server.py @@ -8,7 +8,7 @@ from typing import TypeVar import anyio import click -import mcp_types as types +import mcp.types as types from mcp.server import Server, ServerRequestContext T = TypeVar("T") diff --git a/examples/servers/simple-prompt/mcp_simple_prompt/server.py b/examples/servers/simple-prompt/mcp_simple_prompt/server.py index 31e3eb7d..6ddec653 100644 --- a/examples/servers/simple-prompt/mcp_simple_prompt/server.py +++ b/examples/servers/simple-prompt/mcp_simple_prompt/server.py @@ -1,6 +1,6 @@ import anyio import click -import mcp_types as types +import mcp.types as types from mcp.server import Server, ServerRequestContext diff --git a/examples/servers/simple-resource/mcp_simple_resource/server.py b/examples/servers/simple-resource/mcp_simple_resource/server.py index fe9dcfb7..24534cf3 100644 --- a/examples/servers/simple-resource/mcp_simple_resource/server.py +++ b/examples/servers/simple-resource/mcp_simple_resource/server.py @@ -2,7 +2,7 @@ from urllib.parse import urlparse import anyio import click -import mcp_types as types +import mcp.types as types from mcp.server import Server, ServerRequestContext SAMPLE_RESOURCES = { diff --git a/examples/servers/simple-streamablehttp-stateless/mcp_simple_streamablehttp_stateless/server.py b/examples/servers/simple-streamablehttp-stateless/mcp_simple_streamablehttp_stateless/server.py index 9df18cc6..575f8ab8 100644 --- a/examples/servers/simple-streamablehttp-stateless/mcp_simple_streamablehttp_stateless/server.py +++ b/examples/servers/simple-streamablehttp-stateless/mcp_simple_streamablehttp_stateless/server.py @@ -2,7 +2,7 @@ import logging import anyio import click -import mcp_types as types +import mcp.types as types import uvicorn from mcp.server import Server, ServerRequestContext from starlette.middleware.cors import CORSMiddleware diff --git a/examples/servers/simple-streamablehttp/mcp_simple_streamablehttp/event_store.py b/examples/servers/simple-streamablehttp/mcp_simple_streamablehttp/event_store.py index c9369cfc..3501fa47 100644 --- a/examples/servers/simple-streamablehttp/mcp_simple_streamablehttp/event_store.py +++ b/examples/servers/simple-streamablehttp/mcp_simple_streamablehttp/event_store.py @@ -10,7 +10,7 @@ from dataclasses import dataclass from uuid import uuid4 from mcp.server.streamable_http import EventCallback, EventId, EventMessage, EventStore, StreamId -from mcp_types import JSONRPCMessage +from mcp.types import JSONRPCMessage logger = logging.getLogger(__name__) diff --git a/examples/servers/simple-streamablehttp/mcp_simple_streamablehttp/server.py b/examples/servers/simple-streamablehttp/mcp_simple_streamablehttp/server.py index e650b357..70ddaf10 100644 --- a/examples/servers/simple-streamablehttp/mcp_simple_streamablehttp/server.py +++ b/examples/servers/simple-streamablehttp/mcp_simple_streamablehttp/server.py @@ -2,7 +2,7 @@ import logging import anyio import click -import mcp_types as types +import mcp.types as types import uvicorn from mcp.server import Server, ServerRequestContext from starlette.middleware.cors import CORSMiddleware diff --git a/examples/servers/simple-tool/mcp_simple_tool/server.py b/examples/servers/simple-tool/mcp_simple_tool/server.py index b16249e0..a43dd0f7 100644 --- a/examples/servers/simple-tool/mcp_simple_tool/server.py +++ b/examples/servers/simple-tool/mcp_simple_tool/server.py @@ -1,6 +1,6 @@ import anyio import click -import mcp_types as types +import mcp.types as types from mcp.server import Server, ServerRequestContext from mcp.shared._httpx_utils import create_mcp_http_client diff --git a/examples/servers/sse-polling-demo/mcp_sse_polling_demo/event_store.py b/examples/servers/sse-polling-demo/mcp_sse_polling_demo/event_store.py index e2cca4a2..c77bddef 100644 --- a/examples/servers/sse-polling-demo/mcp_sse_polling_demo/event_store.py +++ b/examples/servers/sse-polling-demo/mcp_sse_polling_demo/event_store.py @@ -10,7 +10,7 @@ from dataclasses import dataclass from uuid import uuid4 from mcp.server.streamable_http import EventCallback, EventId, EventMessage, EventStore, StreamId -from mcp_types import JSONRPCMessage +from mcp.types import JSONRPCMessage logger = logging.getLogger(__name__) diff --git a/examples/servers/sse-polling-demo/mcp_sse_polling_demo/server.py b/examples/servers/sse-polling-demo/mcp_sse_polling_demo/server.py index 7d2c60fa..452a3816 100644 --- a/examples/servers/sse-polling-demo/mcp_sse_polling_demo/server.py +++ b/examples/servers/sse-polling-demo/mcp_sse_polling_demo/server.py @@ -16,7 +16,7 @@ import logging import anyio import click -import mcp_types as types +import mcp.types as types import uvicorn from mcp.server import Server, ServerRequestContext diff --git a/examples/servers/structured-output-lowlevel/mcp_structured_output_lowlevel/__main__.py b/examples/servers/structured-output-lowlevel/mcp_structured_output_lowlevel/__main__.py index 393ff7a5..2fb62a94 100644 --- a/examples/servers/structured-output-lowlevel/mcp_structured_output_lowlevel/__main__.py +++ b/examples/servers/structured-output-lowlevel/mcp_structured_output_lowlevel/__main__.py @@ -10,9 +10,8 @@ import json import random from datetime import datetime -import mcp_types as types - import mcp.server.stdio +import mcp.types as types from mcp.server import Server, ServerRequestContext diff --git a/examples/snippets/clients/completion_client.py b/examples/snippets/clients/completion_client.py index 52957d97..dc0c1b4f 100644 --- a/examples/snippets/clients/completion_client.py +++ b/examples/snippets/clients/completion_client.py @@ -5,10 +5,9 @@ uv run completion-client import asyncio import os -from mcp_types import PromptReference, ResourceTemplateReference - from mcp import ClientSession, StdioServerParameters from mcp.client.stdio import stdio_client +from mcp.types import PromptReference, ResourceTemplateReference # Create server parameters for stdio connection server_params = StdioServerParameters( diff --git a/examples/snippets/clients/pagination_client.py b/examples/snippets/clients/pagination_client.py index 00663ef0..b9b8c23a 100644 --- a/examples/snippets/clients/pagination_client.py +++ b/examples/snippets/clients/pagination_client.py @@ -2,10 +2,9 @@ import asyncio -from mcp_types import PaginatedRequestParams, Resource - from mcp.client.session import ClientSession from mcp.client.stdio import StdioServerParameters, stdio_client +from mcp.types import PaginatedRequestParams, Resource async def list_all_resources() -> None: diff --git a/examples/snippets/clients/parsing_tool_results.py b/examples/snippets/clients/parsing_tool_results.py index f9aade41..6f2a985e 100644 --- a/examples/snippets/clients/parsing_tool_results.py +++ b/examples/snippets/clients/parsing_tool_results.py @@ -2,8 +2,7 @@ import asyncio -import mcp_types as types - +import mcp.types as types from mcp import ClientSession, StdioServerParameters from mcp.client.stdio import stdio_client diff --git a/examples/snippets/clients/stdio_client.py b/examples/snippets/clients/stdio_client.py index 6fff0838..577189eb 100644 --- a/examples/snippets/clients/stdio_client.py +++ b/examples/snippets/clients/stdio_client.py @@ -5,8 +5,7 @@ uv run client import asyncio import os -import mcp_types as types - +import mcp.types as types from mcp import ClientSession, StdioServerParameters from mcp.client.context import ClientRequestContext from mcp.client.stdio import stdio_client diff --git a/examples/snippets/clients/url_elicitation_client.py b/examples/snippets/clients/url_elicitation_client.py index de962eb7..14fc08d9 100644 --- a/examples/snippets/clients/url_elicitation_client.py +++ b/examples/snippets/clients/url_elicitation_client.py @@ -28,13 +28,12 @@ import webbrowser from typing import Any from urllib.parse import urlparse -import mcp_types as types -from mcp_types import URL_ELICITATION_REQUIRED - +import mcp.types as types from mcp import ClientSession from mcp.client.context import ClientRequestContext from mcp.client.sse import sse_client from mcp.shared.exceptions import MCPError, UrlElicitationRequiredError +from mcp.types import URL_ELICITATION_REQUIRED async def handle_elicitation( diff --git a/examples/snippets/servers/completion.py b/examples/snippets/servers/completion.py index 7fc2f204..47accffa 100644 --- a/examples/snippets/servers/completion.py +++ b/examples/snippets/servers/completion.py @@ -1,4 +1,5 @@ -from mcp_types import ( +from mcp.server.mcpserver import MCPServer +from mcp.types import ( Completion, CompletionArgument, CompletionContext, @@ -6,8 +7,6 @@ from mcp_types import ( ResourceTemplateReference, ) -from mcp.server.mcpserver import MCPServer - mcp = MCPServer(name="Example") diff --git a/examples/snippets/servers/direct_call_tool_result.py b/examples/snippets/servers/direct_call_tool_result.py index f3035338..4c98c358 100644 --- a/examples/snippets/servers/direct_call_tool_result.py +++ b/examples/snippets/servers/direct_call_tool_result.py @@ -2,10 +2,10 @@ from typing import Annotated -from mcp_types import CallToolResult, TextContent from pydantic import BaseModel from mcp.server.mcpserver import MCPServer +from mcp.types import CallToolResult, TextContent mcp = MCPServer("CallToolResult Example") diff --git a/examples/snippets/servers/elicitation.py b/examples/snippets/servers/elicitation.py index 97e847b5..79453f54 100644 --- a/examples/snippets/servers/elicitation.py +++ b/examples/snippets/servers/elicitation.py @@ -7,11 +7,11 @@ like OAuth flows, credential collection, or payment processing. import uuid -from mcp_types import ElicitRequestURLParams from pydantic import BaseModel, Field from mcp.server.mcpserver import Context, MCPServer from mcp.shared.exceptions import UrlElicitationRequiredError +from mcp.types import ElicitRequestURLParams mcp = MCPServer(name="Elicitation Example") diff --git a/examples/snippets/servers/lowlevel/basic.py b/examples/snippets/servers/lowlevel/basic.py index ff9b0a2c..6292a2d1 100644 --- a/examples/snippets/servers/lowlevel/basic.py +++ b/examples/snippets/servers/lowlevel/basic.py @@ -4,9 +4,8 @@ uv run examples/snippets/servers/lowlevel/basic.py import asyncio -import mcp_types as types - import mcp.server.stdio +import mcp.types as types from mcp.server import Server, ServerRequestContext diff --git a/examples/snippets/servers/lowlevel/direct_call_tool_result.py b/examples/snippets/servers/lowlevel/direct_call_tool_result.py index 4d6607d2..5545887f 100644 --- a/examples/snippets/servers/lowlevel/direct_call_tool_result.py +++ b/examples/snippets/servers/lowlevel/direct_call_tool_result.py @@ -4,9 +4,8 @@ uv run examples/snippets/servers/lowlevel/direct_call_tool_result.py import asyncio -import mcp_types as types - import mcp.server.stdio +import mcp.types as types from mcp.server import Server, ServerRequestContext diff --git a/examples/snippets/servers/lowlevel/lifespan.py b/examples/snippets/servers/lowlevel/lifespan.py index 46db9ecc..747dfb38 100644 --- a/examples/snippets/servers/lowlevel/lifespan.py +++ b/examples/snippets/servers/lowlevel/lifespan.py @@ -6,9 +6,8 @@ from collections.abc import AsyncIterator from contextlib import asynccontextmanager from typing import TypedDict -import mcp_types as types - import mcp.server.stdio +import mcp.types as types from mcp.server import Server, ServerRequestContext diff --git a/examples/snippets/servers/lowlevel/structured_output.py b/examples/snippets/servers/lowlevel/structured_output.py index 84e411ff..70c6ebfb 100644 --- a/examples/snippets/servers/lowlevel/structured_output.py +++ b/examples/snippets/servers/lowlevel/structured_output.py @@ -5,9 +5,8 @@ uv run examples/snippets/servers/lowlevel/structured_output.py import asyncio import json -import mcp_types as types - import mcp.server.stdio +import mcp.types as types from mcp.server import Server, ServerRequestContext diff --git a/examples/snippets/servers/pagination_example.py b/examples/snippets/servers/pagination_example.py index 4f7435ac..6ee17e81 100644 --- a/examples/snippets/servers/pagination_example.py +++ b/examples/snippets/servers/pagination_example.py @@ -1,7 +1,6 @@ """Example of implementing pagination with the low-level MCP server.""" -import mcp_types as types - +import mcp.types as types from mcp.server import Server, ServerRequestContext # Sample data to paginate diff --git a/examples/snippets/servers/sampling.py b/examples/snippets/servers/sampling.py index 83ec5066..a3f6d5c7 100644 --- a/examples/snippets/servers/sampling.py +++ b/examples/snippets/servers/sampling.py @@ -1,6 +1,5 @@ -from mcp_types import SamplingMessage, TextContent - from mcp.server.mcpserver import Context, MCPServer +from mcp.types import SamplingMessage, TextContent mcp = MCPServer(name="Sampling Example") diff --git a/examples/stories/_harness.py b/examples/stories/_harness.py index 62e02e70..9501fc06 100644 --- a/examples/stories/_harness.py +++ b/examples/stories/_harness.py @@ -19,13 +19,13 @@ from urllib.parse import urlsplit import anyio import httpx2 -from mcp_types.version import LATEST_MODERN_VERSION from mcp import StdioServerParameters, stdio_client from mcp.client import Transport from mcp.client.streamable_http import streamable_http_client from mcp.server import Server from mcp.server.mcpserver import MCPServer +from mcp.types.version import LATEST_MODERN_VERSION if sys.version_info >= (3, 11): import tomllib diff --git a/examples/stories/apps/client.py b/examples/stories/apps/client.py index dd79071b..661cfbf4 100644 --- a/examples/stories/apps/client.py +++ b/examples/stories/apps/client.py @@ -1,9 +1,8 @@ """Negotiate MCP Apps, discover a tool's `ui://` UI, fetch it, and call the tool.""" -from mcp_types import TextContent, TextResourceContents - from mcp.client import Client, advertise from mcp.server.apps import APP_MIME_TYPE, EXTENSION_ID +from mcp.types import TextContent, TextResourceContents from stories._harness import Target, run_client diff --git a/examples/stories/bearer_auth/server_lowlevel.py b/examples/stories/bearer_auth/server_lowlevel.py index f5abfc08..e03cb26d 100644 --- a/examples/stories/bearer_auth/server_lowlevel.py +++ b/examples/stories/bearer_auth/server_lowlevel.py @@ -2,10 +2,10 @@ from typing import Any -import mcp_types as types from pydantic import AnyHttpUrl from starlette.applications import Starlette +import mcp.types as types from mcp.server.auth.middleware.auth_context import get_access_token from mcp.server.auth.settings import AuthSettings from mcp.server.context import ServerRequestContext diff --git a/examples/stories/custom_methods/client.py b/examples/stories/custom_methods/client.py index 7bf27dd7..5e64068f 100644 --- a/examples/stories/custom_methods/client.py +++ b/examples/stories/custom_methods/client.py @@ -2,8 +2,7 @@ from typing import Literal -import mcp_types as types - +import mcp.types as types from mcp.client import Client from stories._harness import Target, run_client diff --git a/examples/stories/custom_methods/server.py b/examples/stories/custom_methods/server.py index 260aff78..88013db2 100644 --- a/examples/stories/custom_methods/server.py +++ b/examples/stories/custom_methods/server.py @@ -6,8 +6,7 @@ story's `server.py` is lowlevel-native (no `server_lowlevel.py` sibling). from typing import Any -import mcp_types as types - +import mcp.types as types from mcp.server.context import ServerRequestContext from mcp.server.lowlevel import Server from stories._hosting import run_server_from_args diff --git a/examples/stories/dual_era/client.py b/examples/stories/dual_era/client.py index b884c706..30eb262b 100644 --- a/examples/stories/dual_era/client.py +++ b/examples/stories/dual_era/client.py @@ -1,9 +1,8 @@ """Connect to the same server factory twice — once per era, so `main` takes `targets` — and assert both are served.""" -import mcp_types as types -from mcp_types.version import LATEST_HANDSHAKE_VERSION, LATEST_MODERN_VERSION - +import mcp.types as types from mcp.client import Client +from mcp.types.version import LATEST_HANDSHAKE_VERSION, LATEST_MODERN_VERSION from stories._harness import TargetFactory, run_client diff --git a/examples/stories/dual_era/server.py b/examples/stories/dual_era/server.py index 3f70ee63..59b6571f 100644 --- a/examples/stories/dual_era/server.py +++ b/examples/stories/dual_era/server.py @@ -1,8 +1,7 @@ """One MCPServer factory that serves both the 2025 handshake era and the 2026 stateless era.""" -from mcp_types.version import MODERN_PROTOCOL_VERSIONS - from mcp.server.mcpserver import Context, MCPServer +from mcp.types.version import MODERN_PROTOCOL_VERSIONS from stories._hosting import run_server_from_args diff --git a/examples/stories/dual_era/server_lowlevel.py b/examples/stories/dual_era/server_lowlevel.py index b209135e..64024201 100644 --- a/examples/stories/dual_era/server_lowlevel.py +++ b/examples/stories/dual_era/server_lowlevel.py @@ -2,11 +2,10 @@ from typing import Any -import mcp_types as types -from mcp_types.version import MODERN_PROTOCOL_VERSIONS - +import mcp.types as types from mcp.server.context import ServerRequestContext from mcp.server.lowlevel import Server +from mcp.types.version import MODERN_PROTOCOL_VERSIONS from stories._hosting import run_server_from_args GREET_INPUT_SCHEMA: dict[str, Any] = { diff --git a/examples/stories/error_handling/client.py b/examples/stories/error_handling/client.py index 872ec7fe..4a7cffb0 100644 --- a/examples/stories/error_handling/client.py +++ b/examples/stories/error_handling/client.py @@ -1,9 +1,8 @@ """Prove the two error channels: is_error results return; MCPError raises.""" -from mcp_types import INVALID_PARAMS, TextContent - from mcp import MCPError from mcp.client import Client +from mcp.types import INVALID_PARAMS, TextContent from stories._harness import Target, run_client diff --git a/examples/stories/error_handling/server.py b/examples/stories/error_handling/server.py index e4f35544..96667a5d 100644 --- a/examples/stories/error_handling/server.py +++ b/examples/stories/error_handling/server.py @@ -1,10 +1,9 @@ """Two error channels: ToolError -> is_error result; MCPError -> JSON-RPC protocol error.""" -from mcp_types import INVALID_PARAMS - from mcp.server.mcpserver import MCPServer from mcp.server.mcpserver.exceptions import ToolError from mcp.shared.exceptions import MCPError +from mcp.types import INVALID_PARAMS from stories._hosting import run_server_from_args diff --git a/examples/stories/error_handling/server_lowlevel.py b/examples/stories/error_handling/server_lowlevel.py index 9bb9aef8..81462abe 100644 --- a/examples/stories/error_handling/server_lowlevel.py +++ b/examples/stories/error_handling/server_lowlevel.py @@ -2,8 +2,7 @@ from typing import Any -import mcp_types as types - +import mcp.types as types from mcp.server.context import ServerRequestContext from mcp.server.lowlevel import Server from mcp.shared.exceptions import MCPError diff --git a/examples/stories/extensions/client.py b/examples/stories/extensions/client.py index 0bb033d7..eceb4a1a 100644 --- a/examples/stories/extensions/client.py +++ b/examples/stories/extensions/client.py @@ -2,10 +2,9 @@ from typing import Literal -import mcp_types as types -from mcp_types import TextContent - +import mcp.types as types from mcp.client import Client, advertise +from mcp.types import TextContent from stories._harness import Target, run_client EXTENSION_ID = "com.example/catalog" diff --git a/examples/stories/extensions/server.py b/examples/stories/extensions/server.py index 837c668d..7c34e8fa 100644 --- a/examples/stories/extensions/server.py +++ b/examples/stories/extensions/server.py @@ -9,9 +9,9 @@ the vendor method. from collections.abc import Sequence from typing import Any -import mcp_types as types from pydantic import Field +import mcp.types as types from mcp.server.context import ServerRequestContext from mcp.server.extension import Extension, MethodBinding, ToolBinding from mcp.server.mcpserver import MCPServer, require_client_extension diff --git a/examples/stories/identity_assertion/server_lowlevel.py b/examples/stories/identity_assertion/server_lowlevel.py index 1fcf8def..80852762 100644 --- a/examples/stories/identity_assertion/server_lowlevel.py +++ b/examples/stories/identity_assertion/server_lowlevel.py @@ -3,9 +3,9 @@ import json from typing import Any -import mcp_types as types from starlette.applications import Starlette +import mcp.types as types from mcp.server.auth.middleware.auth_context import get_access_token from mcp.server.auth.provider import ProviderTokenVerifier from mcp.server.context import ServerRequestContext diff --git a/examples/stories/json_response/client.py b/examples/stories/json_response/client.py index 8cbfed3f..c5a00a67 100644 --- a/examples/stories/json_response/client.py +++ b/examples/stories/json_response/client.py @@ -6,15 +6,15 @@ asserts the response is a single ``application/json`` body with no session id. """ import httpx2 -from mcp_types import TextContent -from mcp_types.version import LATEST_MODERN_VERSION from mcp.client import Client +from mcp.types import TextContent +from mcp.types.version import LATEST_MODERN_VERSION from stories._harness import Target, run_client # The raw 2026-07-28 POST envelope: per-request `_meta` replaces the initialize handshake. # The key/header strings are spelled out on purpose — this is the raw-wire story. In code -# use the named constants instead: `mcp_types.PROTOCOL_VERSION_META_KEY` / +# use the named constants instead: `mcp.types.PROTOCOL_VERSION_META_KEY` / # `CLIENT_INFO_META_KEY` / `CLIENT_CAPABILITIES_META_KEY` and # `mcp.shared.inbound.MCP_PROTOCOL_VERSION_HEADER` (`legacy_routing/` shows that form). RAW_ENVELOPE_BODY: dict[str, object] = { diff --git a/examples/stories/json_response/server_lowlevel.py b/examples/stories/json_response/server_lowlevel.py index bcb14eb9..33c2ebdc 100644 --- a/examples/stories/json_response/server_lowlevel.py +++ b/examples/stories/json_response/server_lowlevel.py @@ -2,9 +2,9 @@ from typing import Any -import mcp_types as types from starlette.applications import Starlette +import mcp.types as types from mcp.server.context import ServerRequestContext from mcp.server.lowlevel import Server from stories._hosting import NO_DNS_REBIND, run_app_from_args diff --git a/examples/stories/legacy_elicitation/client.py b/examples/stories/legacy_elicitation/client.py index 52bb95e5..96ce0ec4 100644 --- a/examples/stories/legacy_elicitation/client.py +++ b/examples/stories/legacy_elicitation/client.py @@ -1,7 +1,6 @@ """Auto-answer form and URL elicitations and assert the tool result reflects them.""" -import mcp_types as types - +import mcp.types as types from mcp.client import Client, ClientRequestContext from stories._harness import Target, run_client diff --git a/examples/stories/legacy_elicitation/server_lowlevel.py b/examples/stories/legacy_elicitation/server_lowlevel.py index 08c7c3a7..6c93a9ed 100644 --- a/examples/stories/legacy_elicitation/server_lowlevel.py +++ b/examples/stories/legacy_elicitation/server_lowlevel.py @@ -2,8 +2,7 @@ from typing import Any -import mcp_types as types - +import mcp.types as types from mcp.server.context import ServerRequestContext from mcp.server.lowlevel import Server from stories._hosting import run_server_from_args diff --git a/examples/stories/legacy_routing/client.py b/examples/stories/legacy_routing/client.py index b9b401a2..a3209472 100644 --- a/examples/stories/legacy_routing/client.py +++ b/examples/stories/legacy_routing/client.py @@ -2,12 +2,11 @@ from typing import Any -import mcp_types as types -from mcp_types import CLIENT_CAPABILITIES_META_KEY, CLIENT_INFO_META_KEY, PROTOCOL_VERSION_META_KEY -from mcp_types.version import LATEST_HANDSHAKE_VERSION, LATEST_MODERN_VERSION - +import mcp.types as types from mcp.client import Client from mcp.shared.inbound import MCP_METHOD_HEADER, MCP_PROTOCOL_VERSION_HEADER, InboundLadderRejection +from mcp.types import CLIENT_CAPABILITIES_META_KEY, CLIENT_INFO_META_KEY, PROTOCOL_VERSION_META_KEY +from mcp.types.version import LATEST_HANDSHAKE_VERSION, LATEST_MODERN_VERSION from stories._harness import TargetFactory, run_client from .server import classify_era diff --git a/examples/stories/legacy_routing/server.py b/examples/stories/legacy_routing/server.py index 79cc2afa..29712d09 100644 --- a/examples/stories/legacy_routing/server.py +++ b/examples/stories/legacy_routing/server.py @@ -3,13 +3,13 @@ from collections.abc import Mapping from typing import Any, Literal -from mcp_types import INVALID_PARAMS -from mcp_types.version import MODERN_PROTOCOL_VERSIONS from starlette.applications import Starlette from starlette.middleware.cors import CORSMiddleware from mcp.server.mcpserver import Context, MCPServer from mcp.shared.inbound import InboundLadderRejection, InboundModernRoute, classify_inbound_request +from mcp.types import INVALID_PARAMS +from mcp.types.version import MODERN_PROTOCOL_VERSIONS from stories._hosting import NO_DNS_REBIND, run_app_from_args #: Response headers a browser-based MCP client must be able to read. diff --git a/examples/stories/legacy_routing/server_lowlevel.py b/examples/stories/legacy_routing/server_lowlevel.py index d2f763c8..034f9e18 100644 --- a/examples/stories/legacy_routing/server_lowlevel.py +++ b/examples/stories/legacy_routing/server_lowlevel.py @@ -2,13 +2,13 @@ from typing import Any -import mcp_types as types -from mcp_types.version import MODERN_PROTOCOL_VERSIONS from starlette.applications import Starlette from starlette.middleware.cors import CORSMiddleware +import mcp.types as types from mcp.server.context import ServerRequestContext from mcp.server.lowlevel import Server +from mcp.types.version import MODERN_PROTOCOL_VERSIONS from stories._hosting import NO_DNS_REBIND, run_app_from_args from .server import MCP_ALLOWED_HEADERS, MCP_ALLOWED_METHODS, MCP_EXPOSED_HEADERS diff --git a/examples/stories/lifespan/client.py b/examples/stories/lifespan/client.py index 51633177..f84895cd 100644 --- a/examples/stories/lifespan/client.py +++ b/examples/stories/lifespan/client.py @@ -1,8 +1,7 @@ """Prove the lifespan-yielded state is reachable from a tool call.""" -from mcp_types import TextContent - from mcp.client import Client +from mcp.types import TextContent from stories._harness import Target, run_client diff --git a/examples/stories/lifespan/server_lowlevel.py b/examples/stories/lifespan/server_lowlevel.py index 09945c12..c5301dc1 100644 --- a/examples/stories/lifespan/server_lowlevel.py +++ b/examples/stories/lifespan/server_lowlevel.py @@ -5,8 +5,7 @@ from contextlib import asynccontextmanager from dataclasses import dataclass from typing import Any -import mcp_types as types - +import mcp.types as types from mcp.server.context import ServerRequestContext from mcp.server.lowlevel import Server from stories._hosting import run_server_from_args diff --git a/examples/stories/middleware/server.py b/examples/stories/middleware/server.py index 076120dc..e2164eb6 100644 --- a/examples/stories/middleware/server.py +++ b/examples/stories/middleware/server.py @@ -7,8 +7,7 @@ one supported registration point is the `middleware` list on `lowlevel.Server`. import json from typing import Any -import mcp_types as types - +import mcp.types as types from mcp.server.context import CallNext, HandlerResult, ServerRequestContext from mcp.server.lowlevel import Server from stories._hosting import run_server_from_args diff --git a/examples/stories/mrtr/client.py b/examples/stories/mrtr/client.py index 7280fd0a..eb770c71 100644 --- a/examples/stories/mrtr/client.py +++ b/examples/stories/mrtr/client.py @@ -1,7 +1,6 @@ """Drive the deploy tool both ways: the Client auto-loop, and a manual session-level loop.""" -import mcp_types as types - +import mcp.types as types from mcp import MCPError from mcp.client import Client, ClientRequestContext from stories._harness import Target, run_client diff --git a/examples/stories/mrtr/server.py b/examples/stories/mrtr/server.py index 8155b90f..cb308b9b 100644 --- a/examples/stories/mrtr/server.py +++ b/examples/stories/mrtr/server.py @@ -1,8 +1,7 @@ """Multi-round tool result (2026 era): a tool returns input_required and resumes from echoed state.""" -from mcp_types import ElicitRequest, ElicitRequestedSchema, ElicitRequestFormParams, ElicitResult, InputRequiredResult - from mcp.server.mcpserver import Context, MCPServer +from mcp.types import ElicitRequest, ElicitRequestedSchema, ElicitRequestFormParams, ElicitResult, InputRequiredResult from stories._hosting import run_server_from_args CONFIRM_SCHEMA: ElicitRequestedSchema = { diff --git a/examples/stories/mrtr/server_lowlevel.py b/examples/stories/mrtr/server_lowlevel.py index 6f3f489d..4382acbf 100644 --- a/examples/stories/mrtr/server_lowlevel.py +++ b/examples/stories/mrtr/server_lowlevel.py @@ -2,8 +2,7 @@ from typing import Any -import mcp_types as types - +import mcp.types as types from mcp.server.context import ServerRequestContext from mcp.server.lowlevel import Server from mcp.server.request_state import RequestStateBoundary, RequestStateSecurity diff --git a/examples/stories/oauth/server_lowlevel.py b/examples/stories/oauth/server_lowlevel.py index 0bc7799c..df2b0a4d 100644 --- a/examples/stories/oauth/server_lowlevel.py +++ b/examples/stories/oauth/server_lowlevel.py @@ -2,9 +2,9 @@ from typing import Any -import mcp_types as types from starlette.applications import Starlette +import mcp.types as types from mcp.server.auth.middleware.auth_context import get_access_token from mcp.server.auth.provider import ProviderTokenVerifier from mcp.server.context import ServerRequestContext diff --git a/examples/stories/oauth_client_credentials/server_lowlevel.py b/examples/stories/oauth_client_credentials/server_lowlevel.py index ba2003de..cde947e9 100644 --- a/examples/stories/oauth_client_credentials/server_lowlevel.py +++ b/examples/stories/oauth_client_credentials/server_lowlevel.py @@ -5,13 +5,13 @@ import json import secrets from typing import Any -import mcp_types as types from pydantic import AnyHttpUrl from starlette.applications import Starlette from starlette.requests import Request from starlette.responses import JSONResponse from starlette.routing import Route +import mcp.types as types from mcp.server.auth.middleware.auth_context import get_access_token from mcp.server.auth.provider import AccessToken from mcp.server.context import ServerRequestContext diff --git a/examples/stories/pagination/server_lowlevel.py b/examples/stories/pagination/server_lowlevel.py index 55958a96..cf024abf 100644 --- a/examples/stories/pagination/server_lowlevel.py +++ b/examples/stories/pagination/server_lowlevel.py @@ -2,8 +2,7 @@ from typing import Any -import mcp_types as types - +import mcp.types as types from mcp.server.context import ServerRequestContext from mcp.server.lowlevel import Server from mcp.shared.exceptions import MCPError diff --git a/examples/stories/parallel_calls/client.py b/examples/stories/parallel_calls/client.py index 945e5410..c940053d 100644 --- a/examples/stories/parallel_calls/client.py +++ b/examples/stories/parallel_calls/client.py @@ -1,9 +1,9 @@ """Two concurrent `Client`s, so `main` takes `targets`; their rendezvous in one tool proves concurrent dispatch.""" import anyio -from mcp_types import TextContent from mcp.client import Client +from mcp.types import TextContent from stories._harness import TargetFactory, run_client diff --git a/examples/stories/parallel_calls/server_lowlevel.py b/examples/stories/parallel_calls/server_lowlevel.py index 32807e17..2874e85d 100644 --- a/examples/stories/parallel_calls/server_lowlevel.py +++ b/examples/stories/parallel_calls/server_lowlevel.py @@ -4,8 +4,8 @@ from collections import defaultdict from typing import Any import anyio -import mcp_types as types +import mcp.types as types from mcp.server.context import ServerRequestContext from mcp.server.lowlevel import Server from stories._hosting import run_server_from_args diff --git a/examples/stories/prompts/client.py b/examples/stories/prompts/client.py index 22aae4af..d6837132 100644 --- a/examples/stories/prompts/client.py +++ b/examples/stories/prompts/client.py @@ -1,8 +1,7 @@ """List prompts, autocomplete an argument, then render both prompts.""" -from mcp_types import PromptReference, TextContent - from mcp.client import Client +from mcp.types import PromptReference, TextContent from stories._harness import Target, run_client diff --git a/examples/stories/prompts/server.py b/examples/stories/prompts/server.py index 2ef3fc3d..9fe9788d 100644 --- a/examples/stories/prompts/server.py +++ b/examples/stories/prompts/server.py @@ -1,9 +1,8 @@ """Prompts primitive: register templates, list, render, complete an argument.""" -from mcp_types import Completion, CompletionArgument, CompletionContext, PromptReference, ResourceTemplateReference - from mcp.server.mcpserver import MCPServer from mcp.server.mcpserver.prompts.base import AssistantMessage, Message, UserMessage +from mcp.types import Completion, CompletionArgument, CompletionContext, PromptReference, ResourceTemplateReference from stories._hosting import run_server_from_args LANGUAGES = ["python", "pytorch", "rust", "go", "typescript"] diff --git a/examples/stories/prompts/server_lowlevel.py b/examples/stories/prompts/server_lowlevel.py index 2fb41de8..2524f79d 100644 --- a/examples/stories/prompts/server_lowlevel.py +++ b/examples/stories/prompts/server_lowlevel.py @@ -2,8 +2,7 @@ from typing import Any -import mcp_types as types - +import mcp.types as types from mcp.server.context import ServerRequestContext from mcp.server.lowlevel import Server from stories._hosting import run_server_from_args diff --git a/examples/stories/reconnect/client.py b/examples/stories/reconnect/client.py index 0bf3c7af..c9c8a548 100644 --- a/examples/stories/reconnect/client.py +++ b/examples/stories/reconnect/client.py @@ -1,9 +1,8 @@ """Probe server/discover once, persist the result, reconnect with zero round-trips — a fresh `Client` via `targets`.""" -from mcp_types import DiscoverResult -from mcp_types.version import LATEST_MODERN_VERSION - from mcp.client import Client +from mcp.types import DiscoverResult +from mcp.types.version import LATEST_MODERN_VERSION from stories._harness import TargetFactory, run_client diff --git a/examples/stories/reconnect/server_lowlevel.py b/examples/stories/reconnect/server_lowlevel.py index 5c6a057d..ce6e2cb3 100644 --- a/examples/stories/reconnect/server_lowlevel.py +++ b/examples/stories/reconnect/server_lowlevel.py @@ -2,8 +2,7 @@ from typing import Any -import mcp_types as types - +import mcp.types as types from mcp.server.context import ServerRequestContext from mcp.server.lowlevel import Server from stories._hosting import run_server_from_args diff --git a/examples/stories/refund_desk/client.py b/examples/stories/refund_desk/client.py index 0ff8d28f..293947d5 100644 --- a/examples/stories/refund_desk/client.py +++ b/examples/stories/refund_desk/client.py @@ -1,7 +1,6 @@ """Prove the refund amount is schema-hidden, resolvers memoize per call, and decline semantics differ per consumer.""" -import mcp_types as types - +import mcp.types as types from mcp.client import Client, ClientRequestContext from stories._harness import Target, run_client diff --git a/examples/stories/resources/client.py b/examples/stories/resources/client.py index 29f88d52..9e12e51e 100644 --- a/examples/stories/resources/client.py +++ b/examples/stories/resources/client.py @@ -1,8 +1,7 @@ """List resources and templates, then read both the static and templated URIs.""" -from mcp_types import TextResourceContents - from mcp.client import Client +from mcp.types import TextResourceContents from stories._harness import Target, run_client diff --git a/examples/stories/resources/server_lowlevel.py b/examples/stories/resources/server_lowlevel.py index 2161fecc..2431ffdb 100644 --- a/examples/stories/resources/server_lowlevel.py +++ b/examples/stories/resources/server_lowlevel.py @@ -2,12 +2,11 @@ from typing import Any -import mcp_types as types -from mcp_types.jsonrpc import INVALID_PARAMS - +import mcp.types as types from mcp.server.context import ServerRequestContext from mcp.server.lowlevel import Server from mcp.shared.exceptions import MCPError +from mcp.types import INVALID_PARAMS from stories._hosting import run_server_from_args diff --git a/examples/stories/roots/client.py b/examples/stories/roots/client.py index 9d825299..ce18cd10 100644 --- a/examples/stories/roots/client.py +++ b/examples/stories/roots/client.py @@ -1,9 +1,9 @@ """Expose two filesystem roots and verify the server's tool can read them back.""" -from mcp_types import ListRootsResult, Root, TextContent from pydantic import FileUrl from mcp.client import Client, ClientRequestContext +from mcp.types import ListRootsResult, Root, TextContent from stories._harness import Target, run_client diff --git a/examples/stories/roots/server_lowlevel.py b/examples/stories/roots/server_lowlevel.py index 2696c946..af48d427 100644 --- a/examples/stories/roots/server_lowlevel.py +++ b/examples/stories/roots/server_lowlevel.py @@ -2,8 +2,7 @@ from typing import Any -import mcp_types as types - +import mcp.types as types from mcp.server.context import ServerRequestContext from mcp.server.lowlevel import Server from stories._hosting import run_server_from_args diff --git a/examples/stories/sampling/client.py b/examples/stories/sampling/client.py index 0ca88db9..93d3dddf 100644 --- a/examples/stories/sampling/client.py +++ b/examples/stories/sampling/client.py @@ -1,8 +1,7 @@ """Supply a canned sampling_callback and assert its text round-trips through the tool.""" -from mcp_types import CreateMessageRequestParams, CreateMessageResult, TextContent - from mcp.client import Client, ClientRequestContext +from mcp.types import CreateMessageRequestParams, CreateMessageResult, TextContent from stories._harness import Target, run_client diff --git a/examples/stories/sampling/server.py b/examples/stories/sampling/server.py index c97d8ab2..7481f2e3 100644 --- a/examples/stories/sampling/server.py +++ b/examples/stories/sampling/server.py @@ -1,8 +1,7 @@ """Sampling primitive: a tool asks the client's LLM for a completion mid-call.""" -from mcp_types import SamplingMessage, TextContent - from mcp.server.mcpserver import Context, MCPServer +from mcp.types import SamplingMessage, TextContent from stories._hosting import run_server_from_args diff --git a/examples/stories/sampling/server_lowlevel.py b/examples/stories/sampling/server_lowlevel.py index 5bc2a194..82f87332 100644 --- a/examples/stories/sampling/server_lowlevel.py +++ b/examples/stories/sampling/server_lowlevel.py @@ -2,8 +2,7 @@ from typing import Any -import mcp_types as types - +import mcp.types as types from mcp.server.context import ServerRequestContext from mcp.server.lowlevel import Server from stories._hosting import run_server_from_args diff --git a/examples/stories/schema_validators/client.py b/examples/stories/schema_validators/client.py index 8f6794ed..66e990bc 100644 --- a/examples/stories/schema_validators/client.py +++ b/examples/stories/schema_validators/client.py @@ -1,8 +1,7 @@ """Asserts each variant publishes a `who` object schema and the call round-trips.""" -from mcp_types import TextContent - from mcp.client import Client +from mcp.types import TextContent from stories._harness import Target, run_client diff --git a/examples/stories/schema_validators/server_lowlevel.py b/examples/stories/schema_validators/server_lowlevel.py index 02dca8d1..657c0320 100644 --- a/examples/stories/schema_validators/server_lowlevel.py +++ b/examples/stories/schema_validators/server_lowlevel.py @@ -2,8 +2,7 @@ from typing import Any -import mcp_types as types - +import mcp.types as types from mcp.server.context import ServerRequestContext from mcp.server.lowlevel import Server from stories._hosting import run_server_from_args diff --git a/examples/stories/serve_one/client.py b/examples/stories/serve_one/client.py index 73bd457e..b75510e9 100644 --- a/examples/stories/serve_one/client.py +++ b/examples/stories/serve_one/client.py @@ -1,9 +1,8 @@ """Drive `handle_one` directly to assert the raw result-dict shape, then over the wire.""" -import mcp_types as types -from mcp_types.version import LATEST_MODERN_VERSION - +import mcp.types as types from mcp.client import Client +from mcp.types.version import LATEST_MODERN_VERSION from stories._harness import Target, run_client from stories.serve_one.server import build_server, handle_one diff --git a/examples/stories/serve_one/server.py b/examples/stories/serve_one/server.py index 447e4a82..774a08fc 100644 --- a/examples/stories/serve_one/server.py +++ b/examples/stories/serve_one/server.py @@ -13,9 +13,8 @@ from dataclasses import dataclass, field from typing import Any import anyio -import mcp_types as types -from mcp_types.version import LATEST_MODERN_VERSION +import mcp.types as types from mcp.server.connection import Connection # deep-path import; shorter re-export planned from mcp.server.context import ServerRequestContext from mcp.server.lowlevel import Server @@ -24,6 +23,7 @@ from mcp.server.stdio import stdio_server from mcp.shared.exceptions import NoBackChannelError from mcp.shared.jsonrpc_dispatcher import JSONRPCDispatcher from mcp.shared.transport_context import TransportContext +from mcp.types.version import LATEST_MODERN_VERSION __all__ = ["SingleExchangeContext", "build_server", "handle_one"] diff --git a/examples/stories/sse_polling/client.py b/examples/stories/sse_polling/client.py index d2f39189..39cec5dc 100644 --- a/examples/stories/sse_polling/client.py +++ b/examples/stories/sse_polling/client.py @@ -1,9 +1,9 @@ """Call a tool whose SSE stream the server closes mid-flight; the call still completes. HTTP-only — no SSE on stdio.""" import anyio -from mcp_types import TextContent from mcp.client import Client +from mcp.types import TextContent from stories._harness import Target, run_client diff --git a/examples/stories/sse_polling/event_store.py b/examples/stories/sse_polling/event_store.py index 95d2b8ac..1cd24827 100644 --- a/examples/stories/sse_polling/event_store.py +++ b/examples/stories/sse_polling/event_store.py @@ -4,9 +4,8 @@ Sequential integer IDs so the wire is readable; a production server would back this interface with persistent storage so replay survives a process restart. """ -from mcp_types import JSONRPCMessage - from mcp.server.streamable_http import EventCallback, EventId, EventMessage, EventStore, StreamId +from mcp.types import JSONRPCMessage class InMemoryEventStore(EventStore): diff --git a/examples/stories/sse_polling/server_lowlevel.py b/examples/stories/sse_polling/server_lowlevel.py index fcf31998..72cb79d6 100644 --- a/examples/stories/sse_polling/server_lowlevel.py +++ b/examples/stories/sse_polling/server_lowlevel.py @@ -2,9 +2,9 @@ from typing import Any -import mcp_types as types from starlette.applications import Starlette +import mcp.types as types from mcp.server.context import ServerRequestContext from mcp.server.lowlevel import Server from stories._hosting import NO_DNS_REBIND, run_app_from_args diff --git a/examples/stories/standalone_get/client.py b/examples/stories/standalone_get/client.py index d2054ca8..7e9801db 100644 --- a/examples/stories/standalone_get/client.py +++ b/examples/stories/standalone_get/client.py @@ -1,8 +1,8 @@ """Receive `notifications/resources/list_changed` over the standalone GET stream, then re-list.""" import anyio -import mcp_types as types +import mcp.types as types from mcp.client import Client, IncomingMessage from stories._harness import Target, run_client diff --git a/examples/stories/standalone_get/server_lowlevel.py b/examples/stories/standalone_get/server_lowlevel.py index 21ee8c1f..d8c054f1 100644 --- a/examples/stories/standalone_get/server_lowlevel.py +++ b/examples/stories/standalone_get/server_lowlevel.py @@ -3,8 +3,7 @@ import itertools from typing import Any -import mcp_types as types - +import mcp.types as types from mcp.server.context import ServerRequestContext from mcp.server.lowlevel import Server from stories._hosting import run_server_from_args diff --git a/examples/stories/starlette_mount/client.py b/examples/stories/starlette_mount/client.py index dcfc3495..c2865773 100644 --- a/examples/stories/starlette_mount/client.py +++ b/examples/stories/starlette_mount/client.py @@ -1,8 +1,7 @@ """Connect to the sub-mounted MCP endpoint at /api/, list tools and call greet. HTTP-only: the mount is the story.""" -from mcp_types import TextContent - from mcp.client import Client +from mcp.types import TextContent from stories._harness import Target, run_client diff --git a/examples/stories/stateless_legacy/client.py b/examples/stories/stateless_legacy/client.py index d21ff850..1f9ea47f 100644 --- a/examples/stories/stateless_legacy/client.py +++ b/examples/stories/stateless_legacy/client.py @@ -1,9 +1,8 @@ """Connect at each era — two connections, so `main` takes `targets`; the same stateless app answers both.""" -from mcp_types import TextContent -from mcp_types.version import LATEST_HANDSHAKE_VERSION, LATEST_MODERN_VERSION - from mcp.client import Client +from mcp.types import TextContent +from mcp.types.version import LATEST_HANDSHAKE_VERSION, LATEST_MODERN_VERSION from stories._harness import TargetFactory, run_client diff --git a/examples/stories/stateless_legacy/server_lowlevel.py b/examples/stories/stateless_legacy/server_lowlevel.py index 44943abd..1bcf3581 100644 --- a/examples/stories/stateless_legacy/server_lowlevel.py +++ b/examples/stories/stateless_legacy/server_lowlevel.py @@ -2,9 +2,9 @@ from typing import Any -import mcp_types as types from starlette.applications import Starlette +import mcp.types as types from mcp.server.context import ServerRequestContext from mcp.server.lowlevel import Server from stories._hosting import NO_DNS_REBIND, run_app_from_args diff --git a/examples/stories/stickynotes/client.py b/examples/stories/stickynotes/client.py index a5b0e41d..b6b89151 100644 --- a/examples/stories/stickynotes/client.py +++ b/examples/stories/stickynotes/client.py @@ -1,10 +1,10 @@ """Drive the sticky-notes board end to end and prove `remove_all` clears only on a confirmed elicitation.""" import anyio -import mcp_types as types -from mcp_types.version import HANDSHAKE_PROTOCOL_VERSIONS +import mcp.types as types from mcp.client import Client, ClientRequestContext, IncomingMessage +from mcp.types.version import HANDSHAKE_PROTOCOL_VERSIONS from stories._harness import Target, run_client diff --git a/examples/stories/stickynotes/server_lowlevel.py b/examples/stories/stickynotes/server_lowlevel.py index 15a20a79..92266f14 100644 --- a/examples/stories/stickynotes/server_lowlevel.py +++ b/examples/stories/stickynotes/server_lowlevel.py @@ -5,8 +5,7 @@ from contextlib import asynccontextmanager from dataclasses import dataclass, field from typing import Any -import mcp_types as types - +import mcp.types as types from mcp.server.context import ServerRequestContext from mcp.server.lowlevel import Server from stories._hosting import run_server_from_args diff --git a/examples/stories/streaming/client.py b/examples/stories/streaming/client.py index e584b4c1..99398265 100644 --- a/examples/stories/streaming/client.py +++ b/examples/stories/streaming/client.py @@ -1,9 +1,9 @@ """Asserts progress + log notifications arrive in order, then cancels a call mid-flight.""" import anyio -from mcp_types import LoggingMessageNotificationParams from mcp.client import Client +from mcp.types import LoggingMessageNotificationParams from stories._harness import Target, run_client diff --git a/examples/stories/streaming/server.py b/examples/stories/streaming/server.py index ced59878..1c3dda9a 100644 --- a/examples/stories/streaming/server.py +++ b/examples/stories/streaming/server.py @@ -1,8 +1,8 @@ """Progress, in-flight logging, and cancellation from a single long-running tool.""" import anyio -import mcp_types as types +import mcp.types as types from mcp.server.mcpserver import Context, MCPServer from stories._hosting import run_server_from_args diff --git a/examples/stories/streaming/server_lowlevel.py b/examples/stories/streaming/server_lowlevel.py index 6d9add0b..13393d49 100644 --- a/examples/stories/streaming/server_lowlevel.py +++ b/examples/stories/streaming/server_lowlevel.py @@ -3,8 +3,8 @@ from typing import Any import anyio -import mcp_types as types +import mcp.types as types from mcp.server.context import ServerRequestContext from mcp.server.lowlevel import Server from stories._hosting import run_server_from_args diff --git a/examples/stories/subscriptions/client.py b/examples/stories/subscriptions/client.py index d2053aaf..a034f0a8 100644 --- a/examples/stories/subscriptions/client.py +++ b/examples/stories/subscriptions/client.py @@ -1,8 +1,8 @@ """Open a `subscriptions/listen` stream, watch one URI and the tool list, then close it.""" import anyio -import mcp_types as types +import mcp.types as types from mcp.client import Client from mcp.client.subscriptions import ResourceUpdated, ToolsListChanged from stories._harness import Target, run_client diff --git a/examples/stories/subscriptions/server_lowlevel.py b/examples/stories/subscriptions/server_lowlevel.py index 6d9da182..d982c1ff 100644 --- a/examples/stories/subscriptions/server_lowlevel.py +++ b/examples/stories/subscriptions/server_lowlevel.py @@ -2,8 +2,7 @@ from typing import Any -import mcp_types as types - +import mcp.types as types from mcp.server.context import ServerRequestContext from mcp.server.lowlevel import Server from mcp.server.subscriptions import ( diff --git a/examples/stories/tools/client.py b/examples/stories/tools/client.py index 74e1ab4c..55c22e3b 100644 --- a/examples/stories/tools/client.py +++ b/examples/stories/tools/client.py @@ -1,8 +1,7 @@ """List tools, inspect schemas + annotations, call both tools, assert structured output.""" -from mcp_types import TextContent - from mcp.client import Client +from mcp.types import TextContent from stories._harness import Target, run_client diff --git a/examples/stories/tools/server.py b/examples/stories/tools/server.py index a1f035c2..93e43980 100644 --- a/examples/stories/tools/server.py +++ b/examples/stories/tools/server.py @@ -2,10 +2,10 @@ from typing import Literal -from mcp_types import ToolAnnotations from pydantic import BaseModel from mcp.server.mcpserver import MCPServer +from mcp.types import ToolAnnotations from stories._hosting import run_server_from_args diff --git a/examples/stories/tools/server_lowlevel.py b/examples/stories/tools/server_lowlevel.py index e6c4c05e..15cc7db3 100644 --- a/examples/stories/tools/server_lowlevel.py +++ b/examples/stories/tools/server_lowlevel.py @@ -2,8 +2,7 @@ from typing import Any -import mcp_types as types - +import mcp.types as types from mcp.server.context import ServerRequestContext from mcp.server.lowlevel import Server from stories._hosting import run_server_from_args diff --git a/pyproject.toml b/pyproject.toml index aa79ed39..a18d6e98 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -217,6 +217,8 @@ max-complexity = 24 # Default is 10 [tool.ruff.lint.per-file-ignores] "__init__.py" = ["F401"] +# The mcp.types package is an alias that mirrors mcp_types namespaces by design. +"src/mcp/types/*.py" = ["F403"] # Generated by scripts/gen_surface_types.py: raw datamodel-codegen output (TID251 lifts the repo-wide RootModel ban for these generated validators). "src/mcp-types/mcp_types/_v*/__init__.py" = ["D212", "E501", "I001", "TID251", "UP007", "UP037"] "tests/server/mcpserver/test_func_metadata.py" = ["E501"] diff --git a/scripts/docs/gen_ref_pages.py b/scripts/docs/gen_ref_pages.py index 2340e184..26916e8c 100644 --- a/scripts/docs/gen_ref_pages.py +++ b/scripts/docs/gen_ref_pages.py @@ -30,6 +30,12 @@ API_DIR = ROOT / "docs" / "api" # it from `src/` would emit the unimportable `mcp-types.mcp_types.*`. PACKAGES = (ROOT / "src" / "mcp", ROOT / "src" / "mcp-types" / "mcp_types") +# Alias packages that mirror another package's namespaces (`mcp.types` mirrors +# `mcp_types`, `mcp.types.version` mirrors `mcp_types.version`): the mirrored +# package's pages are the canonical rendering, so an alias, and every module +# under it, earns no page of its own. +EXCLUDED = frozenset({"mcp.types"}) + _KIND_SECTIONS = { griffe.Kind.MODULE: "Modules", griffe.Kind.CLASS: "Classes", @@ -185,6 +191,8 @@ def generate() -> list[NavItem]: continue ident = ".".join(parts) + if any(ident == e or ident.startswith(f"{e}.") for e in EXCLUDED): + continue documented.add(ident) stubs[API_DIR / doc_path] = _stub(parts[-1], f"::: {ident}") pages[ident] = API_DIR / doc_path diff --git a/src/mcp-types/mcp_types/jsonrpc.py b/src/mcp-types/mcp_types/jsonrpc.py index fcc3317d..e9c6db96 100644 --- a/src/mcp-types/mcp_types/jsonrpc.py +++ b/src/mcp-types/mcp_types/jsonrpc.py @@ -6,6 +6,29 @@ from typing import Annotated, Any, Final, Literal from pydantic import BaseModel, Field, TypeAdapter +__all__ = [ + "CONNECTION_CLOSED", + "HEADER_MISMATCH", + "INTERNAL_ERROR", + "INVALID_PARAMS", + "INVALID_REQUEST", + "JSONRPC_VERSION", + "METHOD_NOT_FOUND", + "MISSING_REQUIRED_CLIENT_CAPABILITY", + "PARSE_ERROR", + "REQUEST_TIMEOUT", + "UNSUPPORTED_PROTOCOL_VERSION", + "URL_ELICITATION_REQUIRED", + "ErrorData", + "JSONRPCError", + "JSONRPCMessage", + "JSONRPCNotification", + "JSONRPCRequest", + "JSONRPCResponse", + "RequestId", + "jsonrpc_message_adapter", +] + RequestId = Annotated[int, Field(strict=True)] | str """The ID of a JSON-RPC request.""" diff --git a/src/mcp-types/mcp_types/version.py b/src/mcp-types/mcp_types/version.py index c5c22332..e2f7e1ac 100644 --- a/src/mcp-types/mcp_types/version.py +++ b/src/mcp-types/mcp_types/version.py @@ -9,6 +9,18 @@ ordering questions go through KNOWN_PROTOCOL_VERSIONS. from typing import Final +__all__ = [ + "KNOWN_PROTOCOL_VERSIONS", + "HANDSHAKE_PROTOCOL_VERSIONS", + "MODERN_PROTOCOL_VERSIONS", + "SUPPORTED_PROTOCOL_VERSIONS", + "LATEST_PROTOCOL_VERSION", + "LATEST_HANDSHAKE_VERSION", + "LATEST_MODERN_VERSION", + "OLDEST_SUPPORTED_VERSION", + "is_version_at_least", +] + KNOWN_PROTOCOL_VERSIONS: Final[tuple[str, ...]] = ( "2024-11-05", "2025-03-26", diff --git a/src/mcp/__init__.py b/src/mcp/__init__.py index 085e445d..28bc4703 100644 --- a/src/mcp/__init__.py +++ b/src/mcp/__init__.py @@ -58,6 +58,9 @@ from mcp_types import ( ) from mcp_types import Role as SamplingRole +# Bind the `mcp.types` submodule on the package, as v1's `from .types import +# ...` did, so `import mcp` followed by `mcp.types.Tool` keeps working. +from . import types as types from .client._input_required import InputRequiredRoundsExceededError from .client.client import Client from .client.session import ClientSession diff --git a/src/mcp/types/__init__.py b/src/mcp/types/__init__.py new file mode 100644 index 00000000..9bdfa06a --- /dev/null +++ b/src/mcp/types/__init__.py @@ -0,0 +1,31 @@ +"""The MCP protocol wire types, as the `mcp.types` namespace. + +This module mirrors the standalone `mcp_types` package exactly (every name is the +same object), so SDK users can keep the familiar v1 spelling: + + import mcp.types as types + + types.TextContent(type="text", text="hi") + +The `mcp.types.jsonrpc`, `mcp.types.methods`, and `mcp.types.version` +submodules mirror `mcp_types.jsonrpc`, `mcp_types.methods`, and +`mcp_types.version` the same way, so every supported `mcp_types` import has +an `mcp.types` spelling. + +Depend on and import `mcp_types` directly instead when you only need to +(de)serialize MCP traffic and don't want the SDK's transport stack: its only +runtime dependencies are `pydantic` and `typing-extensions`. +""" + +# A wildcard mirror of the mcp_types namespace is the whole point of this module. +# pyright: reportWildcardImportFromLibrary=false + +from mcp_types import * +from mcp_types import __all__ as __all__ + +# Bind the mirror submodules on the package, so `mcp.types.version.X` is as +# reachable by attribute access as `mcp_types.version.X` (whose `__init__` +# binds `.version` by importing from it), not only via `from ... import`. +from . import jsonrpc as jsonrpc +from . import methods as methods +from . import version as version diff --git a/src/mcp/types/jsonrpc.py b/src/mcp/types/jsonrpc.py new file mode 100644 index 00000000..a76b74ee --- /dev/null +++ b/src/mcp/types/jsonrpc.py @@ -0,0 +1,13 @@ +"""The JSON-RPC 2.0 message and error types, as the `mcp.types.jsonrpc` namespace. + +A mirror of `mcp_types.jsonrpc` (every name is the same object), so code that +depends on `mcp` can import from `mcp.types.jsonrpc` without importing the +`mcp_types` distribution directly. Depend on and import `mcp_types.jsonrpc` +instead when you use `mcp-types` without the SDK. +""" + +# A wildcard mirror of the mcp_types.jsonrpc namespace is the whole point of this module. +# pyright: reportWildcardImportFromLibrary=false + +from mcp_types.jsonrpc import * +from mcp_types.jsonrpc import __all__ as __all__ diff --git a/src/mcp/types/methods.py b/src/mcp/types/methods.py new file mode 100644 index 00000000..4b01fcc6 --- /dev/null +++ b/src/mcp/types/methods.py @@ -0,0 +1,13 @@ +"""The MCP method registry, as the `mcp.types.methods` namespace. + +A mirror of `mcp_types.methods` (every name is the same object), so code that +depends on `mcp` can import from `mcp.types.methods` without importing the +`mcp_types` distribution directly. Depend on and import `mcp_types.methods` +instead when you use `mcp-types` without the SDK. +""" + +# A wildcard mirror of the mcp_types.methods namespace is the whole point of this module. +# pyright: reportWildcardImportFromLibrary=false + +from mcp_types.methods import * +from mcp_types.methods import __all__ as __all__ diff --git a/src/mcp/types/version.py b/src/mcp/types/version.py new file mode 100644 index 00000000..857c53f0 --- /dev/null +++ b/src/mcp/types/version.py @@ -0,0 +1,13 @@ +"""The protocol-version registry, as the `mcp.types.version` namespace. + +A mirror of `mcp_types.version` (every name is the same object), so code that +depends on `mcp` can write `from mcp.types.version import LATEST_MODERN_VERSION` +without importing the `mcp_types` distribution directly. Depend on and import +`mcp_types.version` instead when you use `mcp-types` without the SDK. +""" + +# A wildcard mirror of the mcp_types.version namespace is the whole point of this module. +# pyright: reportWildcardImportFromLibrary=false + +from mcp_types.version import * +from mcp_types.version import __all__ as __all__ diff --git a/tests/test_types.py b/tests/test_types.py index ad481d2c..e3382805 100644 --- a/tests/test_types.py +++ b/tests/test_types.py @@ -1,5 +1,12 @@ +import subprocess +import sys +from types import ModuleType from typing import Any +import mcp_types +import mcp_types.jsonrpc +import mcp_types.methods +import mcp_types.version import pytest from inline_snapshot import snapshot from mcp_types import ( @@ -38,6 +45,12 @@ from mcp_types import ( ) from pydantic import ValidationError +import mcp +import mcp.types +import mcp.types.jsonrpc +import mcp.types.methods +import mcp.types.version + @pytest.mark.anyio async def test_jsonrpc_request(): @@ -445,3 +458,48 @@ def test_input_required_result_requires_at_least_one_of_input_requests_or_reques with pytest.raises(ValidationError): InputRequiredResult(input_requests={}) assert InputRequiredResult(request_state="s").input_requests is None + + +def _assert_mirrors(mirror: ModuleType, source: ModuleType) -> None: + # The mirror shares the source's `__all__` list object by construction (`from source import + # __all__`), so the meaningful proof is that every exported name is the identical object. + assert all(getattr(mirror, name) is getattr(source, name) for name in source.__all__) + + +def test_mcp_types_namespace_mirrors_mcp_types_exactly(): + """SDK-defined: `mcp.types` is a permanent alias whose every name is the `mcp_types` object.""" + _assert_mirrors(mcp.types, mcp_types) + + +@pytest.mark.parametrize( + ("mirror", "source"), + [ + (mcp.types.jsonrpc, mcp_types.jsonrpc), + (mcp.types.methods, mcp_types.methods), + (mcp.types.version, mcp_types.version), + ], + ids=["jsonrpc", "methods", "version"], +) +def test_mcp_types_submodules_mirror_mcp_types_submodules_exactly(mirror: ModuleType, source: ModuleType): + """SDK-defined: every supported `mcp_types` submodule has an `mcp.types` mirror, name for name.""" + _assert_mirrors(mirror, source) + + +def test_bare_import_mcp_binds_the_types_submodule(): + """SDK-defined: `import mcp` alone binds `mcp.types`, so v1's `mcp.types.Tool` idiom works. + + A fresh interpreter is required to observe `import mcp` in isolation: this test process + has already imported `mcp.types`, and reloading `mcp` here would rebind classes that other + tests hold references to. + """ + # A regression hangs forever, so the bound only has to beat never (matches the suite's + # other subprocess.run calls). + result = subprocess.run( + [sys.executable, "-c", "import mcp; print(mcp.types.Tool.__name__)"], + capture_output=True, + text=True, + check=False, + timeout=20, + ) + assert result.returncode == 0, result.stderr + assert result.stdout == snapshot("Tool\n")