
This page is part of our MCP specification reference, a plain-English guide to the Model Context Protocol spec (version 2026-07-28), within The MCP Guide. Building a server? See MCP development.
Status in the 2026-07-28 spec: core (optional pattern)
Progress notifications are how an MCP server tells the AI app (the client) how far along a slow request is. The client attaches a progressToken to its request. The server can then send notifications/progress messages with a number, an optional total and an optional status message until the work is done.
Progress is optional on both sides. The progress page of the 2026-07-28 spec says the server "MAY send progress notifications to report the status of requests the client has issued." This page covers how it works, what changed in 2026, and how it relates to timeouts and the Tasks extension.
Key Takeaways
- A client asks for progress by putting a
progressTokenin the request's_meta. - The server may send
notifications/progresswithprogress, an optionaltotaland an optionalmessage. - The
progressvalue must increase with every notification, even if the total is unknown. - In 2026-07-28, only servers send progress, and only on the response stream of the request it describes.
- For jobs that take minutes or hours, the Tasks extension is a better fit than a long open request.
Why progress notifications exist
People abandon tools that look frozen. A data export, a large search or a build step may take many seconds. Without feedback, the user, the AI app and any timeout logic cannot tell "working" from "stuck."
Progress notifications give a simple, standard signal. AI apps can show a progress bar or status text. Clients can also use them to decide whether to keep waiting.
How it works
- The client opts in. It adds a
progressTokento the request's_meta. The token must be a string or integer and unique across the client's active requests. - The server reports. While working, it may send
notifications/progressmessages that reference that token. - The server finishes. It sends the normal response. Progress notifications must stop after completion.
Here is the request, from the spec (the real request also carries the required protocol _meta fields):
{
"jsonrpc": "2.0",
"id": 1,
"method": "some_method",
"params": {
"_meta": { "progressToken": "abc123" }
}
}
And a progress notification:
{
"jsonrpc": "2.0",
"method": "notifications/progress",
"params": {
"progressToken": "abc123",
"progress": 50,
"total": 100,
"message": "Reticulating splines..."
}
}
Rules worth knowing
progressmust go up with each notification, even iftotalis unknown.progressandtotalmay be decimals.messageshould be human-readable status text.- The server may skip progress entirely, choose its own frequency, or omit
total. - Both sides should rate-limit to avoid flooding.
Where the updates travel
The 2026-07-28 patterns overview says a server may send notifications "scoped to" a request while it is in flight, naming notifications/progress as an example. The changelog adds that request-scoped notifications "continue to flow on the response stream of the request they relate to, not the subscriptions/listen stream." On Streamable HTTP, that is the SSE stream carrying the response. See MCP Streamable HTTP.
Progress and timeouts
The cancellation page links the two. Implementations "MAY choose to reset the timeout clock when receiving a progress notification," because it shows work is happening. But they "SHOULD always enforce a maximum timeout, regardless of progress notifications." A server that sends progress forever should not be able to hold a request open forever. More on that in cancelling MCP requests.
What changed across spec versions
| Version | Progress change |
|---|---|
| 2024-11-05 | Introduced, with progressToken, progress and optional total (page) |
| 2025-03-26 | Optional message field added to progress notifications (changelog) |
| 2025-11-25 | Rules added for experimental task-augmented requests: the same token continues for the task's lifetime |
| 2026-07-28 | Rewritten for client-to-server requests only; moved under "patterns"; task rules removed from core |
In 2025-11-25, "either side" could send progress, because servers could also send requests to clients. In 2026-07-28, servers no longer start requests, so the text now speaks of clients and servers specifically. Tasks moved to an extension, so the task-specific progress rules left the core page too. Read why MCP became stateless for the background.
Progress vs Tasks
Progress notifications only work while the original request stays open. If the connection drops, the request is lost. The changelog says a broken stream means the client "MUST re-issue it as a new request with a new request ID."
For long jobs, the Tasks extension is the better tool. The server returns a task ID right away. The client checks status with tasks/get, and the task carries its own status message. That survives disconnects in a way an open request cannot.
| Use progress notifications when | Use Tasks when |
|---|---|
| The job takes seconds | The job takes minutes or hours |
| The connection is stable | Clients may disconnect or restart |
| A progress bar is enough | You need a durable handle and mid-job input |
Common mistakes
- Progress that goes backwards. The spec says
progress"MUST increase with each notification." - Reusing tokens. Tokens must be unique across all active requests.
- Sending progress after the response. Notifications must stop when the operation completes.
- Treating progress as a heartbeat with no limit. Clients should still enforce a maximum timeout.
- Expecting progress on a separate stream. In 2026-07-28 it rides on the request's own response stream.
- Flooding the client. Send updates at a sensible rate.
Next step
Progress tells users a job is moving. The next question is how to stop one. Read cancelling MCP requests, or explore the MCP specification reference.
Frequently asked questions
Is progress reporting required in MCP?
No. It is optional on both sides. A client asks for it with a progressToken, and even then the server may choose not to send any updates.
What is a progressToken?
It is a string or integer the client attaches to a request's _meta. The server includes the same token in every progress notification so the client knows which request it describes. It must be unique across the client's active requests.
Can the total change or be missing?
The total is optional, and the server may omit it if it does not know. The progress value must still increase with each update.
Do progress notifications prevent timeouts?
They can help. Implementations may reset the timeout clock when progress arrives, but the spec says they should still enforce a maximum timeout regardless.
Should I use progress notifications or Tasks?
Use progress notifications for jobs that finish in seconds over a stable connection. Use the Tasks extension for long jobs, unreliable connections or work that pauses for user input.











