Commit bb1f7c1
committed
RequestContext not captured in QueryBand on FastMCP 3.x
When the dependency was upgraded from FastMCP 2.x to 3.x, set_state and get_state became async and required JSON-serializable values by default.
This introduced two silent bugs that caused request_context to always be None (or an unawaited coroutine) when building the Teradata QueryBand, so no per-request fields (REQUEST_ID, SESSION_ID, TENANT, etc.) were ever set.
Bug 1 — serialization failure (middleware.py):
set_state was called with serializable=True (default), but RequestContext is a plain Python dataclass, not JSON-serializable. FastMCP raised a TypeError that was silently swallowed by the except-at-debug-level block, so the state was never stored. Fixed by passing serializable=False to both set_state calls, routing the value into the request-scoped in-memory dict (_request_state) instead of the persistent store.
Bug 2 — async/thread boundary (factory.py, app.py):
execute_db_tool is a sync function dispatched via asyncio.to_thread. From
inside a worker thread, calling the async get_state without await returns a coroutine object rather than the actual value. Fixed by capturing request_context in the async _mcp_tool (before thread dispatch) using a
new _fetch_request_context() helper that properly awaits get_state, then injecting it as _request_context into the executor kwargs. execute_db_tool now pops _request_context from kwargs directly instead of calling get_context()/get_state() from the thread. The now-unused get_context import is removed from app.py.1 parent 893d176 commit bb1f7c1
3 files changed
Lines changed: 18 additions & 9 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
27 | 27 | | |
28 | 28 | | |
29 | 29 | | |
30 | | - | |
31 | 30 | | |
32 | 31 | | |
33 | 32 | | |
| |||
318 | 317 | | |
319 | 318 | | |
320 | 319 | | |
| 320 | + | |
321 | 321 | | |
322 | 322 | | |
323 | 323 | | |
| |||
334 | 334 | | |
335 | 335 | | |
336 | 336 | | |
337 | | - | |
338 | | - | |
339 | 337 | | |
340 | 338 | | |
341 | 339 | | |
| |||
359 | 357 | | |
360 | 358 | | |
361 | 359 | | |
362 | | - | |
363 | | - | |
364 | 360 | | |
365 | 361 | | |
366 | 362 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
74 | 74 | | |
75 | 75 | | |
76 | 76 | | |
77 | | - | |
| 77 | + | |
78 | 78 | | |
79 | 79 | | |
80 | 80 | | |
| |||
197 | 197 | | |
198 | 198 | | |
199 | 199 | | |
200 | | - | |
| 200 | + | |
201 | 201 | | |
202 | 202 | | |
203 | 203 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
5 | 16 | | |
6 | 17 | | |
7 | 18 | | |
| |||
48 | 59 | | |
49 | 60 | | |
50 | 61 | | |
51 | | - | |
| 62 | + | |
| 63 | + | |
52 | 64 | | |
53 | 65 | | |
54 | 66 | | |
55 | 67 | | |
56 | | - | |
| 68 | + | |
| 69 | + | |
57 | 70 | | |
58 | 71 | | |
59 | 72 | | |
| |||
0 commit comments