fix(mcp): handle sync OR async fastmcp Context.get_state/set_state#87
Merged
Conversation
#86 awaited get_state/set_state unconditionally, which fixed local fastmcp 3.x but broke on FastMCP Cloud: the hosted runtime pins a fastmcp where those are still sync, so `await ctx.get_state(...)` raised `object NoneType can't be used in 'await' expression` on every tool call. the installed fastmcp version doesn't govern the hosted runtime, so detect the calling convention instead of assuming it: - add `_maybe_await()` — awaits the return value only if it's awaitable - route every `ctx.get_state(...)` (client.py) and `ctx.set_state(...)` (middleware.py) through it - regression tests now parametrize over `_FakeAsyncContext` (3.x) AND `_FakeSyncContext` (2.x / hosted); the sync variants fail on the bare-await code and pass with `_maybe_await` (verified by reverting) full suite: 166 passed; prek (ruff/ty/mdxify) clean and idempotent. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
Follow-up to #86.
#86 fixed the fastmcp-3 async
get_state/set_statebug locally, but FastMCP Cloud (the hostedpdsx-by-zzstoatzz.fastmcp.appdeploy) pins a fastmcp where those methods are still sync — soawait ctx.get_state(...)flipped the failure mode to:i.e. every tool was still broken on the deployed server, just with a different error. The installed fastmcp version doesn't govern the hosted runtime, so the fix can't assume either convention.
fix
_maybe_await(value)— awaits only ifinspect.isawaitable(value), else returns as-isctx.get_state(...)(client.py) andctx.set_state(...)(middleware.py) through ittests
_FakeAsyncContext(3.x) and_FakeSyncContext(2.x / hosted). The sync variants reproduce the cloudawait Noneerror — verified they fail on the bare-await code and pass with_maybe_await.🤖 Generated with Claude Code