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
[FEATURE]: Surface MCP tool progress in the TUI (revive #32480 with a dedicated progress event) #49929
I have verified this feature I'm about to request hasn't been suggested before.
Describe the enhancement you want to request
MCP servers commonly emit notifications/progress for long-running tools (30–180 s search over a large index, reindex, etc.). Since #32477 the client receives those notifications and resets the per-request timeout, but nothing is shown in the UI: the tool card keeps a bare spinner, so users can't tell "working" from "hung". Verified on 1.18.31 against a local streamable-http server — the server sees _meta.progressToken and its notifications are delivered, the TUI just ignores them.
What I'd like: render the running tool's progress in the TUI (e.g. In progress [N/M] · message on the tool card), using a dedicated event so it isn't confused with streamed partial tool output (session.next.tool.progress).
Prior art: #26328 (design + plan, closed by the stale bot) and #32480 (implementation, auto-closed during PR cleanup — the open question there was exactly the event name). Happy to rebase #32480 with a renamed event if a maintainer confirms the shape.
Confirmed on v2.1.2 and dev HEAD. The current state, for the record — packages/core/src/mcp/client.ts:349-360:
callTool: (input)=>request("call MCP tool",(signal)=>client.callTool({name: input.name,arguments: input.args??{}, ... },// Requesting progress keeps long calls alive under the SDK's timeout; execution is the hard wall.{ signal,timeout: execution,onprogress: ()=>{}},),).pipe(Effect.map(toCallToolResult)),
The token is requested, a spec-compliant server emits notifications/progress, the SDK matches them to the registered handler — a literal () => {} — and the message evaporates before anything UI-side sees it.
One correction to the issue body: "since #32477 the client resets the per-request timeout" doesn't hold on dev HEAD. #32477 touched packages/opencode/src/mcp/catalog.ts, the pre-v2 tree, which is gone; no call site in the v2 tree sets resetTimeoutOnProgress, so the SDK's per-request timer never actually resets on progress. The 12-hour execution default makes that mostly moot, but the comment on line 357 overstates what the no-op does.
An angle the earlier reports didn't cover, from the use case that drove me here: it's not only the user who is blind mid-run — the agent is too. My MCP server executes Ansible playbooks (minutes-long runs, progress per play and per task: TASK [Configure nginx] …). With no progress surface, the model can't tell a stuck run from a slow one; when the final answer was too large for its context, the agent's fallback was to re-run the playbook ten times with different tags to locate the changed tasks — an expensive workaround for missing mid-call visibility. (We've since put a server-side query tool over the run logs to stop that bleeding; the client surface is the right fix.)
On the open question from #32480 (the event name): a dedicated event distinct from streamed partial output sounds right — progress is not partial output, and conflating them breaks exactly the long-running case.
Happy to test a PR against the Ansible MCP server — a real long-running, progress-emitting workload is already set up here.
Thanks for the clear write-up and the links to the earlier attempts!
To restate it: you'd like the TUI to show a running MCP tool's notifications/progress on its tool card (e.g. In progress [N/M] · message), so a long call is clearly working rather than hung.
This also applies to v2. On the current dev branch, callTool in packages/core/src/mcp/client.ts still passes a no-op onprogress. That keeps long calls from timing out, but the progress messages themselves are discarded. v2 already has an ephemeral session.tool.progress event that carries live metadata for a running tool, so the open design question is still the one from #32480: reuse that event's metadata or add a dedicated progress field or event. Maintainers will consider the request and which shape they'd want before a PR.
Activity
cogito-mens commentedon Oct 21, 2026
Confirmed on v2.1.2 and dev HEAD. The current state, for the record —
packages/core/src/mcp/client.ts:349-360:The token is requested, a spec-compliant server emits
notifications/progress, the SDK matches them to the registered handler — a literal() => {}— and the message evaporates before anything UI-side sees it.One correction to the issue body: "since #32477 the client resets the per-request timeout" doesn't hold on dev HEAD. #32477 touched
packages/opencode/src/mcp/catalog.ts, the pre-v2 tree, which is gone; no call site in the v2 tree setsresetTimeoutOnProgress, so the SDK's per-request timer never actually resets on progress. The 12-hourexecutiondefault makes that mostly moot, but the comment on line 357 overstates what the no-op does.An angle the earlier reports didn't cover, from the use case that drove me here: it's not only the user who is blind mid-run — the agent is too. My MCP server executes Ansible playbooks (minutes-long runs, progress per play and per task:
TASK [Configure nginx] …). With no progress surface, the model can't tell a stuck run from a slow one; when the final answer was too large for its context, the agent's fallback was to re-run the playbook ten times with different tags to locate the changed tasks — an expensive workaround for missing mid-call visibility. (We've since put a server-side query tool over the run logs to stop that bleeding; the client surface is the right fix.)On the open question from #32480 (the event name): a dedicated event distinct from streamed partial output sounds right — progress is not partial output, and conflating them breaks exactly the long-running case.
Happy to test a PR against the Ansible MCP server — a real long-running, progress-emitting workload is already set up here.
opencodejr commentedon Oct 28, 2026
Thanks for the clear write-up and the links to the earlier attempts!
To restate it: you'd like the TUI to show a running MCP tool's
notifications/progresson its tool card (e.g.In progress [N/M] · message), so a long call is clearly working rather than hung.This also applies to v2. On the current
devbranch,callToolinpackages/core/src/mcp/client.tsstill passes a no-oponprogress. That keeps long calls from timing out, but the progress messages themselves are discarded. v2 already has an ephemeralsession.tool.progressevent that carries live metadata for a running tool, so the open design question is still the one from #32480: reuse that event's metadata or add a dedicated progress field or event. Maintainers will consider the request and which shape they'd want before a PR.Related issues: