MCP Python SDK v2: Type-Hinted Tools, Two Release Lines, and a Migration You Have to Schedule
The official Python SDK for Model Context Protocol servers and clients
At a glance
- What is it?
- The official Python implementation of the Model Context Protocol ships servers and clients from one package. The interesting part is not the decorator syntax, it is the fact that pip install mcp now gives you 2.x while v1.x still receives security patches on a separate branch.
- Who is it for?
- Adopt mcp 2.x for new Python 3.10+ projects that expose tools or resources to an MCP host, and pin mcp>=1.28,<2 if you are not migrating yet, since the README states that pip install mcp now resolves to 2.x. Skip it if you need a non-Python runtime or a transport outside stdio, Streamable HTTP and SSE. Before committing, read the migration guide linked from the README and confirm which of your call sites touch the parts of the API that v2 reworked.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 5 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The boilerplate this SDK deletes
An MCP server has to describe its capabilities to a host, parse incoming requests, validate arguments against a schema, and serialise results back over a transport. Written by hand, that is a protocol implementation before you have written a single line of your actual feature. The SDK's claim is that two type-hinted Python functions and a docstring cover all of it.
The README's fifteen-line example makes the trade explicit. A function decorated with @mcp.tool() takes a: int, b: int and returns an int, and the README notes that 'a: int, b: int is the schema'. There is no JSON Schema block to keep in sync with the function signature, and no request parsing or validation code in the file. A second decorator, @mcp.resource("greeting://{name}"), registers a templated resource whose URI pattern carries the parameter.
The audience is Python developers who need to expose internal functions, data, or prompt templates to an LLM application without designing a bespoke tool-calling format. If your tools are already ordinary Python functions with sensible type hints, the registration cost is close to zero. If they are not, you will be adding annotations before you can add decorators.
What v2 changed and why the version pin matters more than the feature list
The README is blunt that v2 is 'a major rework of the SDK', driven by two things: support for the 2026-07-28 MCP specification (and, it says, every earlier revision), and fixes for what it calls long-standing architectural issues. It does not enumerate those issues on the front page. It points to a What's new in v2 page and a separate migration guide for 'every breaking change'.
That is the operational fact worth internalising. The package name did not change. pip install mcp now installs 2.x. If your requirements file says mcp without an upper bound, your next install can cross a major version boundary without any signal in the package name. The README's own remedy is explicit: keep a <2 upper bound, for example mcp>=1.28,<2, until you have migrated.
The v1.x line lives on a branch of the same repository and, per the README, continues to receive critical bug fixes and security patches, with documentation at a separate /v1/ path. Two stable lines under one PyPI name is a maintenance arrangement that works, but it puts the burden of choosing a line on your dependency declaration rather than on the installer.
How a server is declared and what the decorators actually register
The entry point is from mcp.server import MCPServer, instantiated with a display name. Decorated functions are attached to that instance. The README's example registers one tool and one templated resource, and the resource URI contains a {name} placeholder that maps to the function's name parameter.
The README points to docs_src/index/tutorial001.py in the repository as the full example. It does not describe the decorator's optional arguments, error semantics, or how a tool that raises an exception is reported to the client. Those details are left to the API reference at py.sdk.modelcontextprotocol.io/api/mcp/. Treat the front page as a shape, not a specification.
The transport layer is where the SDK does its heaviest lifting. The README states that servers can speak stdio, Streamable HTTP, and SSE. Which one you get is a runtime decision, not a code decision: the same server.py runs under mcp dev for inspection and under mcp run --transport streamable-http for deployment.
Running a server: mcp dev, mcp run, and the cli extra
Installation is uv add "mcp[cli]" or pip install "mcp[cli]". The cli extra is what adds the mcp command-line tool with mcp dev, mcp run, and mcp install. Plain mcp installs the SDK without the CLI, which is the right choice for a library that only needs the client classes. The README also gives a no-project form, uv run --with "mcp[cli]" mcp ..., for one-off commands.
Opening the example server in the MCP Inspector is uv run mcp dev server.py. Serving it over HTTP is uv run mcp run server.py --transport streamable-http, which the README pairs with the client example hitting http://localhost:8000/mcp. That default port and path appear only in the example; the README does not document flags for changing them, so check the CLI reference before assuming they are configurable.
The client side is deliberately symmetric. from mcp import Client, used as an async context manager against a URL, and the README states that a URL means Streamable HTTP. The same class can launch a local server as a stdio subprocess or take a custom transport. A tool call returns an object with a structured_content attribute, shown printing {'result': 3} for the add tool.
The migration is the real cost of entry
The README frames v2 as a fix for architectural problems, which is a reasonable thing to do and also a warning. Code written against v1 may not merely need a version bump; the migration guide is described as covering 'every breaking change', and the existence of a dedicated guide implies the list is not short. The README does not estimate the size of the change or give a compatibility shim, so the only honest way to size the work is to read that guide against your own call sites.
The second cost is the split documentation. Two sets of docs, one per major line, means search results and examples you find in the wild may target either. The README's own remedy is a version bound, which also stops you from accidentally reading v2 documentation while running v1 code.
A third limitation is scope rather than quality: the SDK is Python-only by definition, Python 3.10+ specifically, and the transports listed are stdio, Streamable HTTP, and SSE. If your host speaks something else, or your service is not Python, this package is not the tool, regardless of how clean the decorator syntax is.
Where a hand-rolled JSON-RPC layer still wins
The obvious alternative is not another MCP SDK, it is writing the protocol surface yourself against the specification. The difference is where the schema lives. With this SDK the function signature is the schema, and the SDK derives the tool description from annotations and the docstring. In a hand-rolled layer you write the JSON Schema by hand and keep it aligned with the handler as the function changes.
That manual approach costs more per tool but buys things the SDK does not advertise. You control exactly which fields are exposed, you can generate schemas from a source other than Python type hints, and you avoid a dependency whose major version has moved under a stable package name. For a single tool in a service you already operate, hand-rolling is defensible. For a server exposing a dozen tools where the schemas would otherwise drift, the decorator approach removes a class of bug rather than adding a feature.
The second alternative is a different MCP implementation in another language. That is not a like-for-like swap if your tools are Python functions; it means reimplementing them or calling across a process boundary. The README's stdio transport is the escape hatch here: a non-Python MCP server can be launched as a subprocess and driven by this SDK's Client, which keeps the protocol handling in one place even when the tools are not in Python.
Licence, releases, and what to verify before you pin
The project is MIT licensed, and the README points to the LICENSE file in the repository for the text. MIT is permissive and places no condition on how you distribute your own server code. That is a statement about the licence identifier, not advice about your situation; if you are redistributing the SDK itself or bundling it into a product with its own compliance requirements, read the licence text and your own counsel's guidance rather than this summary.
Release cadence is visible in the material: v2.2.0 and v1.30.0 landed on the same day in early September, with v2.0.1 a couple of weeks earlier. Two lines receiving releases in parallel is consistent with the README's promise of continued v1 maintenance, and it also means upgrade notes arrive on two tracks. The README does not state a support window for v1.x, so the duration of that maintenance is not something you can plan against from the front page alone.
What to verify first, concretely: run uv run mcp dev server.py against your own server and confirm the tool list and argument schemas the Inspector shows match what you intended. Then check your dependency declaration for a bare mcp requirement and add the <2 bound if you have not migrated. Finally, read the migration guide at py.sdk.modelcontextprotocol.io/migration/ before changing the pin, because that document, not this article, is where the breaking changes are enumerated.
Editorial conclusion
Adopt mcp 2.x for new Python 3.10+ projects that expose tools or resources to an MCP host, and pin mcp>=1.28,<2 if you are not migrating yet, since the README states that pip install mcp now resolves to 2.x. Skip it if you need a non-Python runtime or a transport outside stdio, Streamable HTTP and SSE. Before committing, read the migration guide linked from the README and confirm which of your call sites touch the parts of the API that v2 reworked.
Community notes