Skip to content

[FEATURE]: Surface MCP tool progress in the TUI (revive #32480 with a dedicated progress event) #49929

Open

Description

@gareag

Feature hasn't been suggested before.

  • 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.

Activity

  1. cogito-mens commented on Oct 21, 2026

    @cogito-mens

    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.

  2. opencodejr commented on Oct 28, 2026

    @opencodejr
    Contributor

    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.

    Related issues:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions