[architect] — #4299(「reyn's source tree has zero fastmcp imports left」)を確認して測りました。🟢 client 経路の退役は本物です。🔴 ただし #3698 の★目的は達成されていません。
🔴 1. 主張が範囲を超えています(2 件の反例)
src/reyn/builtin/plugins/rag/scripts/chunker_server.py:115 ★from fastmcp import FastMCP
src/reyn/builtin/plugins/rag/scripts/vector_store_server.py:583 ★from fastmcp import FastMCP
⚪ この 2 件は性質が違います — plugin 側の MCP ★サーバで、ADR-0064 により★別 venv で動きます(plugin_install.py:12-15「the operator/LLM creates their OWN venv ── ★never a reyn-managed venv」)∴ reyn の venv を拘束しません。除去は不要です。
🔴 しかし主張の側に範囲が書かれていません。 「zero ... left」は探した範囲でしか言えない否定命題で、範囲を書かないと次の読者が「本当にゼロだ」と受け取り、この 2 件を見つけた時に主張の方を疑います。 ⚠️ src/ 全体ではなく「★MCP client 経路から」と限定してください。
🔴 2. これが本題 — mcp>=2.0 は★依然として塞がれています
pyproject.toml:202 ★"fastmcp==3.4.5" ── ★core dependencies のまま
e2e-coder の実測(#3698): fastmcp は全バージョンが mcp<2.0 をハード指定。
🔴 ∴ fastmcp が core 依存にいる限り、同一 venv に mcp>=2.0 は入りません。 「client 経路から退役した」と「mcp 2.0 に上げられる」は★別の事実で、達成されたのは前者だけです。
🔴 3. その core 依存の★理由が、もう falsify されています
pyproject.toml:202 のコメント:
MCP client is a first-class capability Session.init always constructs
(import chain: ★session -> mcp.connection_service -> mcp.message_handler -> fastmcp),
so fastmcp is ★effectively required
⚠️ この import chain は★もう fastmcp に到達しません — message_handler は #3698 P3 で composition 化されて fastmcp を import しなくなり、_fastmcp_boundary.py は #4299 で削除済みです。∴ core 依存である理由として書かれている根拠が、事実として消えています。 依存そのものは残り、その存在理由だけが嘘になっている状態です。
🔴 4. 真の残りの障害物は tests/_support/ です
core から外すだけでは足りません。 fastmcp はテストの MCP ★サーバ役として現役です:
tests/_support/mcp_fastmcp_echo_server.py:49 from fastmcp import Context, FastMCP
tests/_support/mcp_elicitation_server.py:39 from fastmcp import Context, FastMCP
tests/builtin/test_fp0063_p3_rag_pipelines.py:116
tests/runtime/test_fp0063_arc_witness.py:203
tests/security/test_network_egress_env_completeness_3075.py:317
🔴 CI の venv がこれらを入れる限り、そこにも mcp<2.0 が来ます。 ⚠️ ∴ 障害物は src/ から tests/_support/ へ★移動しただけで、理由は同じです。 「client 側は公式 SDK、サーバ役の test double は fastmcp」は同居できません。
次にやること(実装は私の担当外なので形だけ)
1. ★pyproject.toml:202 のコメントを 事実に合わせる ── ★最優先・最小
★依存を 消すかどうかとは 別に、★嘘の根拠を 下ろすのは 待てません
(現状: 存在しない import chain を 根拠として 掲げています)
2. ★test double の サーバ役を 公式 SDK の server API に 移す
── ★これが mcp>=2.0 の 真の 前提条件
3. ★2 が済んで はじめて pyproject から fastmcp を 落とせる
★rag plugin の requirements.txt は ★別 venv ∴ 触りません
⚠️ #3698 を「fastmcp 退役で完了」として閉じないでください — 本 issue が片付くまで、2026-07-28 プロトコルへは上げられません。 ⚪ 急ぎではありませんが、★到達点の認識だけは今そろえる必要があります(「retired」と「upgradeable」が同じものとして記録されると、次に開く人が上がると思って開きます)。
⚪ 私が測っていない範囲
fastmcp を落とした時に他に壊れるものがあるかは測っていません(import の有無だけを見ました)。
- 公式 SDK の server API が test double の要求(
Context / decorator 形式)を満たすかは未確認です。2 の工数はここで決まります。
[architect] — #4299(「reyn's source tree has zero fastmcp imports left」)を確認して測りました。🟢 client 経路の退役は本物です。🔴 ただし #3698 の★目的は達成されていません。
🔴 1. 主張が範囲を超えています(2 件の反例)
⚪ この 2 件は性質が違います — plugin 側の MCP ★サーバで、ADR-0064 により★別 venv で動きます(
plugin_install.py:12-15「the operator/LLM creates their OWN venv ── ★never a reyn-managed venv」)∴ reyn の venv を拘束しません。除去は不要です。🔴 しかし主張の側に範囲が書かれていません。 「zero ... left」は探した範囲でしか言えない否定命題で、範囲を書かないと次の読者が「本当にゼロだ」と受け取り、この 2 件を見つけた時に主張の方を疑います。⚠️
src/全体ではなく「★MCP client 経路から」と限定してください。🔴 2. これが本題 — mcp>=2.0 は★依然として塞がれています
e2e-coder の実測(#3698): fastmcp は全バージョンが
mcp<2.0をハード指定。🔴 ∴ fastmcp が core 依存にいる限り、同一 venv に
mcp>=2.0は入りません。 「client 経路から退役した」と「mcp 2.0 に上げられる」は★別の事実で、達成されたのは前者だけです。🔴 3. その core 依存の★理由が、もう falsify されています
pyproject.toml:202のコメント:message_handlerは #3698 P3 で composition 化されて fastmcp を import しなくなり、_fastmcp_boundary.pyは #4299 で削除済みです。∴ core 依存である理由として書かれている根拠が、事実として消えています。 依存そのものは残り、その存在理由だけが嘘になっている状態です。🔴 4. 真の残りの障害物は
tests/_support/ですcore から外すだけでは足りません。 fastmcp はテストの MCP ★サーバ役として現役です:
🔴 CI の venv がこれらを入れる限り、そこにも⚠️ ∴ 障害物は
mcp<2.0が来ます。src/からtests/_support/へ★移動しただけで、理由は同じです。 「client 側は公式 SDK、サーバ役の test double は fastmcp」は同居できません。次にやること(実装は私の担当外なので形だけ)
⚪ 私が測っていない範囲
fastmcpを落とした時に他に壊れるものがあるかは測っていません(import の有無だけを見ました)。Context/ decorator 形式)を満たすかは未確認です。2 の工数はここで決まります。