Skip to content

fix(mcp): support fastmcp 3 and 4, parse adapter requests - #291

Merged
pontino merged 1 commit into
mainfrom
fix/fastmcp-4
Sep 18, 2026
Merged

pontino merged 1 commit into
mainfrom
fix/fastmcp-4

Conversation

@pontino

@pontino pontino commented Sep 18, 2026

Copy link
Copy Markdown
Collaborator

Supersedes #288.

Why

fastmcp 4 depends on MCP SDK 2, which renamed the protocol Tool fields inputSchema/outputSchema to snake_case. The adapter read the camelCase names, so with extras installed in CI (#290) the lint job fails on #288 with two mypy errors, and every tool listing emits a FastMCPDeprecationWarning. On MCP SDK 1 the snake_case names do not exist, so no single read satisfies the >=3,<5 range Dependabot proposed.

What

  • The adapter reads name, description, parameters and output_schema from fastmcp's own Tool, which is identical on 3.x and 4.x. The conversion to the protocol Tool is gone.
  • mcp extra constraint is fastmcp>=3,<5; lock resolves to fastmcp 4.0.5. Not a breaking change: projects pinned to fastmcp 3 keep resolving.
  • The two adapter subscriptions never passed data_type, so handlers received raw dicts and crashed on message.data. This predates the fastmcp bump. Both subscriptions now declare their request model.
  • New tests/test_mcp.py runs the adapter over the in-memory transport and covers tool listing, a successful call and an error call. It fails on the unmodified adapter with 'dict' object has no attribute 'data'.
  • Changelog under Unreleased.

Verification

  • Full suite against live Redis 7 and Redpanda, fastmcp 4.0.5: 125 passed, 0 skipped.
  • tests/test_mcp.py with -W error on fastmcp 4.0.5, 4.0.3 and 3.4.7 (Python 3.10): passed.
  • mypy with all extras, ruff check and format, poetry build and twine check: clean.

The adapter converted each fastmcp tool to the MCP protocol Tool and read
inputSchema/outputSchema. MCP SDK 2, pulled in by fastmcp 4, renamed those
fields to snake_case, so mypy fails and every listing warns. fastmcp's own
Tool exposes parameters and output_schema unchanged across both majors, so
read them directly and widen the extra to fastmcp>=3,<5.

The adapter subscriptions never passed data_type, so handlers received raw
dicts and crashed on the first attribute access. Declare the request models
on both subscriptions and add an end-to-end test over the in-memory
transport covering tool listing, a successful call and an error call.

Supersedes #288.
@github-actions

Copy link
Copy Markdown
Contributor

QualOps Code Quality Analysis

Status: ⚠️ FAILED - Critical or high severity issues found

Summary

  • Total Issues: 3
  • Critical: 0 🔴
  • High: 1 🟠
  • Medium: 1 🟡
  • Low: 1 🟢
  • Files Analyzed: 5

🟠 High Issues (1)

  • sdk/eggai/adapters/mcp/mcp.py:46 - bug
    Field tool.parameters may not exist on FastMCP Tool objects; the correct attribute is likely inputSchema or input_schema.

🟡 Medium Issues (1)

  • sdk/eggai/adapters/mcp/mcp.py:47 - bug
    Field tool.output_schema may not exist on FastMCP Tool objects, causing an AttributeError at runtime.

📊 Full Report

View detailed report


Powered by QualOps

@pontino

pontino commented Sep 18, 2026

Copy link
Copy Markdown
Collaborator Author

On the QualOps high and medium findings (tool.parameters / tool.output_schema "may not exist"):

Both attributes are declared fields on fastmcp's own Tool model in 3.x (fastmcp.tools.tool.Tool) and 4.x (fastmcp.tools.base.Tool), typed dict[str, Any] and dict[str, Any] | None. list_tools() returns FunctionTool instances, which subclass it. The protocol Tool from the MCP SDK is the one whose field names changed between majors, and the adapter no longer touches it.

Evidence:

  • tests/test_mcp.py in this PR reads both attributes through the adapter and asserts on their contents. It passed in this run on Python 3.10 to 3.13 with fastmcp 4.0.5.
  • Locally the same test passes with -W error on fastmcp 4.0.5, 4.0.3 and 3.4.7.
  • mypy with all extras is clean on both majors, which it would not be if the attributes were missing.

@pontino
pontino merged commit 48737b3 into main Sep 18, 2026
12 of 13 checks passed
@pontino
pontino deleted the fix/fastmcp-4 branch September 18, 2026 10:28
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