From e90d907242d768068b119d1599df7290cd2cb1ee Mon Sep 17 00:00:00 2001 From: Max Isbey <224885523+maxisbey@users.noreply.github.com> Date: Wed, 29 Jul 2026 14:53:06 +0000 Subject: [PATCH 01/11] Publish versioning, roadmap, and dependency policies for v2 The versioning policy, roadmap, and dependency policy that the SEP-1730 tier assessment relies on were written to the v1.x branch and never came forward to main. Add them for v2 as they actually stand: a docs page stating the version scheme, the public-API boundary, what counts as breaking, and the two deprecation channels; a roadmap page pointing at the 2026-07-28 project board and the extension work still open; and a root DEPENDENCY_POLICY.md describing the floors-only requirement style and the automated-update setup. CONTRIBUTING.md gets the issue-triage section (label taxonomy, priority commitments) that its rewrite dropped, and RELEASE.md links the new dependency policy from the bump recipe. No-Verification-Needed: doc-only change --- CONTRIBUTING.md | 16 +++++++++ DEPENDENCY_POLICY.md | 26 +++++++++++++++ RELEASE.md | 3 ++ docs/roadmap.md | 34 +++++++++++++++++++ docs/versioning.md | 77 ++++++++++++++++++++++++++++++++++++++++++++ mkdocs.yml | 3 ++ 6 files changed, 159 insertions(+) create mode 100644 DEPENDENCY_POLICY.md create mode 100644 docs/roadmap.md create mode 100644 docs/versioning.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b0fb9fa57b..20001ea2f9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -52,6 +52,21 @@ Issues labeled `needs confirmation` or `needs maintainer action` are **not** rea Before starting, comment on the issue so we can assign it to you. This prevents duplicate effort. +## Issue Triage + +Every new issue gets a first look from a maintainer within two business days. That first look is the *triage*: it means labeling the issue and deciding whether it is valid and actionable, not fixing it. + +The labels follow the shared [MCP SDK taxonomy](https://modelcontextprotocol.io/community/sdk-tiers#issue-triage-labels): one **type** (`bug`, `enhancement`, `question`), one **status** (`needs confirmation`, `needs repro`, `ready for work`, `good first issue`, `help wanted`), and — once actionable — one **priority**: + +| Label | Meaning | Commitment | +|-------|---------|------------| +| `P0` | Critical: core functionality failures (connections, message exchange, tools/resources/prompts) or a High/Critical-severity security issue | resolved within 7 days | +| `P1` | Significant bug affecting many users | next release | +| `P2` | Moderate issue or valuable feature request | as capacity allows | +| `P3` | Nice-to-have or rare edge case | opportunistic | + +Security reports do not belong in the issue tracker; [SECURITY.md](SECURITY.md) has the private channel. + ## Development Setup 1. Make sure you have Python 3.10+ installed @@ -125,6 +140,7 @@ pre-commit run --all-files - Follow PEP 8 style guidelines - Add type hints to all functions - Include docstrings for public APIs +- Changing a dependency's version bound or adding a runtime dependency follows the [Dependency Policy](DEPENDENCY_POLICY.md) ## Pull Requests diff --git a/DEPENDENCY_POLICY.md b/DEPENDENCY_POLICY.md new file mode 100644 index 0000000000..ce9e6d4a1f --- /dev/null +++ b/DEPENDENCY_POLICY.md @@ -0,0 +1,26 @@ +# Dependency Policy + +`mcp` is a library that lives inside other people's environments, so its dependency requirements are chosen to constrain your resolver as little as possible while still describing what the SDK actually needs. + +## How requirements are declared + +* **Floors, not pins.** Every runtime dependency is a `>=` lower bound, set to the oldest version that provides what the SDK uses. There are no upper bounds unless a dependency's next major version is known to break the SDK. +* **The one exception is `mcp-types`.** The wire-types package is developed and released with `mcp` in lockstep, so `mcp` requires exactly its own version (`mcp-types==`). It is not an independent constraint on your environment; it is the other half of the SDK. +* **Environment markers instead of parallel packages** — Python-version and platform differences (`python_version`, `sys_platform`) are expressed as markers on the requirement, so one wheel serves every supported environment. +* **Optional features are extras.** Anything only some users need lives behind an extra (`mcp[cli]`, `mcp[rich]`) rather than in the base requirement set. + +## When a floor moves + +A minimum version is raised only when the SDK starts relying on functionality, a fix, or an API that first appeared in that version. It is not raised because a dependency published a security advisory. The `>=` bound already lets — and expects — you to run the newest release your other constraints allow, so a higher floor would only shrink the set of environments the SDK installs into without changing what any correctly-updated environment resolves to. The SDK also does not add code to work around a vulnerability in a dependency; the fix belongs upstream and in your lockfile. ([Background](https://github.com/Kludex/uvicorn/discussions/2643) on this stance from another library that adopted it, and [python-sdk#1552](https://github.com/modelcontextprotocol/python-sdk/issues/1552).) + +Every declared floor is exercised: CI runs the full test suite both against the locked dependency set and against a `lowest-direct` resolution, on every supported Python version, so a floor that has quietly become false fails the build rather than a user's install. + +Raising a floor within the same major version of a dependency is a minor-release change and is called out in the release notes; see the [versioning policy](https://py.sdk.modelcontextprotocol.io/versioning/). Adding a new required runtime dependency is a maintainer decision made in an issue before the pull request, not a side effect of a feature. + +## Automated updates + +[Dependabot](https://github.com/modelcontextprotocol/python-sdk/blob/main/.github/dependabot.yml) opens monthly, grouped pull requests for the `uv` lockfile and for GitHub Actions, with a 14-day cooldown on newly published versions. These refresh the versions the SDK is developed and tested against (`uv.lock`); they never change the requirements published to PyPI, which move only under the rules above. + +## Security in the SDK itself + +Vulnerabilities in the SDK's own code — as opposed to its dependencies — follow the reporting process and response commitments in [SECURITY.md](https://github.com/modelcontextprotocol/python-sdk/blob/main/SECURITY.md). diff --git a/RELEASE.md b/RELEASE.md index 58b7fb48f5..1f5e870b8f 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -2,6 +2,9 @@ ## Bumping Dependencies +[`DEPENDENCY_POLICY.md`](DEPENDENCY_POLICY.md) says *when* a bound should +move; this is the mechanics. + 1. Change the dependency version in `pyproject.toml`. The root `mcp` project's runtime dependencies are dynamic and live under `[tool.hatch.metadata.hooks.uv-dynamic-versioning].dependencies`. diff --git a/docs/roadmap.md b/docs/roadmap.md new file mode 100644 index 0000000000..a435d33aae --- /dev/null +++ b/docs/roadmap.md @@ -0,0 +1,34 @@ +# Roadmap + +The SDK's job is to implement the MCP specification, so its roadmap is organized by specification revision: one GitHub project board per revision, each item an issue or pull request you can follow. This page names the board that is current, what remains open on it, and the maintenance stance for the previous major. + +## The 2026-07-28 revision — shipped, with follow-ups + +v2 implements the [2026-07-28 specification](https://modelcontextprotocol.io/specification/2026-07-28) (and negotiates back to every earlier revision — see [Protocol versions](protocol-versions.md)); **[What's new in v2](whats-new.md)** is the tour of what that meant for the SDK. + +* Board: **[python-sdk · 2026-07-28 spec](https://github.com/orgs/modelcontextprotocol/projects/42)**, tracking issue [#2891](https://github.com/modelcontextprotocol/python-sdk/issues/2891). +* Cross-SDK view: [2026-07-28 Spec Implementation](https://github.com/orgs/modelcontextprotocol/projects/41) tracks the same revision across all official SDKs. + +Open on that board: + +* **Capabilities API and the `server/discover` handler** — the last core item still in progress ([#2896](https://github.com/modelcontextprotocol/python-sdk/issues/2896)). + +## Extensions and optional client auth not yet implemented + +The 2026-07-28 revision moved some functionality out of the core protocol into named extensions, and defines client-side auth mechanisms an SDK may support. The ones this SDK does not implement yet are exactly the entries in the conformance suite's expected-failures baseline, [`.github/actions/conformance/expected-failures.yml`](https://github.com/modelcontextprotocol/python-sdk/blob/main/.github/actions/conformance/expected-failures.yml) — that file is grouped by SEP and each entry is removed as the corresponding work lands, so it is the live burn-down list: + +* **Tasks extension** (`io.modelcontextprotocol/tasks`, [SEP-2663](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/docs/seps/2663-tasks-extension.md)) — deferred at 2.0 because the 2026-07-28 design is wire-incompatible with the earlier in-core Tasks; tracked in [#2806](https://github.com/modelcontextprotocol/python-sdk/issues/2806). +* **DPoP-bound access tokens** ([SEP-1932](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1932)) in the OAuth client. +* **The workload-identity `jwt-bearer` grant** in the OAuth client. + +None of these gates conformance today — extension scenarios are informational in the tier scoring — but each is a real gap for anyone who needs the feature, and they are the current queue. + +## Continuous work + +* **Conformance** — every push runs the [conformance suite](https://github.com/modelcontextprotocol/conformance) as both server and client, against the released revisions and against the 2026-07-28 wire specifically; adopting each new harness release and reconciling its baseline is routine. +* **The next specification revision** — draft-only wire changes are tried behind the draft protocol version before they are final, and land in a release once the revision ships; the SDK targets releasing support alongside each new specification version. +* **Everything else** — the [issue tracker](https://github.com/modelcontextprotocol/python-sdk/issues) is the source of truth for bugs and smaller features; `P0`–`P3` labels carry priority. + +## The previous major + +`v1.x` is a maintenance line: critical bug fixes and security fixes only, no new features. Its documentation stays available at [/v1/](https://py.sdk.modelcontextprotocol.io/v1/), the support terms are in [Versioning and support policy](versioning.md#supported-release-lines), and the path off it is the **[Migration Guide](migration.md)**. diff --git a/docs/versioning.md b/docs/versioning.md new file mode 100644 index 0000000000..a409a2b8a2 --- /dev/null +++ b/docs/versioning.md @@ -0,0 +1,77 @@ +# Versioning and support policy + +This page states what a version number of the `mcp` package promises you: which changes can arrive in a minor release, which are held for the next major, how deprecations are announced, and how long each release line is supported. + +## The version number + +Releases follow [Semantic Versioning](https://semver.org/) semantics, written in [PEP 440](https://peps.python.org/pep-0440/) syntax: + +* **`2.X.Y`** — the version comes from the git tag; there is no version field to edit. +* **`X` (minor)** — new functionality and every non-breaking change. +* **`Y` (patch)** — bug fixes only. +* **The leading `2` (major)** — the only place a breaking change to the public API can land. +* **Pre-releases** are cut from `main` as `2.X.YaN` (alpha), `2.X.YbN` (beta), and `2.X.YrcN` (release candidate). Installers never select a pre-release unless you ask for one, by exact pin or `--pre`. + +`mcp` and its wire-types package [`mcp-types`](https://pypi.org/project/mcp-types/) release in lockstep at the same version: each `mcp` release requires exactly the matching `mcp-types` (`mcp-types==2.X.Y`). + +## What the public API is + +The compatibility promise covers the public API: + +* every name exported by `mcp` (its `__all__`) and by `mcp_types`, +* the import paths, classes, functions, and parameters documented on this site and in the [API Reference](api/mcp/index.md), +* documented behavior of those APIs. + +It does not cover names beginning with an underscore, modules and attributes that appear nowhere in the documentation, or the exact text of log lines, warnings, and exception messages (their *type* and the documented conditions that raise them are covered; their wording is not). Depending on one of those is depending on an implementation detail that may change in any release. + +Two labels mark APIs that sit outside the promise while they settle: + +* **Provisional** — shipped and supported, but the signature or semantics may still change in a minor release. The middleware chain is the current example, and its documentation says so. +* **Experimental** — behind an explicit opt-in and expected to change; treat it as a preview. + +## What counts as a breaking change + +These wait for the next major version: + +* removing or renaming a public name, +* changing a signature so that a call that worked stops working (a removed or reordered parameter, a newly required argument, a narrowed accepted type), +* changing a return type, a raised exception type, or documented behavior in a way existing callers would notice, +* removing a documented import path, extra, or CLI command. + +These do not, and can ship in a minor release: + +* new functions, parameters with defaults, classes, fields, and enum members, +* changes to provisional or experimental APIs, +* new deprecation warnings, and the eventual removal of a protocol feature the specification has retired (see [Deprecations](#deprecations)), +* raising a dependency's minimum version when the SDK needs newer functionality, or dropping a Python version that upstream has ended support for — both called out in the release notes (the [dependency policy](https://github.com/modelcontextprotocol/python-sdk/blob/main/DEPENDENCY_POLICY.md) covers the first), +* bug fixes, including fixes that make the SDK match documented or specified behavior it should have had all along. + +When a fix is arguably both a bug fix and a behavior change, the deciding question is whether reasonable code written against the *documented* behavior breaks. If it does, the change is breaking. + +## Deprecations + +There are two kinds, warned differently on purpose. + +**SDK API deprecations** — a name or parameter this SDK is retiring. The API keeps working, marked with [`typing_extensions.deprecated`](https://typing-extensions.readthedocs.io/en/latest/#typing_extensions.deprecated), so static type checkers flag every call site and Python emits a `DeprecationWarning` at runtime. A deprecated API survives at least one minor release with its warning in place, and is removed only in a major version: something deprecated during 2.x is not removed before 3.0. + +**Protocol deprecations** — a feature the MCP specification has retired (for example the SEP-2577 set in the 2026-07-28 revision). These keep working through the specification's deprecation window and warn with `MCPDeprecationWarning`, a `UserWarning` subclass, so the warning is visible by default rather than hidden the way `DeprecationWarning` is outside `__main__`. **[Deprecated features](deprecated.md)** lists every one, its replacement, and how to silence the warning when you genuinely serve older clients. + +## Supported release lines + +Two lines are maintained, and only the newest release of a line receives fixes: + +| Line | Branch | Receives | +| --- | --- | --- | +| 2.x — current stable | `main` | bug fixes, security fixes, new features | +| 1.x — maintenance | [`v1.x`](https://github.com/modelcontextprotocol/python-sdk/tree/v1.x) | critical bug fixes and security fixes | + +Older 1.x releases and all pre-releases are unsupported. The security-specific version of this table, and how to report a vulnerability, is in [SECURITY.md](https://github.com/modelcontextprotocol/python-sdk/blob/main/SECURITY.md). Still on 1.x? Its documentation is at [/v1/](https://py.sdk.modelcontextprotocol.io/v1/), and a `<2` upper bound on your `mcp` requirement keeps an unpinned resolve on that line until you migrate. + +Python versions are supported from the version in the package's `requires-python` up to the newest CPython release the test suite runs against; support for a Python version ends only after that version's upstream end-of-life. + +## Where changes are announced + +* **Release notes** — every release publishes curated notes on [GitHub Releases](https://github.com/modelcontextprotocol/python-sdk/releases): highlights, anything known-incomplete, and a full change list. Pre-releases say what changed since the previous pre-release. +* **The migration guide** — every breaking change between majors is documented in **[Migration Guide](migration.md)** with before-and-after code; a change is not merged for a major release without its entry. +* **The `breaking change` label** — pull requests that make a breaking change carry it, so the set is queryable ahead of a major release. +* **Deprecation warnings** — as above, one release of warning at minimum before an SDK API is removed. diff --git a/mkdocs.yml b/mkdocs.yml index 06b293f876..8a3cc4ab82 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -69,6 +69,9 @@ nav: - MCP Apps: advanced/apps.md - Troubleshooting: troubleshooting.md - Migration Guide: migration.md + - About: + - Versioning and support policy: versioning.md + - Roadmap: roadmap.md - API Reference: api/ theme: From e8bee4d5413db2e0da85aa5c273e67bde3202550 Mon Sep 17 00:00:00 2001 From: Max Isbey <224885523+maxisbey@users.noreply.github.com> Date: Mon, 10 Aug 2026 17:25:23 +0000 Subject: [PATCH 02/11] Address review: pre-release opt-in, era-scoped deprecations, lock recipe - versioning.md: name all three PEP 440 pre-release opt-in routes, matching RELEASE.md's wording. - versioning.md: say what a retired protocol feature does on each kind of connection instead of implying it keeps working everywhere. - roadmap.md: conformance runs on pull requests and pushes to main, not "every push". - RELEASE.md: the bump recipe said `uv lock --resolution lowest-direct`, which would floor the entire committed lock; the lock is a normal resolution and lowest-direct belongs only to the CI leg. No-Verification-Needed: doc-only change --- RELEASE.md | 6 +++++- docs/roadmap.md | 2 +- docs/versioning.md | 4 ++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/RELEASE.md b/RELEASE.md index 1f5e870b8f..eb093917e9 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -8,7 +8,11 @@ move; this is the mechanics. 1. Change the dependency version in `pyproject.toml`. The root `mcp` project's runtime dependencies are dynamic and live under `[tool.hatch.metadata.hooks.uv-dynamic-versioning].dependencies`. -2. Upgrade lock with `uv lock --resolution lowest-direct` +2. Regenerate the lock with `uv lock` (or `uv lock --upgrade-package ` + to move just that package's locked version). The committed `uv.lock` is a + normal, newest-allowed resolution; the `lowest-direct` resolution that + proves the floors still work is applied only by its CI matrix leg at test + time and never written to the lock. ## Release lines diff --git a/docs/roadmap.md b/docs/roadmap.md index a435d33aae..1aac99428e 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -25,7 +25,7 @@ None of these gates conformance today — extension scenarios are informational ## Continuous work -* **Conformance** — every push runs the [conformance suite](https://github.com/modelcontextprotocol/conformance) as both server and client, against the released revisions and against the 2026-07-28 wire specifically; adopting each new harness release and reconciling its baseline is routine. +* **Conformance** — every pull request and every push to `main` runs the [conformance suite](https://github.com/modelcontextprotocol/conformance) as both server and client, against the released revisions and against the 2026-07-28 wire specifically; adopting each new harness release and reconciling its baseline is routine. * **The next specification revision** — draft-only wire changes are tried behind the draft protocol version before they are final, and land in a release once the revision ships; the SDK targets releasing support alongside each new specification version. * **Everything else** — the [issue tracker](https://github.com/modelcontextprotocol/python-sdk/issues) is the source of truth for bugs and smaller features; `P0`–`P3` labels carry priority. diff --git a/docs/versioning.md b/docs/versioning.md index a409a2b8a2..35075f2eeb 100644 --- a/docs/versioning.md +++ b/docs/versioning.md @@ -10,7 +10,7 @@ Releases follow [Semantic Versioning](https://semver.org/) semantics, written in * **`X` (minor)** — new functionality and every non-breaking change. * **`Y` (patch)** — bug fixes only. * **The leading `2` (major)** — the only place a breaking change to the public API can land. -* **Pre-releases** are cut from `main` as `2.X.YaN` (alpha), `2.X.YbN` (beta), and `2.X.YrcN` (release candidate). Installers never select a pre-release unless you ask for one, by exact pin or `--pre`. +* **Pre-releases** are cut from `main` as `2.X.YaN` (alpha), `2.X.YbN` (beta), and `2.X.YrcN` (release candidate). Installers select a pre-release only when a requirement asks for one explicitly — an exact pin, a specifier that itself names a pre-release version (such as `mcp>=2.1.0b1`), or `--pre` — so an unpinned `pip install mcp` always lands on a stable release. `mcp` and its wire-types package [`mcp-types`](https://pypi.org/project/mcp-types/) release in lockstep at the same version: each `mcp` release requires exactly the matching `mcp-types` (`mcp-types==2.X.Y`). @@ -54,7 +54,7 @@ There are two kinds, warned differently on purpose. **SDK API deprecations** — a name or parameter this SDK is retiring. The API keeps working, marked with [`typing_extensions.deprecated`](https://typing-extensions.readthedocs.io/en/latest/#typing_extensions.deprecated), so static type checkers flag every call site and Python emits a `DeprecationWarning` at runtime. A deprecated API survives at least one minor release with its warning in place, and is removed only in a major version: something deprecated during 2.x is not removed before 3.0. -**Protocol deprecations** — a feature the MCP specification has retired (for example the SEP-2577 set in the 2026-07-28 revision). These keep working through the specification's deprecation window and warn with `MCPDeprecationWarning`, a `UserWarning` subclass, so the warning is visible by default rather than hidden the way `DeprecationWarning` is outside `__main__`. **[Deprecated features](deprecated.md)** lists every one, its replacement, and how to silence the warning when you genuinely serve older clients. +**Protocol deprecations** — a feature the MCP specification has retired (for example the SEP-2577 set in the 2026-07-28 revision). The SDK keeps implementing these through the specification's deprecation window, but what still works depends on the revision a connection negotiated: on a connection speaking an older revision they behave as before; on a 2026-07-28 connection a retired feature may have no wire support left at all (server-initiated sampling and roots have no back-channel to travel over, and `ping` no longer exists), so the call warns and then fails. Either way the call site warns with `MCPDeprecationWarning`, a `UserWarning` subclass, so the warning is visible by default rather than hidden the way `DeprecationWarning` is outside `__main__`. **[Deprecated features](deprecated.md)** lists every one, exactly what happens on each kind of connection, its replacement, and how to silence the warning when you genuinely serve older clients. ## Supported release lines From fbefbf6f106b287fae22c60348169927801b7822 Mon Sep 17 00:00:00 2001 From: Max Isbey <224885523+maxisbey@users.noreply.github.com> Date: Fri, 14 Aug 2026 12:21:40 +0000 Subject: [PATCH 03/11] Address review: state policy, stop restating mechanics owned elsewhere The second review round found the same class of problem as the first: the policy pages paraphrased behavior that other files own (deprecated features, pre-release selection, the CI matrix, SECURITY.md), and each paraphrase drifted from the code. Trim them back to the commitments and link to the owning page instead: - versioning.md: pre-release selection described by reference to PEP 440 rather than a closed list; provisional examples given as examples; the SDK-API deprecation promise stated as policy (marked wherever Python can carry a marker, docstring plus migration guide otherwise); protocol deprecations defer per-connection behavior to deprecated.md and legacy-clients.md instead of enumerating it. - roadmap.md: the open items are "carried as expected failures until they land", without tier-scoring commentary. - DEPENDENCY_POLICY.md: floors "the suite exercises" cannot go false; versioning.md is the single authority on release kinds; a dependency's new major is decided in an issue like a new dependency; SECURITY.md is a reporting process, not response commitments. - RELEASE.md: the lowest-direct lock is never committed (it is written, in CI's checkout); name the no-final-release pre-release fallback. - CONTRIBUTING.md: the label is `needs maintainer`. No-Verification-Needed: doc-only change --- CONTRIBUTING.md | 2 +- DEPENDENCY_POLICY.md | 6 +++--- RELEASE.md | 7 ++++--- docs/roadmap.md | 2 +- docs/versioning.md | 12 ++++++------ 5 files changed, 15 insertions(+), 14 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 20001ea2f9..81481772a2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -48,7 +48,7 @@ Bug fixes for clear, reproducible issues are welcome—but still create an issue | [`help wanted`](https://github.com/modelcontextprotocol/python-sdk/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22) | Experienced contributors | Maintainers probably won't get to this | | [`ready for work`](https://github.com/modelcontextprotocol/python-sdk/issues?q=is%3Aopen+is%3Aissue+label%3A%22ready+for+work%22) | Maintainers | Triaged and ready for a maintainer to pick up | -Issues labeled `needs confirmation` or `needs maintainer action` are **not** ready for work—wait for maintainer input first. +Issues labeled `needs confirmation` or `needs maintainer` are **not** ready for work—wait for maintainer input first. Before starting, comment on the issue so we can assign it to you. This prevents duplicate effort. diff --git a/DEPENDENCY_POLICY.md b/DEPENDENCY_POLICY.md index ce9e6d4a1f..ddd4ef9406 100644 --- a/DEPENDENCY_POLICY.md +++ b/DEPENDENCY_POLICY.md @@ -13,9 +13,9 @@ A minimum version is raised only when the SDK starts relying on functionality, a fix, or an API that first appeared in that version. It is not raised because a dependency published a security advisory. The `>=` bound already lets — and expects — you to run the newest release your other constraints allow, so a higher floor would only shrink the set of environments the SDK installs into without changing what any correctly-updated environment resolves to. The SDK also does not add code to work around a vulnerability in a dependency; the fix belongs upstream and in your lockfile. ([Background](https://github.com/Kludex/uvicorn/discussions/2643) on this stance from another library that adopted it, and [python-sdk#1552](https://github.com/modelcontextprotocol/python-sdk/issues/1552).) -Every declared floor is exercised: CI runs the full test suite both against the locked dependency set and against a `lowest-direct` resolution, on every supported Python version, so a floor that has quietly become false fails the build rather than a user's install. +The floors are tested, not just declared: CI runs the test suite against a `lowest-direct` resolution as well as the locked set, on every supported Python version, so a floor the suite exercises cannot quietly become false. -Raising a floor within the same major version of a dependency is a minor-release change and is called out in the release notes; see the [versioning policy](https://py.sdk.modelcontextprotocol.io/versioning/). Adding a new required runtime dependency is a maintainer decision made in an issue before the pull request, not a side effect of a feature. +Raising a floor is a minor-release change, called out in the release notes; the [versioning policy](https://py.sdk.modelcontextprotocol.io/versioning/) is the authority on what may ship in which kind of release. Adding a new required runtime dependency, or moving an existing one to its next major version, is a maintainer decision made in an issue before the pull request, not a side effect of a feature. ## Automated updates @@ -23,4 +23,4 @@ Raising a floor within the same major version of a dependency is a minor-release ## Security in the SDK itself -Vulnerabilities in the SDK's own code — as opposed to its dependencies — follow the reporting process and response commitments in [SECURITY.md](https://github.com/modelcontextprotocol/python-sdk/blob/main/SECURITY.md). +Vulnerabilities in the SDK's own code — as opposed to its dependencies — follow the reporting process in [SECURITY.md](https://github.com/modelcontextprotocol/python-sdk/blob/main/SECURITY.md). diff --git a/RELEASE.md b/RELEASE.md index eb093917e9..0c2a6d4db3 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -12,7 +12,7 @@ move; this is the mechanics. to move just that package's locked version). The committed `uv.lock` is a normal, newest-allowed resolution; the `lowest-direct` resolution that proves the floors still work is applied only by its CI matrix leg at test - time and never written to the lock. + time and is never committed. ## Release lines @@ -111,8 +111,9 @@ hand for the same reason as above. Then ask someone to review the release. Pre-releases of the next version are cut from `main` with a PEP 440 pre-release tag: `aN` for alphas, later `bN`/`rcN` for betas and release candidates. The PEP 440 suffix is what keeps `pip install mcp` on the stable -version — installers only select a pre-release when it is requested explicitly (an -exact pin, a specifier that names a pre-release version, or `--pre`). +version — installers select a pre-release only when it is requested explicitly (an +exact pin, a specifier that names a pre-release version, or `--pre`) or when no +final release satisfies the requirement at all. 1. During a pre-release phase the README and docs pin the exact pre-release version, so update those examples first (grep the outgoing version — the diff --git a/docs/roadmap.md b/docs/roadmap.md index 1aac99428e..be35dfb83b 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -21,7 +21,7 @@ The 2026-07-28 revision moved some functionality out of the core protocol into n * **DPoP-bound access tokens** ([SEP-1932](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1932)) in the OAuth client. * **The workload-identity `jwt-bearer` grant** in the OAuth client. -None of these gates conformance today — extension scenarios are informational in the tier scoring — but each is a real gap for anyone who needs the feature, and they are the current queue. +None of these blocks a release — each is carried as an expected failure in that baseline until it lands — but each is a real gap for anyone who needs the feature, and together they are the current queue. ## Continuous work diff --git a/docs/versioning.md b/docs/versioning.md index 35075f2eeb..aee0a51b9c 100644 --- a/docs/versioning.md +++ b/docs/versioning.md @@ -10,7 +10,7 @@ Releases follow [Semantic Versioning](https://semver.org/) semantics, written in * **`X` (minor)** — new functionality and every non-breaking change. * **`Y` (patch)** — bug fixes only. * **The leading `2` (major)** — the only place a breaking change to the public API can land. -* **Pre-releases** are cut from `main` as `2.X.YaN` (alpha), `2.X.YbN` (beta), and `2.X.YrcN` (release candidate). Installers select a pre-release only when a requirement asks for one explicitly — an exact pin, a specifier that itself names a pre-release version (such as `mcp>=2.1.0b1`), or `--pre` — so an unpinned `pip install mcp` always lands on a stable release. +* **Pre-releases** are cut from `main` as `2.X.YaN` (alpha), `2.X.YbN` (beta), and `2.X.YrcN` (release candidate). Installers prefer final releases by default (PEP 440's [pre-release handling](https://peps.python.org/pep-0440/#handling-of-pre-releases)), so an unpinned `pip install mcp` stays on a stable release; you get a pre-release by asking for one, for example with an exact pin or `--pre`. `mcp` and its wire-types package [`mcp-types`](https://pypi.org/project/mcp-types/) release in lockstep at the same version: each `mcp` release requires exactly the matching `mcp-types` (`mcp-types==2.X.Y`). @@ -26,7 +26,7 @@ It does not cover names beginning with an underscore, modules and attributes tha Two labels mark APIs that sit outside the promise while they settle: -* **Provisional** — shipped and supported, but the signature or semantics may still change in a minor release. The middleware chain is the current example, and its documentation says so. +* **Provisional** — shipped and supported, but the signature or semantics may still change in a minor release. The middleware chain and the `Dispatcher` lifecycle are examples; each is labelled provisional in its own documentation. * **Experimental** — behind an explicit opt-in and expected to change; treat it as a preview. ## What counts as a breaking change @@ -43,7 +43,7 @@ These do not, and can ship in a minor release: * new functions, parameters with defaults, classes, fields, and enum members, * changes to provisional or experimental APIs, * new deprecation warnings, and the eventual removal of a protocol feature the specification has retired (see [Deprecations](#deprecations)), -* raising a dependency's minimum version when the SDK needs newer functionality, or dropping a Python version that upstream has ended support for — both called out in the release notes (the [dependency policy](https://github.com/modelcontextprotocol/python-sdk/blob/main/DEPENDENCY_POLICY.md) covers the first), +* raising a dependency's minimum version when the SDK needs newer functionality (see the [dependency policy](https://github.com/modelcontextprotocol/python-sdk/blob/main/DEPENDENCY_POLICY.md)), as long as the dependency's own changes do not reach you through the SDK's public API — if they would, the rules above apply — or dropping a Python version that upstream has ended support for; both are called out in the release notes, * bug fixes, including fixes that make the SDK match documented or specified behavior it should have had all along. When a fix is arguably both a bug fix and a behavior change, the deciding question is whether reasonable code written against the *documented* behavior breaks. If it does, the change is breaking. @@ -52,9 +52,9 @@ When a fix is arguably both a bug fix and a behavior change, the deciding questi There are two kinds, warned differently on purpose. -**SDK API deprecations** — a name or parameter this SDK is retiring. The API keeps working, marked with [`typing_extensions.deprecated`](https://typing-extensions.readthedocs.io/en/latest/#typing_extensions.deprecated), so static type checkers flag every call site and Python emits a `DeprecationWarning` at runtime. A deprecated API survives at least one minor release with its warning in place, and is removed only in a major version: something deprecated during 2.x is not removed before 3.0. +**SDK API deprecations** — a name or parameter this SDK is retiring. It is deprecated before it is removed: it keeps working for at least one minor release, marked wherever Python can carry a marker — callables and classes get [`typing_extensions.deprecated`](https://typing-extensions.readthedocs.io/en/latest/#typing_extensions.deprecated), which static type checkers flag and which warns at runtime; things that cannot carry one, such as module-level constants, are deprecated in their docstring and the migration guide — and it is removed only in a major version: something deprecated during 2.x is not removed before 3.0. -**Protocol deprecations** — a feature the MCP specification has retired (for example the SEP-2577 set in the 2026-07-28 revision). The SDK keeps implementing these through the specification's deprecation window, but what still works depends on the revision a connection negotiated: on a connection speaking an older revision they behave as before; on a 2026-07-28 connection a retired feature may have no wire support left at all (server-initiated sampling and roots have no back-channel to travel over, and `ping` no longer exists), so the call warns and then fails. Either way the call site warns with `MCPDeprecationWarning`, a `UserWarning` subclass, so the warning is visible by default rather than hidden the way `DeprecationWarning` is outside `__main__`. **[Deprecated features](deprecated.md)** lists every one, exactly what happens on each kind of connection, its replacement, and how to silence the warning when you genuinely serve older clients. +**Protocol deprecations** — a feature the MCP specification has retired (for example the SEP-2577 set in the 2026-07-28 revision). The SDK keeps implementing these through the specification's deprecation window, and deprecation warnings for them use `MCPDeprecationWarning`, a `UserWarning` subclass, so they show by default rather than being hidden the way `DeprecationWarning` is outside `__main__`. Whether a retired feature can still do anything on a given connection depends on the protocol revision that connection negotiated; **[Deprecated features](deprecated.md)** and **[Serving legacy clients](run/legacy-clients.md)** describe the behavior, the replacements, and how to silence the warning when you genuinely serve older clients. ## Supported release lines @@ -74,4 +74,4 @@ Python versions are supported from the version in the package's `requires-python * **Release notes** — every release publishes curated notes on [GitHub Releases](https://github.com/modelcontextprotocol/python-sdk/releases): highlights, anything known-incomplete, and a full change list. Pre-releases say what changed since the previous pre-release. * **The migration guide** — every breaking change between majors is documented in **[Migration Guide](migration.md)** with before-and-after code; a change is not merged for a major release without its entry. * **The `breaking change` label** — pull requests that make a breaking change carry it, so the set is queryable ahead of a major release. -* **Deprecation warnings** — as above, one release of warning at minimum before an SDK API is removed. +* **Deprecations** — as above, at least one minor release of deprecation before an SDK API is removed. From dfee3cb526e3435e7a043f0538edb2e4642bd52a Mon Sep 17 00:00:00 2001 From: Max Isbey <224885523+maxisbey@users.noreply.github.com> Date: Fri, 14 Aug 2026 16:53:03 +0000 Subject: [PATCH 04/11] Address review: SEP link, extras wording, taxonomy scope - roadmap.md: the SEP-2663 link pointed at a docs/seps/ path that 404s; SEPs live under seps/. Also "tracked as" rather than "exactly" for the baseline correspondence. - versioning.md: unpinned installs stay on stable "whenever one satisfies your requirement", which is the PEP 440 rule without a closed list. - DEPENDENCY_POLICY.md: extras hold add-on tooling; the transport stack and auth are base by design. The lowest-direct leg is described as what it does (tests floors continuously), not as a guarantee about every floor. - CONTRIBUTING.md: the taxonomy is the shared core; the repo also has workflow labels such as `needs maintainer`. No-Verification-Needed: doc-only change --- CONTRIBUTING.md | 2 +- DEPENDENCY_POLICY.md | 4 ++-- docs/roadmap.md | 4 ++-- docs/versioning.md | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 81481772a2..62e72784cb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -56,7 +56,7 @@ Before starting, comment on the issue so we can assign it to you. This prevents Every new issue gets a first look from a maintainer within two business days. That first look is the *triage*: it means labeling the issue and deciding whether it is valid and actionable, not fixing it. -The labels follow the shared [MCP SDK taxonomy](https://modelcontextprotocol.io/community/sdk-tiers#issue-triage-labels): one **type** (`bug`, `enhancement`, `question`), one **status** (`needs confirmation`, `needs repro`, `ready for work`, `good first issue`, `help wanted`), and — once actionable — one **priority**: +The core labels follow the shared [MCP SDK taxonomy](https://modelcontextprotocol.io/community/sdk-tiers#issue-triage-labels) (the repository also carries workflow labels of its own, such as `needs maintainer` and `needs decision`): one **type** (`bug`, `enhancement`, `question`), one **status** (`needs confirmation`, `needs repro`, `ready for work`, `good first issue`, `help wanted`), and — once actionable — one **priority**: | Label | Meaning | Commitment | |-------|---------|------------| diff --git a/DEPENDENCY_POLICY.md b/DEPENDENCY_POLICY.md index ddd4ef9406..11e8afa6d2 100644 --- a/DEPENDENCY_POLICY.md +++ b/DEPENDENCY_POLICY.md @@ -7,13 +7,13 @@ * **Floors, not pins.** Every runtime dependency is a `>=` lower bound, set to the oldest version that provides what the SDK uses. There are no upper bounds unless a dependency's next major version is known to break the SDK. * **The one exception is `mcp-types`.** The wire-types package is developed and released with `mcp` in lockstep, so `mcp` requires exactly its own version (`mcp-types==`). It is not an independent constraint on your environment; it is the other half of the SDK. * **Environment markers instead of parallel packages** — Python-version and platform differences (`python_version`, `sys_platform`) are expressed as markers on the requirement, so one wheel serves every supported environment. -* **Optional features are extras.** Anything only some users need lives behind an extra (`mcp[cli]`, `mcp[rich]`) rather than in the base requirement set. +* **Add-on tooling is an extra.** The command-line tooling and rich console output live behind extras (`mcp[cli]`, `mcp[rich]`); the client, the server, the HTTP transport stack, and auth support are all part of the base install by design. ## When a floor moves A minimum version is raised only when the SDK starts relying on functionality, a fix, or an API that first appeared in that version. It is not raised because a dependency published a security advisory. The `>=` bound already lets — and expects — you to run the newest release your other constraints allow, so a higher floor would only shrink the set of environments the SDK installs into without changing what any correctly-updated environment resolves to. The SDK also does not add code to work around a vulnerability in a dependency; the fix belongs upstream and in your lockfile. ([Background](https://github.com/Kludex/uvicorn/discussions/2643) on this stance from another library that adopted it, and [python-sdk#1552](https://github.com/modelcontextprotocol/python-sdk/issues/1552).) -The floors are tested, not just declared: CI runs the test suite against a `lowest-direct` resolution as well as the locked set, on every supported Python version, so a floor the suite exercises cannot quietly become false. +The floors are also tested continuously rather than only when they are set: CI runs the test suite against a `lowest-direct` resolution as well as the locked set, on every supported Python version. Raising a floor is a minor-release change, called out in the release notes; the [versioning policy](https://py.sdk.modelcontextprotocol.io/versioning/) is the authority on what may ship in which kind of release. Adding a new required runtime dependency, or moving an existing one to its next major version, is a maintainer decision made in an issue before the pull request, not a side effect of a feature. diff --git a/docs/roadmap.md b/docs/roadmap.md index be35dfb83b..9da21d1262 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -15,9 +15,9 @@ Open on that board: ## Extensions and optional client auth not yet implemented -The 2026-07-28 revision moved some functionality out of the core protocol into named extensions, and defines client-side auth mechanisms an SDK may support. The ones this SDK does not implement yet are exactly the entries in the conformance suite's expected-failures baseline, [`.github/actions/conformance/expected-failures.yml`](https://github.com/modelcontextprotocol/python-sdk/blob/main/.github/actions/conformance/expected-failures.yml) — that file is grouped by SEP and each entry is removed as the corresponding work lands, so it is the live burn-down list: +The 2026-07-28 revision moved some functionality out of the core protocol into named extensions, and defines client-side auth mechanisms an SDK may support. The ones this SDK does not implement yet are tracked as the entries in the conformance suite's expected-failures baseline, [`.github/actions/conformance/expected-failures.yml`](https://github.com/modelcontextprotocol/python-sdk/blob/main/.github/actions/conformance/expected-failures.yml) — that file is grouped by SEP and each entry is removed as the corresponding work lands, so it is the live burn-down list: -* **Tasks extension** (`io.modelcontextprotocol/tasks`, [SEP-2663](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/docs/seps/2663-tasks-extension.md)) — deferred at 2.0 because the 2026-07-28 design is wire-incompatible with the earlier in-core Tasks; tracked in [#2806](https://github.com/modelcontextprotocol/python-sdk/issues/2806). +* **Tasks extension** (`io.modelcontextprotocol/tasks`, [SEP-2663](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/2663-tasks-extension.md)) — deferred at 2.0 because the 2026-07-28 design is wire-incompatible with the earlier in-core Tasks; tracked in [#2806](https://github.com/modelcontextprotocol/python-sdk/issues/2806). * **DPoP-bound access tokens** ([SEP-1932](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1932)) in the OAuth client. * **The workload-identity `jwt-bearer` grant** in the OAuth client. diff --git a/docs/versioning.md b/docs/versioning.md index aee0a51b9c..400a715dea 100644 --- a/docs/versioning.md +++ b/docs/versioning.md @@ -10,7 +10,7 @@ Releases follow [Semantic Versioning](https://semver.org/) semantics, written in * **`X` (minor)** — new functionality and every non-breaking change. * **`Y` (patch)** — bug fixes only. * **The leading `2` (major)** — the only place a breaking change to the public API can land. -* **Pre-releases** are cut from `main` as `2.X.YaN` (alpha), `2.X.YbN` (beta), and `2.X.YrcN` (release candidate). Installers prefer final releases by default (PEP 440's [pre-release handling](https://peps.python.org/pep-0440/#handling-of-pre-releases)), so an unpinned `pip install mcp` stays on a stable release; you get a pre-release by asking for one, for example with an exact pin or `--pre`. +* **Pre-releases** are cut from `main` as `2.X.YaN` (alpha), `2.X.YbN` (beta), and `2.X.YrcN` (release candidate). Installers prefer final releases by default (PEP 440's [pre-release handling](https://peps.python.org/pep-0440/#handling-of-pre-releases)), so an unpinned `pip install mcp` stays on a stable release whenever one satisfies your requirement; you get a pre-release by asking for one, for example with an exact pin or `--pre`. `mcp` and its wire-types package [`mcp-types`](https://pypi.org/project/mcp-types/) release in lockstep at the same version: each `mcp` release requires exactly the matching `mcp-types` (`mcp-types==2.X.Y`). From 8f6ededda9acd20e39962267a0f808ce744a40b8 Mon Sep 17 00:00:00 2001 From: Max Isbey <224885523+maxisbey@users.noreply.github.com> Date: Sun, 16 Aug 2026 11:31:43 +0000 Subject: [PATCH 05/11] Trim the versioning policy to its commitments Cut docs/versioning.md to roughly half (77 -> 35 lines): the scheme, the public-API boundary, the breaking / minor-eligible split, the two deprecation channels, and the support-and-announcements paragraph stay; the elaboration and the pointers already carried by other pages go. Same commitments, less surface. roadmap.md's deep link follows the renamed heading. No-Verification-Needed: doc-only change --- docs/roadmap.md | 2 +- docs/versioning.md | 72 ++++++++++------------------------------------ 2 files changed, 16 insertions(+), 58 deletions(-) diff --git a/docs/roadmap.md b/docs/roadmap.md index 9da21d1262..f865cb2d78 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -31,4 +31,4 @@ None of these blocks a release — each is carried as an expected failure in tha ## The previous major -`v1.x` is a maintenance line: critical bug fixes and security fixes only, no new features. Its documentation stays available at [/v1/](https://py.sdk.modelcontextprotocol.io/v1/), the support terms are in [Versioning and support policy](versioning.md#supported-release-lines), and the path off it is the **[Migration Guide](migration.md)**. +`v1.x` is a maintenance line: critical bug fixes and security fixes only, no new features. Its documentation stays available at [/v1/](https://py.sdk.modelcontextprotocol.io/v1/), the support terms are in [Versioning and support policy](versioning.md#support-and-announcements), and the path off it is the **[Migration Guide](migration.md)**. diff --git a/docs/versioning.md b/docs/versioning.md index 400a715dea..9f9a4d0da7 100644 --- a/docs/versioning.md +++ b/docs/versioning.md @@ -1,77 +1,35 @@ # Versioning and support policy -This page states what a version number of the `mcp` package promises you: which changes can arrive in a minor release, which are held for the next major, how deprecations are announced, and how long each release line is supported. +What a version number of `mcp` promises: which changes can arrive in a minor release, which wait for a major, how deprecations are announced, and which release lines are supported. ## The version number -Releases follow [Semantic Versioning](https://semver.org/) semantics, written in [PEP 440](https://peps.python.org/pep-0440/) syntax: +[Semantic Versioning](https://semver.org/) semantics in [PEP 440](https://peps.python.org/pep-0440/) syntax, taken from the git tag: in `2.X.Y`, **X** (minor) carries new functionality and every non-breaking change, **Y** (patch) carries bug fixes only, and a breaking change to the public API lands only in a new **major**. Pre-releases are cut from `main` as `aN`/`bN`/`rcN`; installers prefer final releases by default, so an unpinned `pip install mcp` stays on a stable release whenever one satisfies your requirement. `mcp` and its wire-types package `mcp-types` release in lockstep, each `mcp` requiring exactly the matching `mcp-types`. -* **`2.X.Y`** — the version comes from the git tag; there is no version field to edit. -* **`X` (minor)** — new functionality and every non-breaking change. -* **`Y` (patch)** — bug fixes only. -* **The leading `2` (major)** — the only place a breaking change to the public API can land. -* **Pre-releases** are cut from `main` as `2.X.YaN` (alpha), `2.X.YbN` (beta), and `2.X.YrcN` (release candidate). Installers prefer final releases by default (PEP 440's [pre-release handling](https://peps.python.org/pep-0440/#handling-of-pre-releases)), so an unpinned `pip install mcp` stays on a stable release whenever one satisfies your requirement; you get a pre-release by asking for one, for example with an exact pin or `--pre`. +## The public API -`mcp` and its wire-types package [`mcp-types`](https://pypi.org/project/mcp-types/) release in lockstep at the same version: each `mcp` release requires exactly the matching `mcp-types` (`mcp-types==2.X.Y`). +The promise covers every name exported by `mcp` and `mcp_types` (their `__all__`), the import paths, signatures, and behavior documented on this site and in the [API Reference](api/mcp/index.md). It does not cover underscore-prefixed names, undocumented modules, or the wording of log lines, warnings, and exception messages (their types and documented raise conditions are covered). APIs labelled **provisional** (for example the middleware chain) may still change in a minor release; **experimental** APIs are opt-in previews. -## What the public API is +## Breaking and non-breaking changes -The compatibility promise covers the public API: - -* every name exported by `mcp` (its `__all__`) and by `mcp_types`, -* the import paths, classes, functions, and parameters documented on this site and in the [API Reference](api/mcp/index.md), -* documented behavior of those APIs. - -It does not cover names beginning with an underscore, modules and attributes that appear nowhere in the documentation, or the exact text of log lines, warnings, and exception messages (their *type* and the documented conditions that raise them are covered; their wording is not). Depending on one of those is depending on an implementation detail that may change in any release. - -Two labels mark APIs that sit outside the promise while they settle: - -* **Provisional** — shipped and supported, but the signature or semantics may still change in a minor release. The middleware chain and the `Dispatcher` lifecycle are examples; each is labelled provisional in its own documentation. -* **Experimental** — behind an explicit opt-in and expected to change; treat it as a preview. - -## What counts as a breaking change - -These wait for the next major version: +Held for the next major: * removing or renaming a public name, -* changing a signature so that a call that worked stops working (a removed or reordered parameter, a newly required argument, a narrowed accepted type), -* changing a return type, a raised exception type, or documented behavior in a way existing callers would notice, +* changing a signature, return type, raised exception type, or documented behavior so that working code stops working, * removing a documented import path, extra, or CLI command. -These do not, and can ship in a minor release: +Allowed in a minor: -* new functions, parameters with defaults, classes, fields, and enum members, +* additions — functions, defaulted parameters, classes, fields, enum members, * changes to provisional or experimental APIs, -* new deprecation warnings, and the eventual removal of a protocol feature the specification has retired (see [Deprecations](#deprecations)), -* raising a dependency's minimum version when the SDK needs newer functionality (see the [dependency policy](https://github.com/modelcontextprotocol/python-sdk/blob/main/DEPENDENCY_POLICY.md)), as long as the dependency's own changes do not reach you through the SDK's public API — if they would, the rules above apply — or dropping a Python version that upstream has ended support for; both are called out in the release notes, -* bug fixes, including fixes that make the SDK match documented or specified behavior it should have had all along. - -When a fix is arguably both a bug fix and a behavior change, the deciding question is whether reasonable code written against the *documented* behavior breaks. If it does, the change is breaking. +* new deprecation warnings, and the eventual removal of protocol features the specification has retired, +* raising a dependency floor the SDK needs (see the [dependency policy](https://github.com/modelcontextprotocol/python-sdk/blob/main/DEPENDENCY_POLICY.md)) when the dependency's changes don't reach you through the SDK's API, or dropping a Python version after its upstream end-of-life — both called out in the release notes, +* bug fixes, including ones that make the SDK match its documented or specified behavior. ## Deprecations -There are two kinds, warned differently on purpose. - -**SDK API deprecations** — a name or parameter this SDK is retiring. It is deprecated before it is removed: it keeps working for at least one minor release, marked wherever Python can carry a marker — callables and classes get [`typing_extensions.deprecated`](https://typing-extensions.readthedocs.io/en/latest/#typing_extensions.deprecated), which static type checkers flag and which warns at runtime; things that cannot carry one, such as module-level constants, are deprecated in their docstring and the migration guide — and it is removed only in a major version: something deprecated during 2.x is not removed before 3.0. - -**Protocol deprecations** — a feature the MCP specification has retired (for example the SEP-2577 set in the 2026-07-28 revision). The SDK keeps implementing these through the specification's deprecation window, and deprecation warnings for them use `MCPDeprecationWarning`, a `UserWarning` subclass, so they show by default rather than being hidden the way `DeprecationWarning` is outside `__main__`. Whether a retired feature can still do anything on a given connection depends on the protocol revision that connection negotiated; **[Deprecated features](deprecated.md)** and **[Serving legacy clients](run/legacy-clients.md)** describe the behavior, the replacements, and how to silence the warning when you genuinely serve older clients. - -## Supported release lines - -Two lines are maintained, and only the newest release of a line receives fixes: - -| Line | Branch | Receives | -| --- | --- | --- | -| 2.x — current stable | `main` | bug fixes, security fixes, new features | -| 1.x — maintenance | [`v1.x`](https://github.com/modelcontextprotocol/python-sdk/tree/v1.x) | critical bug fixes and security fixes | - -Older 1.x releases and all pre-releases are unsupported. The security-specific version of this table, and how to report a vulnerability, is in [SECURITY.md](https://github.com/modelcontextprotocol/python-sdk/blob/main/SECURITY.md). Still on 1.x? Its documentation is at [/v1/](https://py.sdk.modelcontextprotocol.io/v1/), and a `<2` upper bound on your `mcp` requirement keeps an unpinned resolve on that line until you migrate. - -Python versions are supported from the version in the package's `requires-python` up to the newest CPython release the test suite runs against; support for a Python version ends only after that version's upstream end-of-life. +**SDK APIs** are deprecated before removal: they keep working for at least one minor release, marked with [`typing_extensions.deprecated`](https://typing-extensions.readthedocs.io/en/latest/#typing_extensions.deprecated) wherever Python can carry the marker (docstring and migration guide otherwise), and are removed only in a major. **Protocol features** the specification retires keep their implementation through the spec's deprecation window and warn with `MCPDeprecationWarning`, a `UserWarning` subclass that shows by default; what still functions depends on the revision a connection negotiated — see [Deprecated features](deprecated.md). -## Where changes are announced +## Support and announcements -* **Release notes** — every release publishes curated notes on [GitHub Releases](https://github.com/modelcontextprotocol/python-sdk/releases): highlights, anything known-incomplete, and a full change list. Pre-releases say what changed since the previous pre-release. -* **The migration guide** — every breaking change between majors is documented in **[Migration Guide](migration.md)** with before-and-after code; a change is not merged for a major release without its entry. -* **The `breaking change` label** — pull requests that make a breaking change carry it, so the set is queryable ahead of a major release. -* **Deprecations** — as above, at least one minor release of deprecation before an SDK API is removed. +Two lines are maintained and only the newest release of each receives fixes: **2.x** (`main`) gets bug fixes, security fixes, and features; **1.x** ([`v1.x`](https://github.com/modelcontextprotocol/python-sdk/tree/v1.x)) gets critical bug fixes and security fixes. [SECURITY.md](https://github.com/modelcontextprotocol/python-sdk/blob/main/SECURITY.md) has the reporting process. Every release publishes notes on [GitHub Releases](https://github.com/modelcontextprotocol/python-sdk/releases); every breaking change between majors is documented in the [Migration Guide](migration.md) before it merges; and pull requests that make one carry the `breaking change` label. From 07eb1a45a7b211e2ad8ddad859bc79dbc7d210af Mon Sep 17 00:00:00 2001 From: Max Isbey <224885523+maxisbey@users.noreply.github.com> Date: Sun, 16 Aug 2026 12:00:55 +0000 Subject: [PATCH 06/11] Trim the roadmap and dependency policy to their commitments Same treatment as the versioning page: docs/roadmap.md keeps the 2026-07-28 board, its open item, the not-yet-implemented extensions, and the v1.x stance, and drops the descriptive "continuous work" section; DEPENDENCY_POLICY.md keeps how requirements are declared, when a floor moves, and the automation, and drops the packaging asides and the CI description. Both land near the size of the equivalent pages in the other Tier 1 SDKs. No-Verification-Needed: doc-only change --- DEPENDENCY_POLICY.md | 19 ++++--------------- docs/roadmap.md | 27 +++++++-------------------- 2 files changed, 11 insertions(+), 35 deletions(-) diff --git a/DEPENDENCY_POLICY.md b/DEPENDENCY_POLICY.md index 11e8afa6d2..a2864e7f95 100644 --- a/DEPENDENCY_POLICY.md +++ b/DEPENDENCY_POLICY.md @@ -1,26 +1,15 @@ # Dependency Policy -`mcp` is a library that lives inside other people's environments, so its dependency requirements are chosen to constrain your resolver as little as possible while still describing what the SDK actually needs. +`mcp` is a library that lives inside other people's environments, so its requirements are chosen to constrain your resolver as little as possible while still describing what the SDK needs. ## How requirements are declared -* **Floors, not pins.** Every runtime dependency is a `>=` lower bound, set to the oldest version that provides what the SDK uses. There are no upper bounds unless a dependency's next major version is known to break the SDK. -* **The one exception is `mcp-types`.** The wire-types package is developed and released with `mcp` in lockstep, so `mcp` requires exactly its own version (`mcp-types==`). It is not an independent constraint on your environment; it is the other half of the SDK. -* **Environment markers instead of parallel packages** — Python-version and platform differences (`python_version`, `sys_platform`) are expressed as markers on the requirement, so one wheel serves every supported environment. -* **Add-on tooling is an extra.** The command-line tooling and rich console output live behind extras (`mcp[cli]`, `mcp[rich]`); the client, the server, the HTTP transport stack, and auth support are all part of the base install by design. +Every runtime dependency is a `>=` floor set to the oldest version that provides what the SDK uses, with no upper bound unless a dependency's next major is known to break the SDK. The one exception is `mcp-types`, the wire-types package released in lockstep with `mcp`: each `mcp` release requires exactly its own version of it, so it is the other half of the SDK rather than an independent constraint. ## When a floor moves -A minimum version is raised only when the SDK starts relying on functionality, a fix, or an API that first appeared in that version. It is not raised because a dependency published a security advisory. The `>=` bound already lets — and expects — you to run the newest release your other constraints allow, so a higher floor would only shrink the set of environments the SDK installs into without changing what any correctly-updated environment resolves to. The SDK also does not add code to work around a vulnerability in a dependency; the fix belongs upstream and in your lockfile. ([Background](https://github.com/Kludex/uvicorn/discussions/2643) on this stance from another library that adopted it, and [python-sdk#1552](https://github.com/modelcontextprotocol/python-sdk/issues/1552).) - -The floors are also tested continuously rather than only when they are set: CI runs the test suite against a `lowest-direct` resolution as well as the locked set, on every supported Python version. - -Raising a floor is a minor-release change, called out in the release notes; the [versioning policy](https://py.sdk.modelcontextprotocol.io/versioning/) is the authority on what may ship in which kind of release. Adding a new required runtime dependency, or moving an existing one to its next major version, is a maintainer decision made in an issue before the pull request, not a side effect of a feature. +A floor is raised only when the SDK starts relying on something that first appeared in that version — not because the dependency published a security advisory. The `>=` bound already lets, and expects, you to run the newest release your other constraints allow, so a higher floor would only shrink the environments the SDK installs into; nor does the SDK add code to work around a dependency's vulnerability, since the fix belongs upstream and in your lockfile ([background](https://github.com/Kludex/uvicorn/discussions/2643), [python-sdk#1552](https://github.com/modelcontextprotocol/python-sdk/issues/1552)). Adding a new runtime dependency, or moving one to its next major version, is decided in an issue before the pull request. Which of these may ship in a minor release is set by the [versioning policy](https://py.sdk.modelcontextprotocol.io/versioning/); floor raises are called out in the release notes. ## Automated updates -[Dependabot](https://github.com/modelcontextprotocol/python-sdk/blob/main/.github/dependabot.yml) opens monthly, grouped pull requests for the `uv` lockfile and for GitHub Actions, with a 14-day cooldown on newly published versions. These refresh the versions the SDK is developed and tested against (`uv.lock`); they never change the requirements published to PyPI, which move only under the rules above. - -## Security in the SDK itself - -Vulnerabilities in the SDK's own code — as opposed to its dependencies — follow the reporting process in [SECURITY.md](https://github.com/modelcontextprotocol/python-sdk/blob/main/SECURITY.md). +[Dependabot](https://github.com/modelcontextprotocol/python-sdk/blob/main/.github/dependabot.yml) opens monthly, grouped pull requests for the `uv` lockfile and for GitHub Actions. These refresh the versions the SDK is developed and tested against; the requirements published to PyPI move only under the rules above. diff --git a/docs/roadmap.md b/docs/roadmap.md index f865cb2d78..7dffccd7a3 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -1,34 +1,21 @@ # Roadmap -The SDK's job is to implement the MCP specification, so its roadmap is organized by specification revision: one GitHub project board per revision, each item an issue or pull request you can follow. This page names the board that is current, what remains open on it, and the maintenance stance for the previous major. +The SDK's work is organized by MCP specification revision, with one GitHub project board per revision; each item is an issue or pull request you can follow. -## The 2026-07-28 revision — shipped, with follow-ups +## The 2026-07-28 revision -v2 implements the [2026-07-28 specification](https://modelcontextprotocol.io/specification/2026-07-28) (and negotiates back to every earlier revision — see [Protocol versions](protocol-versions.md)); **[What's new in v2](whats-new.md)** is the tour of what that meant for the SDK. +v2 implements the [2026-07-28 specification](https://modelcontextprotocol.io/specification/2026-07-28) and negotiates back to every earlier revision. Board: **[python-sdk · 2026-07-28 spec](https://github.com/orgs/modelcontextprotocol/projects/42)** (tracking issue [#2891](https://github.com/modelcontextprotocol/python-sdk/issues/2891)); the cross-SDK view is [2026-07-28 Spec Implementation](https://github.com/orgs/modelcontextprotocol/projects/41). Still open there: the capabilities API and `server/discover` handler ([#2896](https://github.com/modelcontextprotocol/python-sdk/issues/2896)). -* Board: **[python-sdk · 2026-07-28 spec](https://github.com/orgs/modelcontextprotocol/projects/42)**, tracking issue [#2891](https://github.com/modelcontextprotocol/python-sdk/issues/2891). -* Cross-SDK view: [2026-07-28 Spec Implementation](https://github.com/orgs/modelcontextprotocol/projects/41) tracks the same revision across all official SDKs. +## Not yet implemented -Open on that board: - -* **Capabilities API and the `server/discover` handler** — the last core item still in progress ([#2896](https://github.com/modelcontextprotocol/python-sdk/issues/2896)). - -## Extensions and optional client auth not yet implemented - -The 2026-07-28 revision moved some functionality out of the core protocol into named extensions, and defines client-side auth mechanisms an SDK may support. The ones this SDK does not implement yet are tracked as the entries in the conformance suite's expected-failures baseline, [`.github/actions/conformance/expected-failures.yml`](https://github.com/modelcontextprotocol/python-sdk/blob/main/.github/actions/conformance/expected-failures.yml) — that file is grouped by SEP and each entry is removed as the corresponding work lands, so it is the live burn-down list: +The extensions and optional client-auth mechanisms this SDK does not implement yet are tracked as the entries in the conformance suite's expected-failures baseline, [`.github/actions/conformance/expected-failures.yml`](https://github.com/modelcontextprotocol/python-sdk/blob/main/.github/actions/conformance/expected-failures.yml), which burns down as each lands: * **Tasks extension** (`io.modelcontextprotocol/tasks`, [SEP-2663](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/2663-tasks-extension.md)) — deferred at 2.0 because the 2026-07-28 design is wire-incompatible with the earlier in-core Tasks; tracked in [#2806](https://github.com/modelcontextprotocol/python-sdk/issues/2806). * **DPoP-bound access tokens** ([SEP-1932](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1932)) in the OAuth client. * **The workload-identity `jwt-bearer` grant** in the OAuth client. -None of these blocks a release — each is carried as an expected failure in that baseline until it lands — but each is a real gap for anyone who needs the feature, and together they are the current queue. - -## Continuous work - -* **Conformance** — every pull request and every push to `main` runs the [conformance suite](https://github.com/modelcontextprotocol/conformance) as both server and client, against the released revisions and against the 2026-07-28 wire specifically; adopting each new harness release and reconciling its baseline is routine. -* **The next specification revision** — draft-only wire changes are tried behind the draft protocol version before they are final, and land in a release once the revision ships; the SDK targets releasing support alongside each new specification version. -* **Everything else** — the [issue tracker](https://github.com/modelcontextprotocol/python-sdk/issues) is the source of truth for bugs and smaller features; `P0`–`P3` labels carry priority. +Everything else — bugs and smaller features — lives in the [issue tracker](https://github.com/modelcontextprotocol/python-sdk/issues), prioritized `P0`–`P3`. The SDK aims to release support for each new specification revision alongside that revision. ## The previous major -`v1.x` is a maintenance line: critical bug fixes and security fixes only, no new features. Its documentation stays available at [/v1/](https://py.sdk.modelcontextprotocol.io/v1/), the support terms are in [Versioning and support policy](versioning.md#support-and-announcements), and the path off it is the **[Migration Guide](migration.md)**. +`v1.x` is a maintenance line: critical bug fixes and security fixes only. Support terms are in [Versioning and support policy](versioning.md#support-and-announcements); the path off it is the **[Migration Guide](migration.md)**. From 429e98cfd8a8e10fd706f856f8e4ec89da59f9d0 Mon Sep 17 00:00:00 2001 From: Max Isbey <224885523+maxisbey@users.noreply.github.com> Date: Sun, 16 Aug 2026 12:11:04 +0000 Subject: [PATCH 07/11] Move the versioning policy and roadmap to the repository root Publish them as VERSIONING.md and ROADMAP.md, matching the v1.x branch and the other SDKs, instead of as docs-site pages: no nav entry, no docs build surface. Their links into the docs become absolute site URLs, DEPENDENCY_POLICY.md and ROADMAP.md link the sibling file, and docs/index.md gains a one-line pointer to both. No-Verification-Needed: doc-only change --- DEPENDENCY_POLICY.md | 2 +- docs/roadmap.md => ROADMAP.md | 4 ++-- docs/versioning.md => VERSIONING.md | 8 ++++---- docs/index.md | 1 + mkdocs.yml | 3 --- 5 files changed, 8 insertions(+), 10 deletions(-) rename docs/roadmap.md => ROADMAP.md (85%) rename docs/versioning.md => VERSIONING.md (74%) diff --git a/DEPENDENCY_POLICY.md b/DEPENDENCY_POLICY.md index a2864e7f95..0ec2c2ac90 100644 --- a/DEPENDENCY_POLICY.md +++ b/DEPENDENCY_POLICY.md @@ -8,7 +8,7 @@ Every runtime dependency is a `>=` floor set to the oldest version that provides ## When a floor moves -A floor is raised only when the SDK starts relying on something that first appeared in that version — not because the dependency published a security advisory. The `>=` bound already lets, and expects, you to run the newest release your other constraints allow, so a higher floor would only shrink the environments the SDK installs into; nor does the SDK add code to work around a dependency's vulnerability, since the fix belongs upstream and in your lockfile ([background](https://github.com/Kludex/uvicorn/discussions/2643), [python-sdk#1552](https://github.com/modelcontextprotocol/python-sdk/issues/1552)). Adding a new runtime dependency, or moving one to its next major version, is decided in an issue before the pull request. Which of these may ship in a minor release is set by the [versioning policy](https://py.sdk.modelcontextprotocol.io/versioning/); floor raises are called out in the release notes. +A floor is raised only when the SDK starts relying on something that first appeared in that version — not because the dependency published a security advisory. The `>=` bound already lets, and expects, you to run the newest release your other constraints allow, so a higher floor would only shrink the environments the SDK installs into; nor does the SDK add code to work around a dependency's vulnerability, since the fix belongs upstream and in your lockfile ([background](https://github.com/Kludex/uvicorn/discussions/2643), [python-sdk#1552](https://github.com/modelcontextprotocol/python-sdk/issues/1552)). Adding a new runtime dependency, or moving one to its next major version, is decided in an issue before the pull request. Which of these may ship in a minor release is set by the [versioning policy](VERSIONING.md); floor raises are called out in the release notes. ## Automated updates diff --git a/docs/roadmap.md b/ROADMAP.md similarity index 85% rename from docs/roadmap.md rename to ROADMAP.md index 7dffccd7a3..8a2839130d 100644 --- a/docs/roadmap.md +++ b/ROADMAP.md @@ -8,7 +8,7 @@ v2 implements the [2026-07-28 specification](https://modelcontextprotocol.io/spe ## Not yet implemented -The extensions and optional client-auth mechanisms this SDK does not implement yet are tracked as the entries in the conformance suite's expected-failures baseline, [`.github/actions/conformance/expected-failures.yml`](https://github.com/modelcontextprotocol/python-sdk/blob/main/.github/actions/conformance/expected-failures.yml), which burns down as each lands: +The extensions and optional client-auth mechanisms this SDK does not implement yet are tracked as the entries in the conformance suite's expected-failures baseline, [`.github/actions/conformance/expected-failures.yml`](.github/actions/conformance/expected-failures.yml), which burns down as each lands: * **Tasks extension** (`io.modelcontextprotocol/tasks`, [SEP-2663](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/2663-tasks-extension.md)) — deferred at 2.0 because the 2026-07-28 design is wire-incompatible with the earlier in-core Tasks; tracked in [#2806](https://github.com/modelcontextprotocol/python-sdk/issues/2806). * **DPoP-bound access tokens** ([SEP-1932](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1932)) in the OAuth client. @@ -18,4 +18,4 @@ Everything else — bugs and smaller features — lives in the [issue tracker](h ## The previous major -`v1.x` is a maintenance line: critical bug fixes and security fixes only. Support terms are in [Versioning and support policy](versioning.md#support-and-announcements); the path off it is the **[Migration Guide](migration.md)**. +`v1.x` is a maintenance line: critical bug fixes and security fixes only. Support terms are in [Versioning and support policy](VERSIONING.md#support-and-announcements); the path off it is the **[Migration Guide](https://py.sdk.modelcontextprotocol.io/migration/)**. diff --git a/docs/versioning.md b/VERSIONING.md similarity index 74% rename from docs/versioning.md rename to VERSIONING.md index 9f9a4d0da7..53d17300e8 100644 --- a/docs/versioning.md +++ b/VERSIONING.md @@ -8,7 +8,7 @@ What a version number of `mcp` promises: which changes can arrive in a minor rel ## The public API -The promise covers every name exported by `mcp` and `mcp_types` (their `__all__`), the import paths, signatures, and behavior documented on this site and in the [API Reference](api/mcp/index.md). It does not cover underscore-prefixed names, undocumented modules, or the wording of log lines, warnings, and exception messages (their types and documented raise conditions are covered). APIs labelled **provisional** (for example the middleware chain) may still change in a minor release; **experimental** APIs are opt-in previews. +The promise covers every name exported by `mcp` and `mcp_types` (their `__all__`), the import paths, signatures, and behavior documented on the [documentation site](https://py.sdk.modelcontextprotocol.io/) and in its [API Reference](https://py.sdk.modelcontextprotocol.io/api/mcp/). It does not cover underscore-prefixed names, undocumented modules, or the wording of log lines, warnings, and exception messages (their types and documented raise conditions are covered). APIs labelled **provisional** (for example the middleware chain) may still change in a minor release; **experimental** APIs are opt-in previews. ## Breaking and non-breaking changes @@ -23,13 +23,13 @@ Allowed in a minor: * additions — functions, defaulted parameters, classes, fields, enum members, * changes to provisional or experimental APIs, * new deprecation warnings, and the eventual removal of protocol features the specification has retired, -* raising a dependency floor the SDK needs (see the [dependency policy](https://github.com/modelcontextprotocol/python-sdk/blob/main/DEPENDENCY_POLICY.md)) when the dependency's changes don't reach you through the SDK's API, or dropping a Python version after its upstream end-of-life — both called out in the release notes, +* raising a dependency floor the SDK needs (see the [dependency policy](DEPENDENCY_POLICY.md)) when the dependency's changes don't reach you through the SDK's API, or dropping a Python version after its upstream end-of-life — both called out in the release notes, * bug fixes, including ones that make the SDK match its documented or specified behavior. ## Deprecations -**SDK APIs** are deprecated before removal: they keep working for at least one minor release, marked with [`typing_extensions.deprecated`](https://typing-extensions.readthedocs.io/en/latest/#typing_extensions.deprecated) wherever Python can carry the marker (docstring and migration guide otherwise), and are removed only in a major. **Protocol features** the specification retires keep their implementation through the spec's deprecation window and warn with `MCPDeprecationWarning`, a `UserWarning` subclass that shows by default; what still functions depends on the revision a connection negotiated — see [Deprecated features](deprecated.md). +**SDK APIs** are deprecated before removal: they keep working for at least one minor release, marked with [`typing_extensions.deprecated`](https://typing-extensions.readthedocs.io/en/latest/#typing_extensions.deprecated) wherever Python can carry the marker (docstring and migration guide otherwise), and are removed only in a major. **Protocol features** the specification retires keep their implementation through the spec's deprecation window and warn with `MCPDeprecationWarning`, a `UserWarning` subclass that shows by default; what still functions depends on the revision a connection negotiated — see [Deprecated features](https://py.sdk.modelcontextprotocol.io/deprecated/). ## Support and announcements -Two lines are maintained and only the newest release of each receives fixes: **2.x** (`main`) gets bug fixes, security fixes, and features; **1.x** ([`v1.x`](https://github.com/modelcontextprotocol/python-sdk/tree/v1.x)) gets critical bug fixes and security fixes. [SECURITY.md](https://github.com/modelcontextprotocol/python-sdk/blob/main/SECURITY.md) has the reporting process. Every release publishes notes on [GitHub Releases](https://github.com/modelcontextprotocol/python-sdk/releases); every breaking change between majors is documented in the [Migration Guide](migration.md) before it merges; and pull requests that make one carry the `breaking change` label. +Two lines are maintained and only the newest release of each receives fixes: **2.x** (`main`) gets bug fixes, security fixes, and features; **1.x** ([`v1.x`](https://github.com/modelcontextprotocol/python-sdk/tree/v1.x)) gets critical bug fixes and security fixes. [SECURITY.md](https://github.com/modelcontextprotocol/python-sdk/blob/main/SECURITY.md) has the reporting process. Every release publishes notes on [GitHub Releases](https://github.com/modelcontextprotocol/python-sdk/releases); every breaking change between majors is documented in the [Migration Guide](https://py.sdk.modelcontextprotocol.io/migration/) before it merges; and pull requests that make one carry the `breaking change` label. diff --git a/docs/index.md b/docs/index.md index 3d10fc9bca..fbf5c13773 100644 --- a/docs/index.md +++ b/docs/index.md @@ -90,6 +90,7 @@ You wrote two Python functions with type hints and a docstring. The SDK does the * Already have a FastAPI or Starlette app? **[Add to an existing app](run/asgi.md)** mounts an MCP server inside it. * Hunting an exact error message? **[Troubleshooting](troubleshooting.md)** is keyed by the verbatim text. * Wondering what changed in v2? **[What's new in v2](whats-new.md)** is the five-minute tour. +* What a version number promises, and what is coming: **[Versioning and support policy](https://github.com/modelcontextprotocol/python-sdk/blob/main/VERSIONING.md)** and the **[Roadmap](https://github.com/modelcontextprotocol/python-sdk/blob/main/ROADMAP.md)**. * Migrating from v1? Start with the **[Migration Guide](migration.md)**. * Hunting for an exact signature? The **[API Reference](api/mcp/index.md)** is generated from the source. * Reading with an LLM? This documentation is also published in the [llms.txt](https://llmstxt.org/) format: diff --git a/mkdocs.yml b/mkdocs.yml index 8a3cc4ab82..06b293f876 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -69,9 +69,6 @@ nav: - MCP Apps: advanced/apps.md - Troubleshooting: troubleshooting.md - Migration Guide: migration.md - - About: - - Versioning and support policy: versioning.md - - Roadmap: roadmap.md - API Reference: api/ theme: From bc5bfe8ee6b15fc0b3ad51b32845809ba9255ee7 Mon Sep 17 00:00:00 2001 From: Max Isbey <224885523+maxisbey@users.noreply.github.com> Date: Sun, 16 Aug 2026 12:16:36 +0000 Subject: [PATCH 08/11] Drop the docs index pointer to the root policy files No-Verification-Needed: doc-only change --- docs/index.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/index.md b/docs/index.md index fbf5c13773..3d10fc9bca 100644 --- a/docs/index.md +++ b/docs/index.md @@ -90,7 +90,6 @@ You wrote two Python functions with type hints and a docstring. The SDK does the * Already have a FastAPI or Starlette app? **[Add to an existing app](run/asgi.md)** mounts an MCP server inside it. * Hunting an exact error message? **[Troubleshooting](troubleshooting.md)** is keyed by the verbatim text. * Wondering what changed in v2? **[What's new in v2](whats-new.md)** is the five-minute tour. -* What a version number promises, and what is coming: **[Versioning and support policy](https://github.com/modelcontextprotocol/python-sdk/blob/main/VERSIONING.md)** and the **[Roadmap](https://github.com/modelcontextprotocol/python-sdk/blob/main/ROADMAP.md)**. * Migrating from v1? Start with the **[Migration Guide](migration.md)**. * Hunting for an exact signature? The **[API Reference](api/mcp/index.md)** is generated from the source. * Reading with an LLM? This documentation is also published in the [llms.txt](https://llmstxt.org/) format: From 2be1b5730af7e49ee25a051501d266d9cad19a8b Mon Sep 17 00:00:00 2001 From: Max Isbey <224885523+maxisbey@users.noreply.github.com> Date: Sun, 16 Aug 2026 12:31:42 +0000 Subject: [PATCH 09/11] Address review: roadmap open item, baseline scope, deferral and placement nits No-Verification-Needed: doc-only change --- CONTRIBUTING.md | 2 +- DEPENDENCY_POLICY.md | 2 +- RELEASE.md | 6 +++--- ROADMAP.md | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 62e72784cb..3e35bd9060 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -140,7 +140,6 @@ pre-commit run --all-files - Follow PEP 8 style guidelines - Add type hints to all functions - Include docstrings for public APIs -- Changing a dependency's version bound or adding a runtime dependency follows the [Dependency Policy](DEPENDENCY_POLICY.md) ## Pull Requests @@ -166,6 +165,7 @@ A few dozen lines can be reviewed in minutes. Hundreds of lines across many file 2. Add tests for new functionality 3. Ensure CI passes 4. Address review feedback +5. Dependency bound changes and new runtime dependencies follow the [Dependency Policy](DEPENDENCY_POLICY.md) ## Code of Conduct diff --git a/DEPENDENCY_POLICY.md b/DEPENDENCY_POLICY.md index 0ec2c2ac90..961157b378 100644 --- a/DEPENDENCY_POLICY.md +++ b/DEPENDENCY_POLICY.md @@ -8,7 +8,7 @@ Every runtime dependency is a `>=` floor set to the oldest version that provides ## When a floor moves -A floor is raised only when the SDK starts relying on something that first appeared in that version — not because the dependency published a security advisory. The `>=` bound already lets, and expects, you to run the newest release your other constraints allow, so a higher floor would only shrink the environments the SDK installs into; nor does the SDK add code to work around a dependency's vulnerability, since the fix belongs upstream and in your lockfile ([background](https://github.com/Kludex/uvicorn/discussions/2643), [python-sdk#1552](https://github.com/modelcontextprotocol/python-sdk/issues/1552)). Adding a new runtime dependency, or moving one to its next major version, is decided in an issue before the pull request. Which of these may ship in a minor release is set by the [versioning policy](VERSIONING.md); floor raises are called out in the release notes. +A floor is raised only when the SDK starts relying on functionality or a fix that first appeared in that version — not because the dependency published a security advisory. The `>=` bound already lets, and expects, you to run the newest release your other constraints allow, so a higher floor would only shrink the environments the SDK installs into; nor does the SDK add code to work around a dependency's vulnerability, since the fix belongs upstream and in your lockfile ([background](https://github.com/Kludex/uvicorn/discussions/2643), [python-sdk#1552](https://github.com/modelcontextprotocol/python-sdk/issues/1552)). Floor raises may ship in a minor release under the [versioning policy](VERSIONING.md) and are called out in the release notes. Adding a new runtime dependency, or moving one to its next major version, is decided in an issue before the pull request. ## Automated updates diff --git a/RELEASE.md b/RELEASE.md index 0c2a6d4db3..6233a37ff7 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -111,9 +111,9 @@ hand for the same reason as above. Then ask someone to review the release. Pre-releases of the next version are cut from `main` with a PEP 440 pre-release tag: `aN` for alphas, later `bN`/`rcN` for betas and release candidates. The PEP 440 suffix is what keeps `pip install mcp` on the stable -version — installers select a pre-release only when it is requested explicitly (an -exact pin, a specifier that names a pre-release version, or `--pre`) or when no -final release satisfies the requirement at all. +version — installers do not pick a pre-release for a plain `mcp` requirement while a +final release satisfies it; a pre-release is opted into with an exact pin, a +specifier that names a pre-release version, or `--pre`. 1. During a pre-release phase the README and docs pin the exact pre-release version, so update those examples first (grep the outgoing version — the diff --git a/ROADMAP.md b/ROADMAP.md index 8a2839130d..1f2d293216 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -4,11 +4,11 @@ The SDK's work is organized by MCP specification revision, with one GitHub proje ## The 2026-07-28 revision -v2 implements the [2026-07-28 specification](https://modelcontextprotocol.io/specification/2026-07-28) and negotiates back to every earlier revision. Board: **[python-sdk · 2026-07-28 spec](https://github.com/orgs/modelcontextprotocol/projects/42)** (tracking issue [#2891](https://github.com/modelcontextprotocol/python-sdk/issues/2891)); the cross-SDK view is [2026-07-28 Spec Implementation](https://github.com/orgs/modelcontextprotocol/projects/41). Still open there: the capabilities API and `server/discover` handler ([#2896](https://github.com/modelcontextprotocol/python-sdk/issues/2896)). +v2 implements the [2026-07-28 specification](https://modelcontextprotocol.io/specification/2026-07-28) and negotiates back to every earlier revision. Board: **[python-sdk · 2026-07-28 spec](https://github.com/orgs/modelcontextprotocol/projects/42)**; the cross-SDK view is [2026-07-28 Spec Implementation](https://github.com/orgs/modelcontextprotocol/projects/41). Still open there: making advertised capabilities configurable rather than pre-computed ([#2896](https://github.com/modelcontextprotocol/python-sdk/issues/2896)). ## Not yet implemented -The extensions and optional client-auth mechanisms this SDK does not implement yet are tracked as the entries in the conformance suite's expected-failures baseline, [`.github/actions/conformance/expected-failures.yml`](.github/actions/conformance/expected-failures.yml), which burns down as each lands: +Extensions and optional client-auth mechanisms not yet implemented are tracked in the issue tracker; those the conformance suite already exercises also appear in its expected-failures baseline, [`.github/actions/conformance/expected-failures.yml`](.github/actions/conformance/expected-failures.yml), which burns down as each lands. The main ones: * **Tasks extension** (`io.modelcontextprotocol/tasks`, [SEP-2663](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/2663-tasks-extension.md)) — deferred at 2.0 because the 2026-07-28 design is wire-incompatible with the earlier in-core Tasks; tracked in [#2806](https://github.com/modelcontextprotocol/python-sdk/issues/2806). * **DPoP-bound access tokens** ([SEP-1932](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1932)) in the OAuth client. From 4102871cadb8a8466729c173ebbe89953f4fdff5 Mon Sep 17 00:00:00 2001 From: Max Isbey <224885523+maxisbey@users.noreply.github.com> Date: Sun, 16 Aug 2026 13:01:49 +0000 Subject: [PATCH 10/11] Address review: retired-feature wording, lock description, roadmap tracking claim No-Verification-Needed: doc-only change --- RELEASE.md | 2 +- ROADMAP.md | 2 +- VERSIONING.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/RELEASE.md b/RELEASE.md index 6233a37ff7..cada37480c 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -10,7 +10,7 @@ move; this is the mechanics. `[tool.hatch.metadata.hooks.uv-dynamic-versioning].dependencies`. 2. Regenerate the lock with `uv lock` (or `uv lock --upgrade-package ` to move just that package's locked version). The committed `uv.lock` is a - normal, newest-allowed resolution; the `lowest-direct` resolution that + normal (default-strategy) resolution; the `lowest-direct` resolution that proves the floors still work is applied only by its CI matrix leg at test time and is never committed. diff --git a/ROADMAP.md b/ROADMAP.md index 1f2d293216..dfdcc41a47 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -8,7 +8,7 @@ v2 implements the [2026-07-28 specification](https://modelcontextprotocol.io/spe ## Not yet implemented -Extensions and optional client-auth mechanisms not yet implemented are tracked in the issue tracker; those the conformance suite already exercises also appear in its expected-failures baseline, [`.github/actions/conformance/expected-failures.yml`](.github/actions/conformance/expected-failures.yml), which burns down as each lands. The main ones: +Of the extensions and optional client-auth mechanisms not yet implemented, those the conformance suite already exercises appear in its expected-failures baseline, [`.github/actions/conformance/expected-failures.yml`](.github/actions/conformance/expected-failures.yml), which burns down as each lands. The main ones: * **Tasks extension** (`io.modelcontextprotocol/tasks`, [SEP-2663](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/2663-tasks-extension.md)) — deferred at 2.0 because the 2026-07-28 design is wire-incompatible with the earlier in-core Tasks; tracked in [#2806](https://github.com/modelcontextprotocol/python-sdk/issues/2806). * **DPoP-bound access tokens** ([SEP-1932](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1932)) in the OAuth client. diff --git a/VERSIONING.md b/VERSIONING.md index 53d17300e8..59c6eec813 100644 --- a/VERSIONING.md +++ b/VERSIONING.md @@ -22,7 +22,7 @@ Allowed in a minor: * additions — functions, defaulted parameters, classes, fields, enum members, * changes to provisional or experimental APIs, -* new deprecation warnings, and the eventual removal of protocol features the specification has retired, +* new deprecation warnings, and retired protocol features ceasing to work on connections that negotiate a revision without them (their Python names stay, deprecated, until a major), * raising a dependency floor the SDK needs (see the [dependency policy](DEPENDENCY_POLICY.md)) when the dependency's changes don't reach you through the SDK's API, or dropping a Python version after its upstream end-of-life — both called out in the release notes, * bug fixes, including ones that make the SDK match its documented or specified behavior. From 9ab5bcac06b61fa1f270b07187184e816b67d4a6 Mon Sep 17 00:00:00 2001 From: Max Isbey <224885523+maxisbey@users.noreply.github.com> Date: Sun, 16 Aug 2026 13:30:20 +0000 Subject: [PATCH 11/11] Bullet the support and announcements section No-Verification-Needed: doc-only change --- VERSIONING.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/VERSIONING.md b/VERSIONING.md index 59c6eec813..bc80d51aef 100644 --- a/VERSIONING.md +++ b/VERSIONING.md @@ -32,4 +32,14 @@ Allowed in a minor: ## Support and announcements -Two lines are maintained and only the newest release of each receives fixes: **2.x** (`main`) gets bug fixes, security fixes, and features; **1.x** ([`v1.x`](https://github.com/modelcontextprotocol/python-sdk/tree/v1.x)) gets critical bug fixes and security fixes. [SECURITY.md](https://github.com/modelcontextprotocol/python-sdk/blob/main/SECURITY.md) has the reporting process. Every release publishes notes on [GitHub Releases](https://github.com/modelcontextprotocol/python-sdk/releases); every breaking change between majors is documented in the [Migration Guide](https://py.sdk.modelcontextprotocol.io/migration/) before it merges; and pull requests that make one carry the `breaking change` label. +Two lines are maintained, and only the newest release of each receives fixes: + +* **2.x** (`main`) — bug fixes, security fixes, and features. +* **1.x** ([`v1.x`](https://github.com/modelcontextprotocol/python-sdk/tree/v1.x)) — critical bug fixes and security fixes. + +Where changes are announced: + +* [SECURITY.md](https://github.com/modelcontextprotocol/python-sdk/blob/main/SECURITY.md) has the vulnerability reporting process. +* Every release publishes notes on [GitHub Releases](https://github.com/modelcontextprotocol/python-sdk/releases). +* Every breaking change between majors is documented in the [Migration Guide](https://py.sdk.modelcontextprotocol.io/migration/) before it merges. +* Pull requests that make a breaking change carry the `breaking change` label.