Skip to content

fix(runtime): bound per-toolset tool listing during startup (#3137)#3154

Merged
dgageot merged 1 commit into
mainfrom
fix/3137-tool-listing-timeout
Jun 17, 2026
Merged

fix(runtime): bound per-toolset tool listing during startup (#3137)#3154
dgageot merged 1 commit into
mainfrom
fix/3137-tool-listing-timeout

Conversation

@Sayt-0

@Sayt-0 Sayt-0 commented Jun 17, 2026

Copy link
Copy Markdown
Member

Fixes #3137.

what

emitToolsProgressively called toolset.Tools(ctx) with no timeout, so if a toolset's Tools() blocked forever (e.g. a wedged MCP stdio server that never answers tools/list), startup tool loading never finished. The terminal ToolsetInfo{Loading:false} was never sent, so the sidebar stayed on "Loading tools..." and EmitStartupInfo's goroutine leaked.

This adds listToolsWithTimeout, which runs Tools() in a goroutine and bounds it with a per-toolset deadline (default 10s, configurable via WithToolListTimeout). I went with goroutine + select instead of a plain context timeout because the MCP client detaches ctx with WithoutCancel, so a wedged server might not honor cancellation. A timed-out toolset is skipped with a warning, and the terminal ToolsetInfo is always sent so the sidebar resolves and shows whatever loaded fine. The toolset is not torn down, so a slow-but-responsive one is listed again on the next turn.

how it maps to the issue

the issue lists three expected behaviours:

  1. per-toolset timeout, skip with a warning: done
  2. sidebar shows the tools that loaded, not an infinite spinner: done
  3. /quit exits promptly: mostly. the leaked startup goroutine that blocked it is gone now that EmitStartupInfo returns. i left the 30s stopToolSets bound alone since the issue lists it as "consider" and lowering it risks cutting off a legit graceful shutdown. happy to do it as a follow-up if you'd prefer.

possible follow-up (not in this PR)

a server that wedges during initialize/Start() would stall startup the same way, and that path is also unbounded (Connect detaches ctx, the supervisor has no connect deadline). the same pattern would fix it. kept it out here to stay close to the issue's stated root cause (Tools()).

test

added TestEmitStartupInfo_SkipsToolsetWhoseListingHangs (passes under -race). also reproduced by hand: hangs before, resolves after, using a hung toolset plus a tiny MCP stdio server that finishes initialize then never answers tools/list.

emitToolsProgressively called toolset.Tools(ctx) with no timeout, so a
toolset whose Tools() blocks forever (for example a wedged MCP stdio
subprocess that never answers tools/list) prevented the loop from ever
sending its terminal ToolsetInfo{Loading:false}. The sidebar stayed on
"Loading tools..." forever and EmitStartupInfo's goroutine leaked.

Add listToolsWithTimeout: it runs Tools() in a goroutine and selects on a
per-toolset deadline, so even a toolset that ignores context cancellation
cannot stall startup. A timed-out toolset is skipped with a warning and the
terminal ToolsetInfo is still sent, so the sidebar resolves and shows the
tools that loaded. Timeout defaults to 10s, configurable via
WithToolListTimeout.
@Sayt-0 Sayt-0 requested a review from a team as a code owner June 17, 2026 08:40
@aheritier aheritier added area/agent For work that has to do with the general agent loop/agentic features of the app area/mcp MCP protocol, MCP tool servers, integration kind/fix PR fixes a bug (maps to fix: commit prefix) labels Jun 17, 2026
@docker-agent

Copy link
Copy Markdown

PR Review Failed — The review agent encountered an error and could not complete the review. View logs.

@Sayt-0 Sayt-0 requested a review from docker-agent June 17, 2026 15:12
@docker-agent

Copy link
Copy Markdown

PR Review Failed — The review agent encountered an error and could not complete the review. View logs.

@dgageot dgageot merged commit b1ff7cf into main Jun 17, 2026
13 checks passed
aheritier added a commit that referenced this pull request Jun 19, 2026
@rumpl rumpl deleted the fix/3137-tool-listing-timeout branch June 19, 2026 21:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/agent For work that has to do with the general agent loop/agentic features of the app area/mcp MCP protocol, MCP tool servers, integration kind/fix PR fixes a bug (maps to fix: commit prefix)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Tool loading hangs indefinitely when a toolset's Tools() blocks — sidebar "Loading tools…" never resolves and /quit shutdown delays

4 participants