What is ProgressToken?
ProgressToken is a scalar identifier — either a string or an integer — that a client attaches to any MCP request when it wants the server to emit incremental progress notifications during long-running operations. It lives inside the optional `params._meta` object of the outgoing request, giving the protocol a clean, non-breaking way to opt individual calls into progress reporting without altering the core method signature. The value itself carries no semantic meaning to the protocol layer; it is treated as an opaque correlation key whose only job is to tie each `notifications/progress` emission back to the originating request. \n\n In the message flow, the client sets `params._meta.progressToken` on the request. The server — if it supports progress — reads that token at the start of execution and includes it verbatim in every subsequent `notifications/progress` notification it sends, alongside the numeric `progress`, optional `total`, and optional human-readable `message` fields. The server never modifies or interprets the token value; it simply echoes it back, allowing the client to demultiplex concurrent in-flight requests using whatever identifier scheme it chose. \n\n The dual string-or-integer type reflects pragmatic compatibility: integer tokens align with JSON-RPC id conventions and are compact on the wire, while string tokens let clients embed structured data such as UUIDs, trace IDs, or user-visible labels without a secondary lookup table. Both forms are valid; the choice belongs entirely to the client. Servers must accept either variant and must not emit `notifications/progress` for a request that carried no token.
When to use
On any request that could take more than ~1 second.
When NOT to use
On fast operations — overhead isn't worth it.
Notes
Token uniqueness is the client's responsibility
The MCP spec does not mandate globally unique tokens, but reusing the same token across two concurrent requests that both expect progress will cause the client to misattribute notifications. Best practice is to derive the token from the request's JSON-RPC `id`, or to generate a UUID v4 string, so uniqueness is trivially guaranteed without a counter.
SDK auto-injection vs. manual passing
Several MCP SDK implementations (TypeScript SDK ≥ 0.9, Python SDK ≥ 1.1) will automatically propagate a progressToken when you call a high-level helper that accepts a progress callback. If you are constructing raw request objects yourself you must set `_meta.progressToken` manually; forgetting it means the server has no token to report against and will silently skip progress notifications.
Integer overflow and string length limits
The JSON-RPC layer treats the token as an opaque JSON value, so an integer token is subject to JSON number precision constraints — avoid values outside the safe-integer range (±2^53−1). String tokens should be kept short (under 128 characters) to avoid inflating every `notifications/progress` frame that echoes the token back.
No token in response, only in notifications
A common misconception is that the final JSON-RPC response for the request will also carry the progress token. It does not — the response follows standard JSON-RPC structure with only the `id` field for correlation. The token is exclusively a signal for the out-of-band notification channel, so clients must not wait for it in the response payload.
Security: avoid embedding sensitive data in tokens
Because the server echoes the token value in every progress notification sent to all listeners on that session, embedding secrets, personally identifiable information, or internal system identifiers in the token string is a data-leakage risk. Treat the token as observable by any party that can read the transport stream, and use an opaque random identifier rather than a structured value derived from sensitive context.
Fields
| Field | Type | Required | Purpose |
|---|---|---|---|
| value | string | number | yes | Unique across all active requests. |
Examples
Token in request
"_meta": { "progressToken": "abc123" }
Common mistakes
❌ Reusing tokens across active requests
✅ Each outstanding request needs its own unique token.