Repository navigation
Move to fastmcp 4.1 and accept its is_error truncation argument - #136
Merged
Merged
Conversation
why: 0.12.22 records workspace-member default groups and dependency-group Python requirements in the lockfile, checks unchanged requirements against the existing lockfile hashes on relock, and adds CPython 3.13.16 and 3.14.8 (with 3.10.22, 3.11.17, 3.12.15). 0.12.23 rejects alternate sources for workspace members across conflicting dependency selections, which had produced uninstallable lockfiles. The span carries no breaking change and no security fix. CI does not read this pin (setup-uv has no version-file), so it moves local runs only. `uv lock --dry-run` under 0.12.23 reports no lockfile changes. 0.12.24 (2026-10-08) and 0.13.0 (2026-10-09, breaking: default Python 3.15, new cache format) stay excluded by the 3-day cooldown until 2026-10-11 and 2026-10-12. what: - .tool-versions: uv 0.12.21 -> 0.12.23 See also: - https://github.com/astral-sh/uv/releases/tag/0.12.22 - https://github.com/astral-sh/uv/releases/tag/0.12.23 - https://github.com/astral-sh/uv/blob/0.12.23/CHANGELOG.md
why: 0.16.10's stable changes are lower memory use for diagnostics and a language-server hardening that stops running `uv format` in untrusted workspaces; the new UP052 rule is preview-only. `ruff check --show-settings` shows preview disabled here. `ruff check .` and `ruff format --check .` produce identical output under 0.16.9 and 0.16.10 in this tree, so no diagnostics or reformatting land. ruff 0.17.0 (published 2026-10-09T19:46Z) changes the default target version and default rule set; it stays excluded by the 3-day cooldown until 2026-10-12, and its floor move is /ruff:bump's job. what: - uv.lock: ruff 0.16.9 -> 0.16.10 via `uv lock --upgrade-package ruff`; no other entry moves - the ruff floor in pyproject.toml is untouched See also: https://github.com/astral-sh/ruff/releases/tag/0.16.10
why: 2.4.0 turns on the native parser by default (built on the Ruff parser; the legacy parser stays behind --no-native-parser until its planned removal in early 2027). The native parser ignores `# type:` comments on for and with targets and infers those types instead. Parallel checking (-n / num_workers) leaves experimental status but stays off by default, and Python 3.15 code (PEP 661 sentinels, PEP 810 lazy imports, PEP 798 comprehension unpacking) is now checked. No error code changes and no Python version is dropped. `uv run mypy .` reports no issues in 71 source files under both 2.3.1 and 2.4.0. No for/with target here carries a `# type:` comment. what: - uv.lock: mypy 2.3.1 -> 2.4.0 via `uv lock --upgrade-package mypy`; no other entry moves See also: https://github.com/python/mypy/blob/v2.4.0/CHANGELOG.md
why: ast-serialize is the mypyc binding behind mypy's native parser. mypy 2.4.0 accepts >=0.11.2,<1.0.0, so this move is not forced by the mypy bump and lands on its own as a 0.x minor. 0.12.0 allows a colon in error codes (#94); 0.12.1 fixes parsing a plain None type inside a string annotation (#96). The project publishes no release notes; the compare view is the record. `uv run mypy .` output is unchanged. what: - uv.lock: ast-serialize 0.11.2 -> 0.12.1 See also: - mypyc/ast_serialize@v0.11.2...v0.12.1 - https://pypi.org/project/ast-serialize/0.12.1/
why: FastMCP 4.1.0 (PrefectHQ/fastmcp#5309) makes ResponseLimitingMiddleware.on_call_tool call _truncate_to_result(text, meta=..., is_error=...) so the base class keeps the error flag on the result it builds. Our override did not accept is_error, so on 4.1.0 an oversized error result raised a TypeError and mypy reported an incompatible override. The on_call_tool restoration stays because the declared floor, fastmcp>=4.0.2, still admits releases whose base class drops the flag. what: - Add is_error: bool = False to TailPreservingResponseLimitingMiddleware._truncate_to_result and pass it to all three ToolResult returns - Update the class docstring: 4.1.0 forwards the flag itself, and on_call_tool restores it for older releases See also: PrefectHQ/fastmcp#5309
why: fastmcp is exempt from the cooldown here on purpose, so its
releases land as they ship. 4.0.11 is a security and bug-fix release
(SSE Host/Origin protection, auth on component-manager routes, OpenAPI
components send only declared arguments, bounded schema nesting).
4.1.0 restores full Python 3.15 support and tightens four behaviours:
MultiAuth client IDs are qualified by source, regex tool search uses
Pydantic's regex engine (no lookarounds or backreferences), skill files
must resolve inside their configured directories, OpenAPI path
parameters reject `.` and `..`; HTTP sessions now expire after the MCP
SDK's 30-minute idle default. mcp 2.3.0 requires httpx2>=2.10, rejects
an invalid x-mcp-header annotation at tool registration, stops sending
empty _meta and params (ctx.meta is None rather than {}), and omits
`experimental` from initialize when none is configured.
The server runs over stdio only (server.run(transport="stdio")), so
the HTTP, auth, OpenAPI and SSE items do not reach it, and the source
uses no ctx.meta, skills provider or regex tool search. 4.1.0 also
forwards is_error to ResponseLimitingMiddleware._truncate_to_result;
the previous commit adapts the override in middleware.py. The full
suite passes on this lock.
fastmcp-slim 4.1.0 requires beartype>=0.23.0rc2 on Python >= 3.15, so
the lock gains a 3.15-only fork on beartype 0.23.0rc2 while 3.10-3.14
stay on 0.22.9. beartype 0.23.0 final (published 2026-10-10) clears
the 3-day cooldown on 2026-10-13; a relock after that replaces the rc.
openapi-pydantic 0.5.1 -> 0.6.0 comes with fastmcp-slim[server]; it
drops Python 3.8 and adds OpenAPI 3.1.2, and nothing here imports it.
what:
- uv.lock: fastmcp 4.0.10 -> 4.1.0
- uv.lock: fastmcp-slim 4.0.10 -> 4.1.0
- uv.lock: mcp 2.2.0 -> 2.3.0
- uv.lock: mcp-types 2.2.0 -> 2.3.0
- uv.lock: openapi-pydantic 0.5.1 -> 0.6.0
- uv.lock: beartype 0.23.0rc2 added for python>=3.15
See also:
- https://github.com/PrefectHQ/fastmcp/releases/tag/v4.0.11
- https://github.com/PrefectHQ/fastmcp/releases/tag/v4.1.0
- https://github.com/modelcontextprotocol/python-sdk/releases/tag/v2.3.0
- https://github.com/mike-oakley/openapi-pydantic/releases/tag/v0.6.0
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #136 +/- ##
=======================================
Coverage 86.81% 86.81%
=======================================
Files 46 46
Lines 3899 3899
Branches 587 587
=======================================
Hits 3385 3385
Misses 360 360
Partials 154 154 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
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.
Moves the lock to fastmcp 4.1.0 and adapts
TailPreservingResponseLimitingMiddlewareto the signature change that release makes. The branch also carries this round's toolchain and lint/type-check bumps (uv, ruff, mypy, ast-serialize) and a bulk lock refresh.Root cause
fastmcp 4.1.0 (PrefectHQ/fastmcp#5309, fixing #5304) changes
ResponseLimitingMiddleware.on_call_toolto callself._truncate_to_result(text, meta=result.meta, is_error=result.is_error), and the base_truncate_to_result(self, text, meta=None, is_error=False)now setsis_erroron theToolResultit builds. Our override insrc/libtmux_mcp/middleware.pydid not acceptis_error, so on 4.1.0:TypeError: ... got an unexpected keyword argument 'is_error'.Changes
is_error: bool = Falseand passes it to all threeToolResultreturns. The class docstring notes that 4.1.0 forwards the flag itself.on_call_toolrestoration stays: the declared floor,fastmcp>=4.0.2, still admits releases whose base class drops the flag.The server runs over stdio only, and the source uses no
ctx.meta, skills provider, or regex tool search, so the other 4.1.0 and mcp 2.3.0 tightenings (HTTP sessions, auth, OpenAPI, SSE) do not reach it. No tool, resource, prompt, or configuration variable changes, so there is noCHANGESentry.Test evidence
tests/test_middleware.py::test_response_limiter_preserves_error_resultsfails foroversized_error_keeps_flagandoversized_success_not_marked_errorwith theTypeErrorabove.Commits
.tool-versions(uv) uv 0.12.21 -> 0.12.23py(deps[dev]) ruff 0.16.9 -> 0.16.10py(deps[dev]) mypy 2.3.1 -> 2.4.0py(deps[dev]) ast-serialize 0.11.2 -> 0.12.1mcp(fix[middleware]): Accept is_error argumentpy(deps) fastmcp 4.0.10 -> 4.1.0, mcp 2.2.0 -> 2.3.0py(deps) Bump packages