fix: FastMCP 4 denials + dual-line MCP CI - #542
Open
aimable100 wants to merge 3 commits into
Open
Conversation
FastMCP 4 requires ToolResult(is_error=True) on deny paths; keep the FastMCP 3 duck-typed wrapper. Add FastMCP 3/4 smoke jobs with major gates, expand integration smoke/matrix coverage, and isolate FastAPI config tests.
Runtime - Denials are a real ToolResult subclass on every FastMCP line: FastMCP 4 only normalizes ToolResult returns, and FastMCP's bundled caching / response-limiting middleware read .content / .structured_content directly. to_mcp_result() always emits isError=True; is_error is set where ToolResult has it (>= 3.4). Replaces the duck-typed wrapper and the per-call try/except TypeError probe with one import-time constant. - Merge request_context.meta under params.meta whenever params.meta lacks "tenuo". FastMCP 4 stamps only _meta.fastmcp.version on the middleware params for version-pinned calls, which previously hid the warrant and denied the call. - Add _compat.tool_input_schema() (SDK 2.x input_schema / 1.x inputSchema, dict-only) and use it in both the client and the LangChain bridge. The previous attribute-order change stripped every argument for duck-typed tools and left the LangChain bridge reading an empty schema on MCP 2.x. Tests - Contract test asserts the ToolResult shape on all lines; new test for the version-pinned meta merge; restore trailing newline (ruff W292); print installed versions from distribution metadata only (no namespace package AttributeError). CI - Compatibility matrix: build a wheel instead of `maturin develop` (which needs an activated venv), add rust-cache, and replace the mis-indented heredoc with scripts/check_installed_majors.py, shared with the mcp-smoke lanes. - mcp-smoke: FastMCP 3 lane installs latest 3.x (the 3.2.1 floor runs in the weekly matrix); share one rust-cache across legs; single pytest run.
- test_mcp_fastmcp_middleware: import tenuo.mcp._compat after the importorskip guards (it loads mcp.types); Python 3.9 cells no longer error at collection. - Compatibility matrix minimum lanes: pin httpx<0.28 for fastapi 0.100 / starlette 0.27 (TestClient still passes app=), and install the floors the code actually needs instead of 1.0/1.1. - Raise declared floors to match reality: tenuo[mcp]/tenuo[fastmcp] need mcp>=1.9.4 (streamable-HTTP transport yields the get_session_id triple; CallToolRequestParams.meta), tenuo[crewai] needs crewai>=1.5 (crewai.hooks). Probed 1.6.0-1.12.0 and 1.1.0-1.8.0 respectively. - Fix the stale "requires crewai>=0.80.0" message in tenuo.crewai and the CrewAI examples; update docs/compatibility-matrix.md and CHANGELOG.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
ToolResult(is_error=True)on 4.x; keep the FastMCP 3 duck-typedto_mcp_result()wrapper.mcp-smokeinto FastMCP 3 (mcp1.x) and FastMCP 4 (mcp2.x) CI jobs with major-version install gates so CrewAI’s MCP 1.x pin cannot hide regressions.Test plan
MCP Smoke (FastMCP 3)andMCP Smoke (FastMCP 4)both greentest_denial_return_matches_fastmcp_toolresult_contractpasses on both lines