Skip to content

fix(deps): require mcp 2.x (FastMCP renamed to MCPServer) - #1371

Open
dependabot[bot] wants to merge 3 commits into
mainlinefrom
dependabot/pip/mcp-gte-1.13.0-and-lt-3
Open

dependabot[bot] wants to merge 3 commits into
mainlinefrom
dependabot/pip/mcp-gte-1.13.0-and-lt-3

Conversation

@dependabot

@dependabot dependabot Bot commented on behalf of github Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Updates the requirements on mcp to permit the latest version.

Release notes

Sourced from mcp's releases.

v2.2.0

pip install -U mcp. Docs: https://py.sdk.modelcontextprotocol.io/

A few defaults changed in this release. If you run a server or client on 2.x, skim these first:

Behaviour changes

HTTP client redirects are only followed within the endpoint's origin (#3397)

  • Client("https://..."), streamable_http_client and sse_client follow a redirect only if it stays on the same scheme, host and port (or upgrades http to https on the same host).
  • A redirect anywhere else is not followed: the call fails with MCPError and the session stays usable (an SSE connect fails with httpx2.HTTPStatusError). If that other URL is the server you meant, use it as the endpoint URL.
  • The follow_redirects setting on an httpx2.AsyncClient you pass in is no longer used for MCP requests, so you don't need it for the trailing-slash redirect any more.
  • The OAuth providers apply the same rule to their own requests.

Idle Streamable HTTP sessions now expire (legacy <=2025-11-25 spec( (#3395)

  • A stateful session with nothing in flight for 30 minutes is closed. The client's next request gets a 404 and it has to initialize again.
  • Clients that keep the GET stream open (the SDK's Client does) are not affected. Neither are stateless servers or 2026-07-28 connections.
  • A server also holds at most 10 000 sessions at once; beyond that, new sessions get a 503.
  • To turn either off: mcp.run(transport="streamable-http", session_idle_timeout=None, max_sessions=None) (also on streamable_http_app() and run_streamable_http_async()).

The OAuth client checks the authorization server's issuer on the legacy path too (#3398)

  • For servers without protected resource metadata, authorization server metadata whose issuer isn't the server's own origin is now rejected with OAuthFlowError: Authorization server metadata issuer mismatch. The protected-resource-metadata path has done this since 2.0.
  • A 403 that isn't an insufficient_scope challenge is returned to the caller instead of retried.
  • If protected resource metadata can't be fetched because of a 5xx/429, the flow now stops instead of falling back to the legacy endpoints.

Two new MCPDeprecationWarnings (#3435, #3447)

  • ClientCredentialsOAuthProvider / PrivateKeyJWTOAuthProvider without issuer=. Pass your authorization server's issuer URL; 3.0 will require it.
  • AuthSettings with resource_server_url set but validate_token_resource unset. Set it to True or False; 3.0 defaults it to True.
  • Both keep working as before in 2.x; this mostly matters if your tests turn warnings into errors.

New

  • AuthSettings.validate_token_resource: only accept tokens your TokenVerifier reports as issued for this server (#3447).
  • issuer= on ClientCredentialsOAuthProvider and PrivateKeyJWTOAuthProvider (#3398).
  • session_idle_timeout= and max_sessions= on the Streamable HTTP server entry points (#3395).

Fixes

  • A client DELETE frees its session immediately, and a refused opening request no longer leaves a session behind (#2455, #3228, #3300).
  • $refs in a tool's outputSchema resolve within that schema only; an unresolvable one surfaces as RuntimeError: Invalid schema for tool ... (#3394).

Known gaps

The tasks extension (SEP-2663), DPoP (SEP-1932) and the jwt-bearer grant are not implemented yet; https://github.com/modelcontextprotocol/python-sdk/blob/main/ROADMAP.md tracks them.

What's Changed

... (truncated)

Commits
  • 9972c21 Replace RootModel wrappers with type aliases and TypeAdapter validation (#3470)
  • fd66270 docs: refresh translations, and translate pages in parallel (#3458)
  • 08a3bc8 docs: ask for AI disclosure on comments too (#3459)
  • 7bb486a docs: stop presenting the in-memory client as the way to connect (#3443)
  • 0c91368 Add AuthSettings.validate_token_resource to check a bearer token's resource (...
  • 9771e6b Keep following a relative redirect when the endpoint URL carries userinfo (#3...
  • a925e55 Bump the locked versions of eight dev and test dependencies (#3449)
  • e8b9486 Bump pymdown-extensions from 11.0 to 11.0.1 (#3285)
  • c6762e8 Follow redirects only within the MCP endpoint's origin (#3397)
  • 5fd3abc Skip automatic docs previews for fork PRs and drop the setup-uv retry steps (...
  • Additional commits viewable in compare view

@dependabot dependabot Bot added dependencies Pull requests that update a dependency file python Pull requests that update Python code labels Sep 29, 2026
@dependabot
dependabot Bot requested a review from a team September 29, 2026 06:44
@dependabot dependabot Bot added the python Pull requests that update Python code label Sep 29, 2026
@github-actions github-actions Bot added the waiting-on-maintainers Waiting on the maintainers to review. label Sep 29, 2026
@dependabot
dependabot Bot force-pushed the dependabot/pip/mcp-gte-1.13.0-and-lt-3 branch from 4161266 to a168209 Compare September 30, 2026 16:36
Updates the requirements on [mcp](https://github.com/modelcontextprotocol/python-sdk) to permit the latest version.
- [Release notes](https://github.com/modelcontextprotocol/python-sdk/releases)
- [Changelog](https://github.com/modelcontextprotocol/python-sdk/blob/main/RELEASE.md)
- [Commits](modelcontextprotocol/python-sdk@v1.13.0...v2.2.0)

---
updated-dependencies:
- dependency-name: mcp
  dependency-version: 2.2.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
@dependabot
dependabot Bot force-pushed the dependabot/pip/mcp-gte-1.13.0-and-lt-3 branch from a168209 to 293d81c Compare September 30, 2026 18:37
github-actions[bot]
github-actions Bot previously approved these changes Sep 30, 2026
mcp 2.0 moved mcp.server.fastmcp.FastMCP to mcp.server.mcpserver.MCPServer,
so widening the requirement to <3 broke 'deadline mcp-server' on import.
Import MCPServer and fall back to FastMCP so both 1.x and 2.x work.

The in-process call_tool() now returns a CallToolResult instead of a list of
content blocks, and Tool.inputSchema is now input_schema; update the
integration tests to handle both shapes.

Signed-off-by: Stephen Crowe <6042774+crowecawcaw@users.noreply.github.com>
Require mcp >= 2.0 instead of supporting both majors, so the server imports
MCPServer directly and the integration tests use the 2.x result types
(CallToolResult, Tool.input_schema) without compatibility shims.

mcp 2.x requires Python 3.10+, so the mcp extra is now gated on
python_version >= '3.10'. The CLI's missing-dependency error now also covers
a stale mcp 1.x install and suggests upgrading.

Signed-off-by: Stephen Crowe <6042774+crowecawcaw@users.noreply.github.com>
@crowecawcaw crowecawcaw changed the title chore(deps): update mcp requirement from <2,>=1.13.0 to >=1.13.0,<3 fix(deps): require mcp 2.x (FastMCP renamed to MCPServer) Sep 30, 2026
@crowecawcaw
crowecawcaw enabled auto-merge (squash) September 30, 2026 20:44
"Error: MCP dependencies not installed.\n"
"Please install them with: pip install 'deadline[mcp]'",
"Error: MCP dependencies are not installed or are out of date (mcp 2.x is required).\n"
"Please install them with: pip install --upgrade 'deadline[mcp]'",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On Python 3.9 this error message is a dead end. The mcp extra is now mcp >= 2.0, < 3; python_version >= '3.10', so on a 3.9 interpreter the extra resolves to zero packages and pip install --upgrade 'deadline[mcp]' exits 0 having installed nothing. The user then re-runs deadline mcp-server, gets this same message, and loops forever with no hint about the real cause.

Previously the failure was loud: mcp >= 1.13.0, < 2 has requires-python >= 3.10, so pip errored out at install time on 3.9. The marker converts that hard failure into a silent no-op, which makes the runtime message the only signal the user gets — and it currently points at a fix that cannot work.

Suggest naming the interpreter requirement here, e.g.:

"Error: MCP dependencies are not installed or are out of date (mcp 2.x, which requires Python 3.10+, is required).\n"
"Please install them with: pip install --upgrade 'deadline[mcp]'\n"
f"(detected Python {sys.version_info.major}.{sys.version_info.minor})"

The docstring at line 27-28 has the same gap.

"""

app = FastMCP("deadline-cloud", instructions=INSTRUCTIONS)
app = MCPServer("deadline-cloud", instructions=INSTRUCTIONS)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This module still has zero unit-test coverage, which is the reason the original FastMCP breakage reached users rather than CI.

test/unit/deadline_mcp/test_mcp.py exercises register_api_tools against a MagicMock() app, so it passes against any SDK whatsoever — a MagicMock happily accepts .tool(name=..., description=...). Nothing under test/unit/ imports deadline._mcp.server, so the only thing that actually constructs a real server object and calls list_tools() is test/integ/, which needs live AWS credentials and does not run on PRs. That is exactly how mcp.server.fastmcp going away produced a broken deadline mcp-server with green CI.

Pinning mcp >= 2.0 closes today's hole but not the class of bug: the next rename (or a Tool field change like inputSchema -> input_schema) lands the same way. A credential-free unit test in test/unit/deadline_mcp/test_mcp.py would catch it, since it only needs the in-process server:

@pytest.mark.asyncio
async def test_server_registers_tools_on_real_sdk():
    from deadline._mcp import server

    tools = await server.app.list_tools()
    names = {t.name for t in tools}
    assert {f"deadline_{n}" for n in TOOL_REGISTRY} <= names
    assert next(t for t in tools if t.name == "deadline_list_queues").input_schema

This imports the real MCPServer, registers every tool through the real ToolManager, and reads the same Tool fields the integ tests read — no boto3 call, since nothing invokes a tool. It skips cleanly on 3.9 under the existing importorskip("mcp"), and pytest-asyncio is already a test dependency.

Comment thread pyproject.toml
]
mcp = [
"mcp >= 1.13.0, < 2",
"mcp >= 2.0, < 3; python_version >= '3.10'",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Putting the python_version >= '3.10' marker on an extra turns a loud install failure into a silent no-op on Python 3.9.

Environment markers in an extra filter the requirement rather than rejecting the install. On a 3.9 interpreter this list evaluates to empty, so pip install 'deadline[mcp]' succeeds, exits 0, installs no mcp, and prints nothing — the user has no signal that the extra they asked for was dropped. They only find out later at deadline mcp-server runtime, via the ImportError branch in mcp_server_command.py, which currently tells them to re-run the same install that just no-opped.

Without the marker, the outcome is better: mcp 2.x declares requires-python >= 3.10, so pip fails the resolve on 3.9 with an explicit "requires a different Python" message naming the package and version. That is the diagnostic the user needs, at the moment they can act on it.

Note this is unlike the click markers above at lines 40-41, which are a genuine either/or — both arms are non-empty, so every interpreter still gets a click. Here the 3.9 arm is absent entirely, so the marker only suppresses the error.

Two options, either is fine, but the tradeoff is worth making deliberately:

  • Drop the marker and let pip's requires-python check fail loudly (extras are opt-in, so this cannot break a plain pip install deadline on 3.9).
  • Keep the marker for resolver convenience, but then the runtime message in mcp_server_command.py must name the Python 3.10+ requirement, since it becomes the only place the user ever learns about it.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The silent failure on 3.9 sounds like it'd create a pretty confusing customer experience. Worth addressing?

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file python Pull requests that update Python code waiting-on-maintainers Waiting on the maintainers to review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants