Skip to content

fix(deps): cap mcp below 2.0.0 (ENG-4250) - #207

Merged
SystemSculpt merged 1 commit into
mainfrom
codex/eng-4250-cap-mcp-v1
Jul 28, 2026
Merged

fix(deps): cap mcp below 2.0.0 (ENG-4250)#207
SystemSculpt merged 1 commit into
mainfrom
codex/eng-4250-cap-mcp-v1

Conversation

@SystemSculpt

@SystemSculpt SystemSculpt commented Jul 28, 2026

Copy link
Copy Markdown
Member

What broke

mcp 2.0.0 was published today at 13:45 UTC and removed the mcp.server.fastmcp module. src/blaxel/core/mcp/server.py subclasses it:

from mcp.server.fastmcp import FastMCP as FastMCPBase

pyproject.toml declared mcp>=1.9.4 with no upper bound, and the workflow's first step runs uv pip install -e ., which resolves fresh and ignores uv.lock. Every fresh install now fails at import:

File "src/blaxel/core/mcp/server.py", line 13, in <module>
    from mcp.server.fastmcp import FastMCP as FastMCPBase
ModuleNotFoundError: No module named 'mcp.server.fastmcp'

This kills Test package installation (base) before any test executes, so Unit Tests fails across 3.10-3.14. It is repo-wide, not branch-specific: every open PR and the next push to main. Last green main run was 2026-07-24, before the release.

Published wheel contents:

version files under mcp/server/fastmcp
1.20.0 19
2.0.0 0

Upstream split FastMCP out into the standalone fastmcp package (currently 3.4.5).

Blast radius is one import

Every mcp import in our source was audited. Only FastMCP is gone:

our import status in 2.0.0
mcp.ClientSession survives
mcp.client.streamable_http survives
mcp.shared.message.SessionMessage survives
mcp.types survives
mcp.server.fastmcp.FastMCP removed

Total dependency: one import and one subclass overriding run(), in a 148-line file.

Fix

-  "mcp>=1.9.4",
+  "mcp>=1.9.4,<2.0.0",

A major bump is entitled to break; the unbounded >= was the actual defect. This matches the existing websockets<16.0.0 precedent in the same dependency list. uv lock produces no change, since the lockfile already resolved inside 1.x, so the diff is one file.

Verification

  • Reproduced the exact CI failure locally on clean main @ 2c405e2 using the workflow's own commands (uv venv, uv pip install -e ., import blaxel.core): ModuleNotFoundError.
  • With the cap, the same commands resolve mcp 1.29.0 and emit the workflow's own success lines for both Test package installation (base) and (with extras).
  • Unit suite: 401 passed, 2 failed, both pre-existing on unpatched main (stale local device-mode credentials hitting api.blaxel.ai/v0/oauth/token).
  • uv lock: no change.

Deliberately not in this PR

Migrating off the removed FastMCP surface. It is small, but it needs an owner decision about the MCP server surface, and an outage stop-gap is the wrong place for it.

Also observed while auditing: 9 of 11 core dependencies are unbounded (pydantic, pyjwt, python-dateutil, pyyaml, requests, tomli, attrs, httpx, dockerfile-parse). The same failure mode is available to any of them, but a reflexive mass-cap is a policy decision rather than a fix for this outage.

Unblocks

ENG-4244 / #206, whose only red checks are this failure.

Linear: ENG-4250


Note

Caps the mcp dependency at <2.0.0 to prevent CI failures caused by mcp 2.0.0 removing the mcp.server.fastmcp module that this SDK subclasses.

Written by Mendral for commit 899177d.

mcp 2.0.0, published today, removed the mcp.server.fastmcp module that
core/mcp/server.py subclasses. The dependency was declared `mcp>=1.9.4` with no
upper bound, and CI's first step runs `uv pip install -e .`, which resolves
fresh and ignores uv.lock. Every fresh install therefore fails at import:

    ModuleNotFoundError: No module named 'mcp.server.fastmcp'

That kills `Test package installation (base)` before any test runs, so Unit
Tests fail on all of 3.10-3.14, on every open PR and on main.

Cap the range. A major bump is entitled to break; the unbounded `>=` was the
defect. Matches the existing `websockets<16.0.0` precedent in the same list.
uv.lock is unchanged, as it already resolved inside 1.x.

Migrating off the removed FastMCP surface is deliberately not bundled here: it
needs an owner decision about the MCP server surface and should not ride along
with an outage stop-gap.
@mendral-app

mendral-app Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

🧪 Testing Guide

What this PR addresses

mcp 2.0.0 removed the mcp.server.fastmcp module that src/blaxel/core/mcp/server.py imports. Since pyproject.toml had no upper bound (mcp>=1.9.4), any fresh install now resolves to 2.0.0 and fails with ModuleNotFoundError. This PR caps the dependency to mcp>=1.9.4,<2.0.0.

Steps to reproduce the original issue

  1. Check out the main branch (before this PR).
  2. Create a fresh virtual environment: uv venv && source .venv/bin/activate
  3. Install the package from source: uv pip install -e .
  4. Run: python -c "from blaxel.core.mcp.server import FastMCP"
  5. Observe ModuleNotFoundError: No module named 'mcp.server.fastmcp' because mcp==2.0.0 is resolved.

What to verify (expected behavior)

  1. Check out this PR branch (codex/eng-4250-cap-mcp-v1).
  2. Create a fresh virtual environment and install: uv venv && source .venv/bin/activate && uv pip install -e .
  3. Confirm the installed mcp version is <2.0.0: uv pip show mcp (expect 1.9.x or 1.x).
  4. Confirm the import succeeds: python -c "from blaxel.core.mcp.server import FastMCP; print('OK')" → prints OK.
  5. Run the existing test suite (pytest) and verify no regressions.
  6. Verify CI passes end-to-end (the workflow's uv pip install -e . step should no longer fail).

Note

Posted by PR Testing Guide · Tag @mendral-app with feedback.

@mendral-app mendral-app Bot left a comment

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.

LGTM

Straightforward, correct upper-bound cap matching the existing websockets<16.0.0 pattern. The version specifier >=1.9.4,<2.0.0 is valid PEP 440 and precisely excludes the breaking major release. No correctness, security, or operational concerns.

Tag @mendral-app with feedback or questions. View session

@mendral-app

mendral-app Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

🔒 Dependency Cap — Interaction Flow

This PR is a minimal dependency constraint change (1 file, 1 logical line), so a full sequence diagram would be overkill. Here's a concise view of why this cap matters in the install/import flow:

sequenceDiagram
    participant CI as CI Workflow
    participant UV as uv pip install
    participant PyPI as PyPI Registry
    participant Proj as pyproject.toml
    participant Srv as core/mcp/server.py

    CI->>UV: uv pip install -e .
    UV->>Proj: Read dependencies
    Proj-->>UV: mcp>=1.9.4,<2.0.0
    UV->>PyPI: Resolve mcp version
    PyPI-->>UV: mcp 1.x.y (capped below 2.0.0)
    UV-->>CI: Install success
    CI->>Srv: import blaxel.core.mcp.server
    Srv->>Srv: from mcp.server.fastmcp import FastMCP
    Note right of Srv: ✅ Module exists in mcp <2.0.0
Loading

Summary: The upper bound <2.0.0 on mcp ensures that uv pip install (which resolves fresh, ignoring uv.lock) won't pull mcp 2.0.0+ where mcp.server.fastmcp was removed — preventing ModuleNotFoundError on every fresh CI install.

Note

Posted by PR Sequence Diagram · Tag @mendral-app with feedback.

@mendral-app

mendral-app Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

✅ Linked to Linear issue ENG-4250 — status already In Progress

Note

Posted by Linear Issue Enforcer · Tag @mendral-app with feedback.

@SystemSculpt
SystemSculpt merged commit 175cb9f into main Jul 28, 2026
23 checks passed
@SystemSculpt
SystemSculpt deleted the codex/eng-4250-cap-mcp-v1 branch July 28, 2026 17:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant