Expand description
v0.11.0 P3 — per-tool progress events for long-running MCP tool calls.
When an MCP tools/call request carries _meta.progressToken in its
params, the dispatcher builds a ProgressReporter wired to the
caller’s crate::mcp_session::SessionState. The reporter is passed
into the tool handler, which calls ProgressReporter::report at
sensible checkpoints. Each call publishes a JSON-RPC
notifications/progress envelope onto the session’s broadcast
channel, where the GET SSE stream subscriber forwards it to the
client.
§Wire shape (Decision C — MCP spec verbatim)
{
"jsonrpc": "2.0",
"method": "notifications/progress",
"params": {
"progressToken": "<echo of the client's token>",
"progress": 5,
"total": 12,
"message": "Processing cluster 5/12"
}
}The progressToken is whatever shape the client sent — string OR
number per the spec. ProgressToken is serde_json::Value-backed
so we preserve the wire shape losslessly on echo.
§Stdio backward compat
ProgressReporter is constructed only for HTTP requests that have
both an attached SessionState (planted by the session middleware)
and a _meta.progressToken in their tools/call params. The stdio
path (rmcp call_tool) and the unit tests that drive dispatch_tool
directly pass None — handlers see Option<ProgressReporter> and
skip reporting silently when it’s None.
§Backpressure
crate::mcp_session::SessionState::publish_event is lossy on the
broadcast channel (slow subscribers see a lagged event on
reconnect) but lossless to the replay buffer for Last-Event-ID
resume. Progress events are inherently best-effort — a client that
falls behind 256 events still sees the final tool result on the
POST side.
Structs§
- Progress
Reporter - A handle that long-running tool handlers call to emit progress
notifications during their work. Wraps the
crate::mcp_session::SessionStatethat owns the broadcast channel - Progress
Token - The progress token an MCP client passes in
tools/callparams_meta.progressToken. Spec allows EITHER a string OR a number; the server echoes back whatever shape the client sent. Held asserde_json::Valueso we don’t lose the original wire shape on the round-trip.
Constants§
- MCP_
NOTIFICATION_ PROGRESS_ METHOD - JSON-RPC method name for
notifications/progressper the MCP Streamable HTTP transport spec. Held as a const so any code that emits the envelope agrees on the exact wire spelling — the GET stream client matches on this string to route into its progress handler. - MCP_
REMEMBER_ BATCH_ PROGRESS_ EMIT_ EVERY - How often (in items processed)
memory_remember_batchemits a progress event during the embed loop. Plan §6 P3 spec: “every 25 rows”. Set to 25 so a 51-item batch emits at items 25 + 50 + the final terminal event. - MCP_
REMEMBER_ BATCH_ PROGRESS_ ITEM_ THRESHOLD - Threshold above which
memory_remember_batchcalls emit per-item embedding progress. Below 50 items the batch completes inside one or two embedder round-trips and progress notifications add wire-overhead with no UX benefit (Decision C). - MCP_
SEARCH_ DOCS_ PROGRESS_ TOP_ K_ THRESHOLD - Threshold above which
memory_search_docscalls emit progress events. Below 100 results the search completes fast enough that progress notifications add wire-overhead with no UX benefit (Decision C).
Functions§
- report_
if_ some - Helper for handlers: emit a progress event if-and-only-if a
reporter is present. Reads cleaner at every checkpoint than the
if let Some(r) = …pattern repeated 4x per handler.