What agents should know before contributing
modelcontextprotocol/python-sdk
The official Python SDK for Model Context Protocol servers and clients
Read by Bluet from 9 files written for agents and 300 merged pull requests on 2026-09-24. Not reviewed by the maintainers.
Rules its files tell agents (20)
- docs/migration.md
mustIf you call these methods directly, narrow with isinstance (or assert not isinstance(result, InputRequiredResu…
Like call_tool() above, MCPServer.get_prompt() now returns GetPromptResult | InputRequiredResult and MCPServer.read_resource() returns Iterable[ReadResourceContents] | InputRequiredResult: at 2026-07-28 an @mcp.prompt() function or an @mcp.resource() template function may answer with an InputRequiredResult to request client input first (see Multi-round-trip requests). If you call these methods directly, narrow with isinstance (or assert not isinstance(result, InputRequiredResult) when your prompt and resource functions never return one). Prompt.render() and ResourceTemplate.create_resource() c
- docs/migration.md
mustAs in v1, the host app's lifespan must enter mcp.session_manager.run() — a mounted sub-app's own lifespan neve…
When mounting in a Starlette app, pass transport params to streamable_http_app(). As in v1, the host app's lifespan must enter mcp.session_manager.run() — a mounted sub-app's own lifespan never runs, so nothing else starts the session manager:
- docs/migration.md
mustIf your own code imports httpx and relied on mcp v1 to pull it in, that import now fails with ModuleNotFoundEr…
mcp no longer installs httpx at all. If your own code imports httpx and relied on mcp v1 to pull it in, that import now fails with ModuleNotFoundError: No module named 'httpx' — a traceback that never mentions mcp. Either add httpx to your own dependencies (the two packages install side by side; only objects handed to the SDK via http_client= or auth= have to be httpx2 types) or port those calls to httpx2, whose Client and AsyncClient are drop-in replacements.
- docs/migration.md
mustIf httpx is still installed — your own code or another package depends on it — an old except httpx.ConnectErro…
Exception handlers need the same rename: the SDK now raises httpx2 exceptions (httpx2.ConnectError, httpx2.HTTPStatusError, and so on), and this failure mode is silent. If httpx is still installed — your own code or another package depends on it — an old except httpx.ConnectError: block keeps importing fine and simply never matches again. Audit except httpx. clauses and isinstance checks along with the imports, and switch test fixtures in the same change: pytest.raises(httpx.ConnectError), an httpx.MockTransport, or a test-only httpx.Auth subclass all target the wrong types once the code under
- CONTRIBUTING.md
mustNever edit the generated pages under i18n/<lang>/pages/—the tool can't tell a hand edit from its own output, s…
Documentation contributions are English only: the pages under docs/ are the source of truth, and the translated documentation sites are generated from them, guided by the per-language style guides and glossaries under i18n/<lang>/. Never edit the generated pages under i18n/<lang>/pages/—the tool can't tell a hand edit from its own output, so the edit persists unchecked, is carried forward into future runs, and hides the real fix. To fix a translation, change that language's instructions.md or glossary.json (or the English page, if that's where the problem is) and re-run translate --lang <code>
- docs/troubleshooting.md
shouldFor a 2026-07-28 client the fix is the same on all three: don't reach back mid-call.
For a 2026-07-28 client the fix is the same on all three: don't reach back mid-call. Move the question into a resolver (or return an InputRequiredResult yourself) and it becomes part of the response, which every connection can carry:
- docs/migration.md
shouldIf you call these methods directly and omit context, a Context with no active request is constructed for you —…
MCPServer.call_tool(), MCPServer.read_resource(), and MCPServer.get_prompt() now accept an optional context: Context | None = None parameter. The framework passes this automatically during normal request handling. If you call these methods directly and omit context, a Context with no active request is constructed for you — tools that don't use ctx work normally, but any attempt to use ctx.session, ctx.request_id, etc. will raise.
- docs/migration.md
shouldThe field is display-only; nothing breaks either way.
In v1, a server constructed without a version reported the installed mcp package's version as its own in the initialize result's serverInfo. In v2 it reports an empty string instead: the SDK's version is not your server's version. Pass version="..." to Server(...) or MCPServer(...) to identify your server properly. The field is display-only; nothing breaks either way.
- docs/migration.md
shouldNo error is raised; the output is silently in the wrong shape.
If you serialize models yourself, pass by_alias=True. In v1, model_dump() produced wire-format camelCase keys because the fields themselves were camelCase. In v2 the same call emits snake_case keys (input_schema, not inputSchema), which peers and other MCP implementations will not recognize. No error is raised; the output is silently in the wrong shape.
- docs/migration.md
shouldUnderscore-prefixed submodules (mcp_types._types, and the generated per-protocol-version packages mcp_types._v…
The supported import surface is the package plus its jsonrpc, methods, and version submodules, and each has both spellings: mcp.types / mcp_types, mcp.types.jsonrpc / mcp_types.jsonrpc, mcp.types.methods / mcp_types.methods, and mcp.types.version / mcp_types.version (each mcp.types module mirrors its mcp_types counterpart, name for name, the same objects). Underscore-prefixed submodules (mcp_types._types, and the generated per-protocol-version packages mcp_types._v2025_11_25 / mcp_types._v2026_07_28) are internal validators with unstable class names; don't import from them, under either spelli
- docs/migration.md
shouldmcp-types is exact-pinned to the SDK version; nothing in a v1 tree can conflict with it, but do not pin mcp-ty…
Relax or bump any conflicting pins when upgrading. sse-starlette jumps two majors, so a project that imports sse_starlette itself must also work through that library's own breaking changes to co-install with mcp v2. opentelemetry-api is a new hard dependency because every outbound request now carries a _meta envelope used for OpenTelemetry trace propagation; see Every outbound request now carries a _meta envelope. mcp-types is exact-pinned to the SDK version; nothing in a v1 tree can conflict with it, but do not pin mcp-types independently of mcp.
- docs/deprecated.md
shouldclient.send_roots_list_changed() warns, and it needs a mode="legacy" client: on a modern connection the notifi…
workspace is the list your list_roots_callback returns. client.send_roots_list_changed() warns, and it needs a mode="legacy" client: on a modern connection the notification is silently dropped. Keep the session open afterwards, because the server's follow-up roots/list arrives on it.
- CONTRIBUTING.md
shouldSecurity reports do not belong in the issue tracker; SECURITY.md has the private channel.
- CONTRIBUTING.md
shouldComments that only ask to be assigned don't factor into it, so please skip those (and don't have an agent post…
Whether to assign an issue, and to whom, is a maintainer call, and it depends on our capacity at the time as much as on the change itself. Comments that only ask to be assigned don't factor into it, so please skip those (and don't have an agent post them). What does help is engaging with the issue itself: confirming the reproduction, asking about the intended behaviour, or briefly describing the approach you'd take. If you reported the issue and would like to fix it yourself, mention that in the issue — the reporter has first call if we do take an outside PR for it.
- AGENTS.md
shouldDon't include the exception in the message: logger.exception("Failed") not logger.exception(f"Failed: {e}")
- AGENTS.md
shouldDon't silence warnings from your own code; fix the underlying cause.
Pytest is configured with filterwarnings = ["error"], so warnings fail tests. Don't silence warnings from your own code; fix the underlying cause. Scoped ignore:: entries for upstream libraries are acceptable in pyproject.toml with a comment explaining why.
- AGENTS.md
shouldDo not use Test prefixed classes — write plain top-level test_* functions.
Do not use Test prefixed classes — write plain top-level test_* functions. Legacy files still contain Test* classes; do NOT follow that pattern for new tests even when adding to such a file.
- AGENTS.md
shouldExplain only non-obvious reasons or constraints; do not narrate the code or restate names, types, or assertion…
Keep comments brief. Explain only non-obvious reasons or constraints; do not narrate the code or restate names, types, or assertions.
- AGENTS.md
shouldDon't list exceptions from argument validation or programmer error.
Public APIs must have docstrings. When a public API raises exceptions a caller would reasonably catch, document them in a Raises: section. Don't list exceptions from argument validation or programmer error.
- AGENTS.md
shouldDon't raise dependency floors for CVEs alone.
Don't raise dependency floors for CVEs alone. The >= constraint already lets users upgrade. Only raise a floor when the SDK needs functionality from the newer version, and don't add SDK code to work around a dependency's vulnerability. See Kludex/uvicorn#2643 and python-sdk #1552 for reasoning.
Decisions its pull requests settled (40)
- #2152accept wildcard media types in Accept header per RFC 7231
- #2185include client_id in token request body for client_secret_post
- #2235remove MIME type validation from MCPServer Resource
- #2356RFC 6570 URI templates with operator-aware security
- #2358restore `dependencies` parameter on MCPServer
- #2404coerce empty-string optional URL fields to None in OAuthClientMetadata
- #2405[v1.x] fix(auth): coerce empty-string optional URL fields to None in OAuthClientMetadata
- #2642add 'invalid_target' to AuthorizationErrorCode (RFC 8707)
- #2714Remove Tasks (SEP-1686) from the SDK
- #2823Clarify AGENTS.md policy on compat shims for breaking changes
- #2828[v1.x] Deprecate the WebSocket transport and the experimental tasks entry points
- #2838[v2] ClientSession runs on JSONRPCDispatcher; BaseSession removed
- #2921Validate the `iss` authorization-response parameter (RFC 9207 / SEP-2468)
- #2925Preserve empty URL paths on OAuth metadata models
- #2929Document `redirect_uri` wire-format change in OAuth migration note
- #2936OAuth client: harden SEP-2352/SEP-2350 edge cases; fix conformance comment
- #2946OAuth client: keep refresh_token on non-rotating refresh; restore same-origin issuer binding
- #2978Rebuild the docs around tested examples; shrink README.v2.md to a pitch
- #2987Preserve empty issuer/resource paths on AuthSettings
- #2988Support RFC 8693 token exchange for enterprise IdP flows (SEP-990)
- #2989find_invalid_x_mcp_header: never repr a non-string annotation value
- #3003Add a pluggable server extension API with MCP Apps
- #3032Require integrity protection for MRTR requestState
- #3034Add a client extension API
- #3046Make client-side cancellation work over the 2026 transports
- #3117Isolate the stdio server's stdin and stdout from handler subprocesses
- #3166Rename scopes= to scope= on the client-credentials OAuth providers
- #3171Replace FileResource.is_binary with an encoding field
- #3181Split the registration request model from the registered-client record
- #3190Add mcp.types as a permanent alias for mcp_types
- #3195Fail fast on server-to-client requests in JSON-response mode instead of hanging
- #3201Expose the middleware chain on MCPServer and stop sending unrequested change notifications
- #3223Drop later-revision cache-hint fields on pre-2026 sessions
- #3314Log MCPServer handler exceptions by kind and keep crash details off the wire
- #3320MCPServer: content-block returns are unstructured, prompt messages take Image/Audio
- #3331Hand TypedDict tool results to pydantic natively
- #3376Give recursive tool return types an object-rooted output schema
- #3388Point imports of mcp.server.fastmcp at the migration guide
- #3395Expire idle Streamable HTTP sessions by default and cap concurrent sessions
- #3397Follow redirects only within the MCP endpoint's origin