progressToken and the
server advertised streaming, the server MAY emit
notifications/progress frames before the final response — reporting pipeline
stages and even partial hits.
Opting in
The client sets_meta.progressToken on the request. The token is a
client-chosen string or integer, unique among the client’s in-flight
requests.
Progress frames
Each frame is a notification (noid, never answered):
string | integer
Echoes the request’s token verbatim. A server MUST NOT emit progress for a
request that carried none.
float
Completion in
0.0–1.0.string
The current pipeline stage (
transform, recall, rerank, mmr, …).object
Optional incremental payload — e.g.
partial.hits with first-stage candidates
before rerank.The final response is authoritative
1
Frames are advisory
A client MUST function correctly even if it never receives a single
progress frame. Never build correctness on them.
2
Ignore unknown tokens
A client MUST ignore a frame bearing a token it doesn’t recognise.
3
The result still arrives
The normal JSON-RPC response bearing the request
id still follows every
stream and is the single source of truth.Over HTTP: SSE
Over stdio, progress frames simply interleave on stdout. Over HTTP, a client that sendsAccept: text/event-stream receives them as Server-Sent Events — zero or
more notifications/progress frames, then one final frame carrying the JSON-RPC
response. See Transports.
Each SSE frame is a single data: line whose payload is a compact JSON object,
terminated by a blank line; the stream ends after the final response frame. A
client that did not ask for SSE gets one buffered JSON response instead — so
the same server handler serves both callers.
Writing a streaming handler
The reference Python SDK turns this into one idiom: a generator handler thatyields rcp.Progress events and returns the final result. Register it with
Server.stream(...) and advertise streaming. serve_http flushes each
Progress as a notifications/progress frame the instant it is produced, then
sends the final response frame; a plain unary POST drains the same generator and
returns only the result.
frame
A progress event.
progress is 0.0–1.0; stage names the pipeline phase;
partial is an optional early-result payload. Serialised into a
notifications/progress frame carrying the request’s progressToken — emitted
only when the client supplied one.The handler is written once and works both ways. Over SSE the frames stream
live; over a plain request the generator is drained and only its
return value
is sent — satisfying §13’s rule that a non-SSE client MUST get a single buffered
JSON response.examples/example_streaming.py: