Skip to content

fix(mcp): make the [mcp] extra installable and the server constructible - #388

Open
phaestos2501 wants to merge 1 commit into
JackHopkins:mainfrom
phaestos2501:fix/declare-fastmcp-dependency
Open

fix(mcp): make the [mcp] extra installable and the server constructible#388
phaestos2501 wants to merge 1 commit into
JackHopkins:mainfrom
phaestos2501:fix/declare-fastmcp-dependency

Conversation

@phaestos2501

Copy link
Copy Markdown

Problem

Three issues prevent the MCP server from starting from a fresh pip install .[mcp]:

  1. fastmcp is undeclared. fle/env/protocols/_mcp/__init__.py and fle/mcp_dataloader.py import it, but the mcp extra only lists mcp[cli] and dulwich, so the package falls into the (broken, see 3) fallback path.
  2. Unpinned mcp resolves to 2.0, which removed McpError from mcp.shared.exceptions and breaks fastmcp at import (fastmcp 2.14 only requires mcp>=1.24 with no upper bound).
  3. Server construction fails and the fallback crashes. Current fastmcp releases removed the dependencies constructor kwarg, so FastMCP(..., dependencies=[...]) raises TypeError — which the except ImportError guard doesn't catch. And when fastmcp is genuinely missing, the module still crashes on mcp.lifespan = fle_lifespan with mcp = None. Additionally, fastmcp only honours a lifespan passed to the constructor (stored in _lifespan at init), so the post-hoc attribute assignment was silently ignored even when it didn't crash — sessions would run without the Factorio lifecycle manager.

Fix

  • Declare fastmcp>=2.14.0 and pin mcp[cli]>=1.24.0,<2 in the mcp extra.
  • Define fle_lifespan before the server is created and pass it as the lifespan constructor kwarg (its late-bound module globals resolve by the time a session starts). The no-fastmcp fallback now imports cleanly with mcp = None.

Verification

  • uv pip install -e '.[mcp]' resolves and installs (previously missing fastmcp entirely).
  • FastMCP('probe', lifespan=fle_lifespan) constructs and _lifespan is wired.
  • Fallback path verified by blocking the fastmcp import: module imports cleanly with mcp = None.
  • Full end-to-end (tools served against a running cluster) not yet exercised: importing the package eagerly builds FactorioMCPState at import time, which requires live Factorio containers — arguably its own issue. A fresh install additionally hits the a2a-sdk 1.x API break addressed by Fixes related to dependencies #372.

🤖 Generated with Claude Code

Three problems prevented the MCP server from ever starting from a
fresh install of .[mcp]:

- fastmcp is imported by fle/env/protocols/_mcp and fle/mcp_dataloader
  but was not declared anywhere; declare it in the mcp extra.
- Unpinned, pip resolves mcp 2.0, which removed McpError and broke
  fastmcp (fastmcp 2.14 only requires mcp>=1.24 with no upper bound);
  pin mcp[cli]>=1.24,<2.
- FastMCP removed the 'dependencies' constructor kwarg, so creating
  the server raised TypeError; and the previous fallback crashed on
  'mcp.lifespan = fle_lifespan' with mcp=None when fastmcp was
  missing. Worse, fastmcp only honours a lifespan passed to the
  constructor (it stores it in _lifespan at init), so the attribute
  assignment was silently ignored even when it did not crash. Define
  fle_lifespan before the server is created and pass it as the
  lifespan kwarg; late-bound module globals resolve by the time the
  session starts.

Note: importing the package still requires running Factorio
containers because _mcp/init.py builds FactorioMCPState eagerly at
import time, and a fresh install additionally hits the a2a-sdk 1.x
API break addressed by PR JackHopkins#372.
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