Skip to main content
An RCP connection has a simple, strict lifecycle: initialize once, call many, shut down.

Phases

1

Initialize

The client’s first request. Negotiates the version and exchanges capabilities. A server MUST reject any non-initialize/info/ping request that arrives before a successful initialize with -32001 (NotInitialized). See Initialization.
2

Operate

The client calls capability-gated methods, optionally pipelining several at once and correlating responses by id. Long calls may stream progress.
3

Shut down

The client sends shutdown (params {}result {}). Over stdio, EOF on stdin is an equivalent shutdown — the server should finish in-flight work, flush responses, and exit.

Cancellation

A client MAY abandon an in-flight request (a long retrieve, rerank, or graph) with a notifications/cancel notification — no id, no direct response:
Cancellation is best-effort and racy. The server still sends exactly one response for the cancelled request — either the normal result (if it had already finished) or a -32006 (Cancelled) error. A client MUST tolerate receiving a full successful result after it sent a cancel.
Cancelling an unknown or already-answered id is a no-op. Cancellation needs no capability — it is always available.

Liveness — ping

ping is a state-free round-trip check, callable at any time (even before initialize). The server MUST echo any nonce it received.
Clients use ping for keep-alive on long-lived connections, to measure round-trip latency, and — inside a Selector — as the liveness probe behind primary → secondary failover.