Skip to content

fix(mcp): pin mcp to >=1.2,<2 (2.x removed mcp.server.fastmcp) and assert the import in CI - #265

Merged
k-yoshimi merged 4 commits into
developfrom
fix/ci-pin-mcp-below-2
Oct 18, 2026
Merged

k-yoshimi merged 4 commits into
developfrom
fix/ci-pin-mcp-below-2

Conversation

@k-yoshimi

Copy link
Copy Markdown
Owner

Summary

CI's pip install mcp and the seven server pyprojects' mcp>=0.9 have no ceiling, so a fresh install now takes mcp 2.3.0 (upstream run 39010271792 did). mcp 2.0 removed mcp.server.fastmcp; every server.py catches that import under except Exception and sets MCP_AVAILABLE = False, so:

  • the seven TestBuildServer classes skip ("Python MCP SDK (mcp) not installed") and CI is green without building a single FastMCP server;
  • anyone following a README (pip install -e python/mcp-servers/eq_mcp) gets a server that exits 2.

This PR pins mcp>=1.2,<2 everywhere and adds a CI tripwire so the skip can never go unnoticed again.

Commits

  1. 9d414211 pin in the workflow and the seven pyprojects — cherry-pick of @HengyuLi-Ozaki-lab's c528b58d from Reconcile bpsi/develop base into develop (bpsi↔fork merge baseline, CI-green) #226 (author preserved). Left out: the hunk for eq_mcp/tests/test_get_psi_rz_tool.py, which does not exist on develop yet, and the numpy install that commit sits next to in Reconcile bpsi/develop base into develop (bpsi↔fork merge baseline, CI-green) #226.
  2. 92b2ad8e pinned string in the servers' "not installed" message, READMEs, Sphinx MCP pages, presentation + builder, MCP plan; CI tripwire — cherry-pick of af197409 from Reconcile bpsi/develop base into develop (bpsi↔fork merge baseline, CI-green) #226 (author preserved), same two hunks left out. The tripwire runs import eq_mcp.server; assert MCP_AVAILABLE right after the pip install, before any make (the import chain loads no .so and needs nothing beyond stdlib + mcp; checked with the libraries absent).
  3. 56d1e9f9 CHANGELOG.
  4. 3325df0d floor raised 0.9 → 1.2 (Codex review finding). mcp/server/fastmcp first ships in the 1.2.0 wheel; 1.1.3 does not have it, so 1.0/1.1 fail exactly like 2.x. Also pins the plan doc's last pip install mcp, fixes the stale "9 tests across 6 modules" comment and the seven pyproject comments.

Porting the servers to the mcp 2.x API is separate work.

Interplay with #226

On its next rebase, #226's c528b58d / af197409 will show as already applied; what remains there is the new test's guards and the numpy install, plus a trivial 0.9 vs 1.2 conflict in the same strings.

Verification

  • python/mcp-servers with the CI flags (--forked --timeout=120 --timeout-method=signal), local mcp 1.27.0, libraries present: 347 passed, 3 skipped (the 3 are the ti fixture-not-generated skips; zero "SDK not installed" skips).
  • Tripwire line run from the worktree with all seven .so removed: MCP_AVAILABLE = True.
  • Workflow parses as YAML; bash -n accepts the tripwire line.
  • Reviews: in-house (no HIGH/MED, 3 LOW all applied) + Codex (2 MED → commit 4, 1 LOW applied; Codex delta re-review: 1 LOW, applied).

🤖 Generated with Claude Code

https://claude.ai/code/session_01TA2KahTs3qLMZL6yjSsWwT

HengyuLi-Ozaki-lab and others added 4 commits October 18, 2026 14:32
…jects

mcp 2.0 removed `mcp.server.fastmcp` (replaced by MCPServer/Server with
a different decorator API). The workflow installs a bare `mcp` and the
seven server pyprojects declare `mcp>=0.9` with no ceiling, so a fresh
install picks up 2.x, every server.py's optional import falls back to
MCP_AVAILABLE=False, the seven TestBuildServer classes skip, and the
stdio servers refuse to start (main() returns 2). Upstream CI run
39010271792 installed mcp 2.3.0 and was green with those 7 skips.

Pin `mcp>=0.9,<2` in the workflow and in all seven pyproject files.
Porting the servers to the 2.x API is its own change.

(cherry picked from commit c528b58,
 part of #226; the hunk for eq_mcp/tests/test_get_psi_rz_tool.py is
 left out because that test does not exist on develop yet, and the
 numpy install that commit sits next to in #226 is not on develop)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TA2KahTs3qLMZL6yjSsWwT
… in CI

Follow-up to the pin. Every server printed

    error: Python MCP SDK (`mcp`) is not installed.
           pip install 'mcp>=0.9'

so a user who hit the 2.x failure and followed the instruction would
install mcp 2.x again. The `mcp>=0.9` strings in the seven server.py
files, their READMEs, the Sphinx mcp pages, the presentation and its
builder, and the MCP plan are now `mcp>=0.9,<2`.

Tripwire: MCP_AVAILABLE is set by a bare `except Exception`, so any
future breakage of the FastMCP import path would silently turn the
seven server suites green-by-skip. The workflow now asserts
MCP_AVAILABLE right after installing the pin, so in the one
environment where those tests must run, a skip becomes a hard failure.

(cherry picked from commit af19740,
 part of #226; the hunks for eq_mcp/tests/test_get_psi_rz_tool.py and
 the numpy install are left out, neither exists on develop yet)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TA2KahTs3qLMZL6yjSsWwT
…er.fastmcp

The pin `mcp>=0.9,<2` kept the old floor. `mcp.server.fastmcp` does not
exist before mcp 1.2.0 (checked the wheels: 1.1.3 has no
mcp/server/fastmcp, 1.2.0 does), so with 1.0 or 1.1 installed every
server fails the same way as with 2.x. `mcp>=1.2,<2` everywhere the
pinned string appears (pyprojects, workflow, server messages, READMEs,
Sphinx MCP pages, presentation and its builder, MCP plan).

Also: the MCP plan's "pip install mcp" (the one unpinned instruction
left), the workflow comment's "9 tests across 6 modules" (it is the 7
TestBuildServer classes, one per module), and the CHANGELOG entry.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TA2KahTs3qLMZL6yjSsWwT
@k-yoshimi
k-yoshimi merged commit 4b5463e into develop Oct 18, 2026
3 checks passed
HengyuLi-Ozaki-lab added a commit to HengyuLi-Ozaki-lab/task that referenced this pull request Oct 21, 2026
develop now carries the pieces split out of this branch (k-yoshimi#256 eq_save,
k-yoshimi#257 the MCP fd isolation, k-yoshimi#265 the mcp pin) and k-yoshimi#232, k-yoshimi#233, k-yoshimi#240, k-yoshimi#242,
k-yoshimi#243, k-yoshimi#248, k-yoshimi#249, k-yoshimi#251, k-yoshimi#254, k-yoshimi#255, k-yoshimi#258, k-yoshimi#259, k-yoshimi#261, k-yoshimi#263, k-yoshimi#264. 43
files conflicted; each was resolved as follows.

- Taken from develop (36 files): every file where this branch only
  changed the mcp pin to "mcp>=0.9,<2" (develop has ">=1.2,<2", k-yoshimi#265):
  the seven pyproject.toml, six READMEs, the fp, ti, tot, wr and wrx
  servers, the Sphinx MCP pages, the trlib presentation and its
  builder, the 2026-04-18 MCP plan; and the eq_save pieces now in
  develop in their reviewed form: eq/eq_api.f90, eq/eq_api.h,
  python/eqlib/tests/test_save.py, eq_mcp/tests/test_save_tool.py; and
  tr_mcp/server.py, whose changes here were this branch's own fd
  isolation (develop's _fd_isolation replaces it) and the os._exit(0)
  at the end of main().
- The os._exit(0) that ended main() of tr_mcp and eq_mcp on this branch
  (to skip the Python teardown, cited in k-yoshimi#227 item 5) is gone with
  them: develop's main() returns 0, as approved in k-yoshimi#257. The abort it
  avoided was a double DEALLOCATE, which this branch fixed in
  tr/trcomm.f90 (DEALLOCATE_TRCOMM returns when nothing is allocated);
  that fix stays, merged without a conflict.
- eq/eqfile.f90: develop's (EQSAVE without an argument, EQSAVE_IERR
  doing the work, and its kept EQDSKR error), plus this branch's
  MODELG=25 in EQ_READ's EQDSK branch (k-yoshimi#228-2). eq/eqmenu.f90 merged
  without a conflict but kept this branch's "CALL EQSAVE(IERR)"; it is
  develop's "CALL EQSAVE" again, as EQSAVE takes no argument.
- python/eqlib/_ffi.py, eqlib.py, tests/test_eqlib.py: develop's, plus
  this branch's get_psi_rz (the eq_common_get_psi_rz_ prototype, the
  Eq.get_psi_rz method, its closed-handle assertion).
- eq_mcp/server.py: develop's (the save tool of k-yoshimi#256, the shared fd
  isolation), plus this branch's get_psi_rz handler and tool and its
  --print-tools entry (13 tools). eq_mcp/tests/test_server.py: this
  branch's (13 tools with save and get_psi_rz), which contains
  develop's change.
- python/mcp-servers/eq_mcp/tests/test_import_isolation.py (this branch
  only, no conflict) is removed: it pinned this branch's own isolation
  helper (_install_fd_isolation, _FD_ISOLATION_INSTALLED in eq_mcp and
  tr_mcp), which develop's python/_fd_isolation.py replaces; develop's
  tests/test_fd_isolation.py of each of the seven servers checks the
  same contract (an import leaves fd 1 and sys.stdout alone).
- .github/workflows/python-tests.yml: develop's mcp pin; this branch's
  numpy install (the get_psi_rz tests import numpy) and ../task symlink
  step kept.
- CHANGELOG.md did not conflict. The three k-yoshimi#228 entries this branch held
  back in d8b6e4d are added to [Unreleased] Fixed, after its first
  entry, where no other open pull request inserts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HengyuLi-Ozaki-lab added a commit to HengyuLi-Ozaki-lab/task that referenced this pull request Oct 21, 2026
The docstring and the skip reason of test_get_psi_rz_tool.py still said
"mcp>=0.9,<2", the pin this branch carried before k-yoshimi#265 moved it to
develop as ">=1.2,<2" (mcp.server.fastmcp first ships in 1.2.0). They
name develop's pin now; the guards themselves are unchanged. The
"trivial 0.9 vs 1.2" K. Yoshimi mentioned on 2026-10-18.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.

2 participants