You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Inspector times out when FastMCP tool emits ctx.info/ctx.report_progress (v2.2.0, LEGACY/STDIO) #2028
v2 — current (@modelcontextprotocol/inspector@latest)
Which client?
Web
Inspector version
2.2.0
Node version
v26.5.0
Operating system (and browser, for the web client)
MacOS 26.5.2
Transport
stdio
MCP server under inspection
Server: FastMCP local Python server (server.py)
Command used: fastmcp dev inspector server.py
Transport: stdio
Protocol era: legacy
OAuth: no
Note: Same server/code works via Claude Desktop; timeout is observed via Inspector path.
Steps to reproduce
Fresh launch Inspector using fastmcp dev inspector server.py.
Connect to the local server over stdio.
Open the Tools tab.
Run slow_task (example input: steps=5) where the tool calls ctx.report_progress(...) and ctx.info(...) in a loop.
Observe progress/log lines appear during execution.
Final result does not return; Inspector shows Tool Error: Request timed out.
Expected behavior
Tool should complete and return its final result in Inspector UI, while still allowing mid-execution context notifications (ctx.report_progress(...) / ctx.info(...)).
Actual behavior
When ctx.report_progress() or ctx.info() is invoked, Inspector eventually shows Tool Error: Request timed out, even though server-side execution appears to finish successfully.
If Context is injected but unused (or no Context calls are made), the tool returns normally.
Logs, errors, or screenshots
Error shown in Inspector UI: Tool Error: Request timed out
Environment:
Inspector version: 2.2.0
Node.js: v26.5.0
OS: macOS 26.5.2
Transport: stdio
Era: legacy
I can provide additional Protocol/Network logs if maintainers want specific traces.
Already prototyped a fix?
No fix prototyped yet.
Before you submit
I searched existing issues and this is not a duplicate.
This is not a security vulnerability report (those go through the private advisory process).
Thanks — I installed and checked badgr-mcp-doctor usage.
Its required mode is --url <sse-url> (SSE endpoint), but my repro is on stdio transport in Inspector (legacy era), not SSE.
badgr-mcp-doctor --help output indicates URL/SSE-based diagnostics only.
Could you share the exact command/flags you want for a stdio-based repro, or should I reproduce this against an SSE endpoint and report that result instead?
Severity 4 — a tool that emits progress or log notifications never returns its result, so the Inspector reports a timeout for a call that completed on the server
Urgency 3 — wanted this milestone; FastMCP's ctx.report_progress / ctx.info are widely used
Bonuses: +1 bug label
The Protocol/Network traces offered above would help — please do attach them.
Board: #28, Status Incoming (awaiting maintainer review — no milestone yet).
@Avi-Jadhav03 Thanks for the trace — it's more useful than my timeout suggestion above, which I now think is wrong. Disregard it: your own trace argues against it.
Reading your excerpt:
t
event
23.013
client → tools/callid 8, _meta.progressToken: 8
23.042
server → notifications/message ("Starting task")
23.044
server → response with id: 7, result "Got 2"
24:23.019
client → notifications/cancelled for requestId 8, "Request timed out"
The server answered 31 ms after the request, so nothing was actually slow — raising Request Timeout would only make it hang longer before the same error.
The response carries id: 7 against a request of id: 8. The SDK matches responses to requests by id, so request 8 never resolves and falls through to the default 60 s timeout (your requestTimeout is 0, meaning the SDK's DEFAULT_REQUEST_TIMEOUT_MSEC) — which is exactly the 60.006 s gap in the trace.
Two details from the Inspector side that fit this and rule out some alternatives:
resetTimeoutOnProgress and progress both default to true, and we wire a per-request onprogress. If genuine notifications/progress were arriving in a loop, the deadline would keep sliding and could not fire at a clean 60 s. That it did suggests no progress notification was ever correlated with request 8.
The _meta.progressToken: 8 is the SDK stamping the message id, so the request really was id 8 on the wire.
Before we dig further, could you narrow it in two ways?
Reproduce without fastmcp dev.fastmcp dev inspector server.py puts FastMCP's dev wrapper between the Inspector and your server — an extra hop, and the most plausible place for a request id to be rewritten. Please launch the Inspector on its own and point a stdio server entry directly at python server.py.
Attach the exported Protocol log (the JSON export from the Protocol tab) rather than a retyped excerpt — an off-by-one id is exactly the kind of thing that can slip in during transcription, and it's the whole finding here.
If id: 7 vs id: 8 survives a direct stdio connection, it's real and we'll chase it. If it disappears, the wrapper is the culprit and this belongs upstream with FastMCP.
Moving this to v2.7.0 in the meantime, since it's waiting on the repro rather than on us.
Thanks — makes sense. I’ll retest with a direct stdio connection (Inspector launched separately, server command set to python server.py, no fastmcp dev wrapper) and attach the raw Protocol JSON export from the Protocol tab.
Good question. This was my first time testing this exact pattern (ctx.info / ctx.report_progress during a tool call), so I can’t yet confirm a regression window.
I reproduced it consistently on Inspector v2.2.0, including direct stdio (no fastmcp dev wrapper), and attached protocol exports above.
If useful, I can run a quick version matrix (e.g., v2.1.x vs v2.2.0 vs latest) and report back to identify whether this is a regression.
Finding: delayed responses and Inspector timeouts in direct stdio
From an exported protocol trace taken in a fresh direct-stdio session:
Request
Server response duration
Inspector result
resources/list
~39 ms
Returned normally
tools/list
~108,561 ms
Cancelled by Inspector after ~60 s
prompts/list
~108,566 ms
Cancelled by Inspector after ~60 s
resources/templates/list
~108,571 ms
Cancelled by Inspector after ~60 s
The UI reflects this: Resources may appear immediately, while Tools and Prompts initially show Request timed out. Their responses can arrive much later.
steps is not used for any work or delay; all values execute the same code.
Observed protocol timings:
Call
Server response duration
Inspector result
slow_task_v4(steps=3)
~44,013 ms
Result displayed
slow_task_v4(steps=5)
~141,222 ms
Cancelled after ~60 s
slow_task_v4(steps=1)
~104,115 ms
Cancelled after ~60 s
subtract(3, 3) afterward
~273 ms
Returned normally
In at least one direct-stdio retest, the request and response IDs matched, but Inspector still emitted notifications/cancelled at ~60 seconds. This does not appear to be solely an ID-mismatch issue.
Current conclusion
In direct stdio, Inspector sometimes delays delivery of list and tool-call responses past its ~60-second timeout, even though the FastMCP server eventually sends valid responses.
I have attached the raw protocol exports for the maintainers to inspect.
Good question. This was my first time testing this exact pattern (ctx.info / ctx.report_progress during a tool call), so I can’t yet confirm a regression window.
I reproduced it consistently on Inspector v2.2.0, including direct stdio (no fastmcp dev wrapper), and attached protocol exports above.
If useful, I can run a quick version matrix (e.g., v2.1.x vs v2.2.0 vs latest) and report back to identify whether this is a regression.
@Avi-Jadhav03 That'd actually be really useful, if you're up for it. And funny timing: manually running that kind of version matrix by hand is basically the exact problem I've been building ContractWatch around, automatically catching a regression like this across versions instead of someone having to bisect it manually after the fact. If you do run the matrix and confirm it's v2.2.0-specific, happy to set you up with a free monitor on this repo so you can see whether it would've caught it automatically, no strings attached.
Thanks for the raw Protocol exports — they were decisive, and they turned out to contain two separate problems. One is a real Inspector bug I've now fixed; the other is server-side and outside the Inspector. Splitting them:
1. Inspector bug — a progress-reporting tool times out at 60s on the web client (fixed in #2363)
The web client doesn't talk to your server directly. The browser runs the MCP Client, and its requests are relayed through the Inspector's Node backend: browser → POST /api/mcp/send → backend → your stdio server, with responses coming back over an SSE stream. That relay added two request-response waits that the CLI/TUI (which use a direct transport) don't have, and both were hardcoded to 60s and blind to notifications/progress.
The MCP SDK's own request timeout resets every time a progress notification arrives (resetTimeoutOnProgress, which the Inspector enables) — that's what lets an arbitrarily long tool keep running as long as it reports progress. But the relay's two progress-blind waits fired first and shadowed it. So a tool that calls ctx.report_progress() in a loop was cancelled at a flat 60s on the web client only, while the same tool rides out fine over the CLI/TUI and in Claude Desktop.
#2363 makes both relay waits reset on a notifications/progress whose token matches the in-flight request, exactly mirroring the SDK. Verified end-to-end against a real FastMCP stdio server over the relay: a 75-second tool that reports progress now completes instead of being cancelled at 60s.
One deliberate boundary: log messages (ctx.info → notifications/message) do not reset the deadline — the SDK and every other client treat only progress as liveness, so a tool that merely logs and genuinely runs past the request timeout still times out. If you have a long tool that legitimately needs more headroom, either emit ctx.report_progress() (now honored on web) or raise Request Timeout in Server Settings.
2. Server-side stall — not an Inspector defect
Your most recent trace shows responses arriving 44s, 104s, 141s, even 173s after the request, with the correct ids. Crucially, the server's notifications/message ("Starting task") arrives within ~80ms — over the same stdout pipe and the same SSE channel that the delayed response travels. If the Inspector's pipe or relay were buffering, the notification would be just as late as the response. It isn't. That places the delay between your server emitting the notification and flushing the response — i.e. server-side, in the ctx.info(...) → return window.
I could not reproduce that stall on the exact stack you reported (FastMCP 3.4.7, mcp 1.30.0, Python 3.14.7) across three independent paths — a raw stdio reader, the Inspector CLI, and the full web relay with a real SDK client, including a 20-round concurrent-burst stress test (max round 17ms). The slow_task_v4 server returns in single-digit milliseconds every time here. So the 44–173s you see looks specific to your host — most likely asyncio/anyio scheduling of the stdio writer on a Python 3.14 pre-release, which is consistent with your own finding that mcp.run(show_banner=False) improved reliability (a server-side toggle). For a call stalled >60s with no progress, the ~60s cancellation you saw is the SDK's default request timeout behaving correctly; #2363 does not change that (and shouldn't).
Two things would let us confirm the server side, if you're up for it:
Re-run on a stable Python (3.12 or 3.13) with the same FastMCP, and see whether the 44–173s stalls disappear.
During a stalled call, capture the server's own logs/stderr (e.g. python -X dev server.py) — that's where a blocked writer or a slow logging handler would show.
Net:#2363 fixes the ctx.report_progress timeout in the title for the web client. The ctx.info-only stalls in your traces are a server-side latency issue on your host that the fix intentionally doesn't paper over. Happy to keep digging on (2) if the stalls persist on a stable Python.
Fixed by #2363, merged to v2/main: both web-relay request-response waits now reset on notifications/progress, so a long tool that reports progress no longer times out at 60s on the web client (it already worked over the CLI/TUI). Log-only tools that genuinely run past the request timeout still time out, matching the SDK and every other client.
Closing this out for the Inspector side. The separate 44–173s server-side stalls in your traces are a FastMCP/Python-3.14 latency issue on your host, not reproducible here — if they persist on a stable Python (3.12/3.13), that's worth a fresh report (ideally with the server's own stderr during a stalled call), and I'm happy to dig in.
Activity
carter-smalls commentedon Aug 16, 2026
Looks like tool error request timed out when ctx.report_progress is called.
Use
badgr-mcp-doctorto diagnostic report showing mcp timeout cause and guidance to resolve it.That should help confirm frequency of ctx.report_progress messages causing timeout.
Avi-Jadhav03 commentedon Aug 16, 2026
Thanks — I installed and checked
badgr-mcp-doctorusage.Its required mode is
--url <sse-url>(SSE endpoint), but my repro is on stdio transport in Inspector (legacy era), not SSE.badgr-mcp-doctor --helpoutput indicates URL/SSE-based diagnostics only.Could you share the exact command/flags you want for a stdio-based repro, or should I reproduce this against an SSE endpoint and report that result instead?
cliffhall commentedon Aug 19, 2026
Triage: Priority Medium (total 8)
ctx.report_progress/ctx.infoare widely usedbuglabelThe Protocol/Network traces offered above would help — please do attach them.
Board: #28, Status
Incoming(awaiting maintainer review — no milestone yet).Avi-Jadhav03 commentedon Aug 20, 2026
Thanks — attaching protocol trace from a failed run.
Repro context
slow_task_v4{"steps": 2}8_meta.progressToken:8What the trace shows
tools/callwithid: 8.notifications/message(Starting task).id: 7(not8) containing result"Got 2".notifications/cancelledforrequestId: 8with reasonSdkError: Request timed out.Raw protocol excerpt (redacted)
[ { "timestamp": "2026-08-20T14:23:23.013Z", "direction": "request", "origin": "client", "message": { "method": "tools/call", "id": 8, "params": { "name": "slow_task_v4", "arguments": { "steps": 2 }, "_meta": { "progressToken": 8 } } } }, { "timestamp": "2026-08-20T14:23:23.042Z", "direction": "notification", "origin": "server", "message": { "method": "notifications/message", "params": { "level": "info", "data": { "msg": "Starting task" } } } }, { "timestamp": "2026-08-20T14:23:23.044Z", "direction": "response", "origin": "server", "message": { "id": 7, "result": { "content": [{ "type": "text", "text": "Got 2" }], "structuredContent": { "result": "Got 2" }, "isError": false } } }, { "timestamp": "2026-08-20T14:24:23.019Z", "direction": "notification", "origin": "client", "message": { "method": "notifications/cancelled", "params": { "requestId": 8, "reason": "SdkError: Request timed out" } } } ]Avi-Jadhav03 commentedon Sep 4, 2026
Thanks for the update. Just confirming: is this issue now targeted for v2.6.0?
Happy to retest any patch/build if needed.
cliffhall commentedon Sep 7, 2026
@Avi-Jadhav03
Have you tried increasing the Request Timeout value in the Server Settings modal for the given server?cliffhall commentedon Sep 7, 2026
@Avi-Jadhav03 Thanks for the trace — it's more useful than my timeout suggestion above, which I now think is wrong. Disregard it: your own trace argues against it.
Reading your excerpt:
tools/callid 8,_meta.progressToken: 8notifications/message("Starting task")id: 7, result"Got 2"notifications/cancelledfor requestId 8, "Request timed out"The server answered 31 ms after the request, so nothing was actually slow — raising Request Timeout would only make it hang longer before the same error.
The response carries
id: 7against a request ofid: 8. The SDK matches responses to requests by id, so request 8 never resolves and falls through to the default 60 s timeout (yourrequestTimeoutis0, meaning the SDK'sDEFAULT_REQUEST_TIMEOUT_MSEC) — which is exactly the 60.006 s gap in the trace.Two details from the Inspector side that fit this and rule out some alternatives:
resetTimeoutOnProgressandprogressboth default to true, and we wire a per-requestonprogress. If genuinenotifications/progresswere arriving in a loop, the deadline would keep sliding and could not fire at a clean 60 s. That it did suggests no progress notification was ever correlated with request 8._meta.progressToken: 8is the SDK stamping the message id, so the request really was id 8 on the wire.Before we dig further, could you narrow it in two ways?
fastmcp dev.fastmcp dev inspector server.pyputs FastMCP's dev wrapper between the Inspector and your server — an extra hop, and the most plausible place for a request id to be rewritten. Please launch the Inspector on its own and point a stdio server entry directly atpython server.py.If
id: 7vsid: 8survives a direct stdio connection, it's real and we'll chase it. If it disappears, the wrapper is the culprit and this belongs upstream with FastMCP.Moving this to v2.7.0 in the meantime, since it's waiting on the repro rather than on us.
Avi-Jadhav03 commentedon Sep 8, 2026
Thanks — makes sense. I’ll retest with a direct stdio connection (Inspector launched separately, server command set to
python server.py, nofastmcp devwrapper) and attach the raw Protocol JSON export from the Protocol tab.1 remaining item
anythingoah commentedon Sep 9, 2026
Sounds like this took a few rounds to pin down was v2.2.0 a version bump that broke something that worked before, or first time trying this pattern?
Avi-Jadhav03 commentedon Sep 9, 2026
Good question. This was my first time testing this exact pattern (
ctx.info/ctx.report_progressduring a tool call), so I can’t yet confirm a regression window.I reproduced it consistently on Inspector v2.2.0, including direct stdio (no
fastmcp devwrapper), and attached protocol exports above.If useful, I can run a quick version matrix (e.g., v2.1.x vs v2.2.0 vs latest) and report back to identify whether this is a regression.
Avi-Jadhav03 commentedon Sep 11, 2026
# Inspector stdio timeout: consolidated retest findings
Environment
MCP Inspector UI: v2.6.0
FastMCP: 3.4.7
Python: 3.14
Transport: stdio (local process)
Inspector launch command:
fastmcp dev inspectorwrapper: not usedFinding: delayed responses and Inspector timeouts in direct stdio
From an exported protocol trace taken in a fresh direct-stdio session:
resources/listtools/listprompts/listresources/templates/listThe UI reflects this: Resources may appear immediately, while Tools and Prompts initially show Request timed out. Their responses can arrive much later.
Tool-call reproduction
Tool under test:
stepsis not used for any work or delay; all values execute the same code.Observed protocol timings:
slow_task_v4(steps=3)slow_task_v4(steps=5)slow_task_v4(steps=1)subtract(3, 3)afterwardIn at least one direct-stdio retest, the request and response IDs matched, but Inspector still emitted
notifications/cancelledat ~60 seconds. This does not appear to be solely an ID-mismatch issue.Current conclusion
In direct stdio, Inspector sometimes delays delivery of list and tool-call responses past its ~60-second timeout, even though the FastMCP server eventually sends valid responses.
I have attached the raw protocol exports for the maintainers to inspect.
inspector-protocol-python-2026-09-11T15-21-17.097Z.json
Separate banner observation
I also observed connection failures with FastMCP's startup banner enabled and reliable connections with:
I have not yet completed a clean A/B reproduction for this, so I am reporting it as an observation rather than a confirmed independent issue.
anythingoah commentedon Sep 11, 2026
@Avi-Jadhav03 That'd actually be really useful, if you're up for it. And funny timing: manually running that kind of version matrix by hand is basically the exact problem I've been building ContractWatch around, automatically catching a regression like this across versions instead of someone having to bisect it manually after the fact. If you do run the matrix and confirm it's v2.2.0-specific, happy to set you up with a free monitor on this repo so you can see whether it would've caught it automatically, no strings attached.
cliffhall commentedon Sep 14, 2026
Thanks for the raw Protocol exports — they were decisive, and they turned out to contain two separate problems. One is a real Inspector bug I've now fixed; the other is server-side and outside the Inspector. Splitting them:
1. Inspector bug — a progress-reporting tool times out at 60s on the web client (fixed in #2363)
The web client doesn't talk to your server directly. The browser runs the MCP
Client, and its requests are relayed through the Inspector's Node backend:browser → POST /api/mcp/send → backend → your stdio server, with responses coming back over an SSE stream. That relay added two request-response waits that the CLI/TUI (which use a direct transport) don't have, and both were hardcoded to 60s and blind tonotifications/progress.The MCP SDK's own request timeout resets every time a progress notification arrives (
resetTimeoutOnProgress, which the Inspector enables) — that's what lets an arbitrarily long tool keep running as long as it reports progress. But the relay's two progress-blind waits fired first and shadowed it. So a tool that callsctx.report_progress()in a loop was cancelled at a flat 60s on the web client only, while the same tool rides out fine over the CLI/TUI and in Claude Desktop.#2363 makes both relay waits reset on a
notifications/progresswhose token matches the in-flight request, exactly mirroring the SDK. Verified end-to-end against a real FastMCP stdio server over the relay: a 75-second tool that reports progress now completes instead of being cancelled at 60s.One deliberate boundary: log messages (
ctx.info→notifications/message) do not reset the deadline — the SDK and every other client treat only progress as liveness, so a tool that merely logs and genuinely runs past the request timeout still times out. If you have a long tool that legitimately needs more headroom, either emitctx.report_progress()(now honored on web) or raise Request Timeout in Server Settings.2. Server-side stall — not an Inspector defect
Your most recent trace shows responses arriving 44s, 104s, 141s, even 173s after the request, with the correct ids. Crucially, the server's
notifications/message("Starting task") arrives within ~80ms — over the same stdout pipe and the same SSE channel that the delayed response travels. If the Inspector's pipe or relay were buffering, the notification would be just as late as the response. It isn't. That places the delay between your server emitting the notification and flushing the response — i.e. server-side, in thectx.info(...)→returnwindow.I could not reproduce that stall on the exact stack you reported (FastMCP 3.4.7, mcp 1.30.0, Python 3.14.7) across three independent paths — a raw stdio reader, the Inspector CLI, and the full web relay with a real SDK client, including a 20-round concurrent-burst stress test (max round 17ms). The
slow_task_v4server returns in single-digit milliseconds every time here. So the 44–173s you see looks specific to your host — most likely asyncio/anyio scheduling of the stdio writer on a Python 3.14 pre-release, which is consistent with your own finding thatmcp.run(show_banner=False)improved reliability (a server-side toggle). For a call stalled >60s with no progress, the ~60s cancellation you saw is the SDK's default request timeout behaving correctly; #2363 does not change that (and shouldn't).Two things would let us confirm the server side, if you're up for it:
python -X dev server.py) — that's where a blocked writer or a slow logging handler would show.Net: #2363 fixes the
ctx.report_progresstimeout in the title for the web client. Thectx.info-only stalls in your traces are a server-side latency issue on your host that the fix intentionally doesn't paper over. Happy to keep digging on (2) if the stalls persist on a stable Python.test: address Copilot review — tighten progress-token guard and de-fl…
test: drop an unnecessary double cast in the relay progress test help…
Merge pull request #2363 from modelcontextprotocol/v2/fix/2028-stdio-…
cliffhall commentedon Sep 14, 2026
Fixed by #2363, merged to
v2/main: both web-relay request-response waits now reset onnotifications/progress, so a long tool that reports progress no longer times out at 60s on the web client (it already worked over the CLI/TUI). Log-only tools that genuinely run past the request timeout still time out, matching the SDK and every other client.Closing this out for the Inspector side. The separate 44–173s server-side stalls in your traces are a FastMCP/Python-3.14 latency issue on your host, not reproducible here — if they persist on a stable Python (3.12/3.13), that's worth a fresh report (ideally with the server's own stderr during a stalled call), and I'm happy to dig in.
Merge origin/v2/main into v2/feat/2318-timeout-diagnostics
fix: reset the relay's request-response waits on progress notificatio…