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.
- 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 withmcpin lockstep, somcprequires exactly its own version (mcp-types==<same version>). 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.
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 on this stance from another library that adopted it, and python-sdk#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. 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.
Dependabot 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.
Vulnerabilities in the SDK's own code — as opposed to its dependencies — follow the reporting process and response commitments in SECURITY.md.