How can an MCP client learn a task advanced without polling tasks/get in a loop?
answer
- push exists, but do not trust it alone
- it rides the subscription stream, not the request
- nothing is replayed after a gap
- reconnect means re-poll
- truth lives behind the taskId
basics
~20 sA server may push notifications/tasks over a subscriptions/listen stream, so the client learns of transitions instead of polling tightly. It is optional and best-effort: a robust client still polls tasks/get after any reconnect, because a push delivered while the stream was down is simply lost.
solid answer
~40 sIn MCP revision 2026-07-28 the baseline for following a task is polling `tasks/get` with the `taskId`. The `io.modelcontextprotocol/tasks` extension additionally allows a server to push `notifications/tasks` over a `subscriptions/listen` stream, which lets a client react to a transition — a task finishing, or parking in `input_required` — without a tight poll loop. This is optional on the server's side and it is a latency optimisation, not a delivery guarantee. Revision 2026-07-28 removed stream resumability entirely: there are no SSE event ids and no `Last-Event-ID`, so a notification emitted while the client's stream was down is gone for good, and on stdio the client must re-send `subscriptions/listen` after a reconnect. The correct architecture is therefore push for responsiveness, poll as the source of truth — always re-poll `tasks/get` after reconnecting.
go deeper
Know that polling tasks/get is the way to follow a task, and that some servers can additionally push updates so you do not have to poll constantly.
Be able to say where the pushes travel — notifications/tasks on a subscriptions/listen stream, not on the original call's response stream, which already closed.
Demonstrate the distrust: pushes are optional and unreplayed after a break because 2026-07-28 removed resumability, so the design is push for latency, tasks/get for truth, always re-poll on reconnect.
Own the tuning and the budget — poll intervals scaled to expected duration, tighter around input_required where a human is blocked, and an explicit policy for how long the system follows and when it cancels.
## Two ways to follow a task The Tasks extension gives a client a `taskId` and a `tasks/get` method. Polling that method is the guaranteed way to know a task's status — it works on stdio and Streamable HTTP alike, it survives reconnects, and it requires nothing of the server beyond the extension itself. Polling has an obvious cost. A poll interval short enough to make a finished task feel instant is wasteful when the task runs for twenty minutes; an interval long enough to be cheap adds latency to every completion and, worse, to every `input_required` park where a human is waiting to be asked something. So the extension optionally allows push: a server may emit `notifications/tasks` on a `subscriptions/listen` stream. The client that has one open learns about transitions promptly and can poll lazily or on demand. ## Why the push is not a guarantee Three properties of MCP 2026-07-28 make push unreliable as a sole mechanism. **No resumability.** 2026-07-28 removed SSE event ids and `Last-Event-ID` resumability. A stream that breaks does not resume; whatever the server emitted while it was down is not replayed. A completion notification lost that way is lost permanently. **Streams must be re-established explicitly.** The listen stream is one long-lived POST that the client opens. If it drops, the client must open a new one — and on stdio the client must re-send `subscriptions/listen` after a reconnect. During the gap, transitions go unobserved. **Push is optional.** Nothing obliges a server that supports tasks to emit `notifications/tasks`. A client that only listens will simply never hear from such a server. ## The correct client architecture Treat push as a latency hint and poll as the source of truth: 1. Open a `subscriptions/listen` stream if you want low-latency updates, and react to `notifications/tasks` by fetching the authoritative state with `tasks/get`. 2. Keep a background poll on a relaxed interval — long enough to be cheap, short enough to bound how stale you can be. This is what catches everything push missed. 3. **Always poll immediately after a reconnect**, before assuming nothing happened. This is the single most important rule, and it falls straight out of the no-resumability change. 4. Never let UI state be driven solely by a notification arriving. "The task is done because I got a message" fails silently; "the task is done because `tasks/get` says `completed`" does not. ## Not to be confused with request-scoped notifications MCP 2026-07-28 has two distinct notification paths, and mixing them up is a common error. - **Request-scoped notifications** — `notifications/progress` and `notifications/message` — flow on the originating request's own response stream. They belong to a request that is still open. - **Subscription notifications** — the list-changed family, resource updates, and `notifications/tasks` — flow only on an opted-in `subscriptions/listen` stream. A task's whole point is that the originating `tools/call` returned immediately with a handle. There is no open request stream to carry progress for it, which is precisely why task pushes ride the subscription stream instead. ## Operational judgment The interesting engineering question is what poll interval to run alongside push. Some rules of thumb worth voicing in an interview: - Scale the interval to the expected duration. Polling a two-hour job every second is absurd; polling a ten-second job every minute wastes nine tenths of the user's patience. - Back off while `working`, tighten around expected transitions, and poll immediately on any push or reconnect. - Treat `input_required` as the latency-critical state. A finished task noticed a minute late is mildly annoying; a task parked waiting for a human that nobody notices for a minute stalls the whole workflow. - Bound the total wait. A client should decide how long it is prepared to follow a task at all, and `tasks/cancel` the ones it abandons so the server can release resources. ## Interview framing Name `notifications/tasks` on `subscriptions/listen` as the push path, then immediately qualify it: optional, best-effort, and unrecoverable across a stream break because 2026-07-28 removed resumability. Conclude with the architecture — push for responsiveness, `tasks/get` as truth, mandatory re-poll after reconnect. That combination of knowing the mechanism and distrusting it is what separates a senior answer here.
- Why don't task updates arrive as notifications/progress on the original request's stream?Because that stream is already gone. Request-scoped notifications like notifications/progress and notifications/message flow on the originating request's own response stream, and a task's tools/call returned immediately with a CreateTaskResult, closing it. Task pushes therefore travel on an opted-in subscriptions/listen stream, which is a separate long-lived channel.
- A client's listen stream drops for thirty seconds and comes back. What must it do?Re-establish the stream — on stdio it must re-send subscriptions/listen after a reconnect — and then poll tasks/get for every task it is following. MCP 2026-07-28 removed SSE event ids and Last-Event-ID resumability, so anything emitted during the gap is not replayed. Assuming silence means no change is the classic bug.
- Is a server that supports the tasks extension obliged to push notifications/tasks?No. The pushes are optional; polling tasks/get is the mechanism every task-supporting server must honour. A client that relies solely on notifications will follow such a server's tasks forever without noticing they finished, which is why polling has to remain the source of truth.
saying these in an interview costs you the question
- Treats notifications/tasks as a guaranteed delivery of task completion
- Expects the server to replay notifications missed while the stream was down
- Says task progress arrives as notifications/progress on the original call's stream
- Assumes every tasks-capable server pushes notifications
- Skips re-polling after a reconnect because no notification arrived