Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/_client/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ This class supports:
- Lifecycle negotiation and connection via `MCP::Client#connect`, adopting the modern lifecycle
when the server serves it; see [Lifecycle](/client/lifecycle/)
- Server discovery via the `server/discover` method (`MCP::Client#discover`); see [Explicit Discovery](/client/lifecycle/#explicit-discovery)
- Liveness check via the `ping` method (`MCP::Client#ping`)
- Liveness check via the `ping` method (`MCP::Client#ping`), and automatic answers to server pings;
see [Answering Server Pings](/client/ping/#answering-server-pings)
- Tool listing via the `tools/list` method (`MCP::Client#tools`)
- Tool invocation via the `tools/call` method (`MCP::Client#call_tool`)
- Resource listing via the `resources/list` method (`MCP::Client#resources`)
Expand Down
8 changes: 6 additions & 2 deletions docs/_client/ping.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,17 @@ propagate as exceptions raised by the transport layer.
## Answering Server Pings

On handshake-lifecycle connections a server may ping the client the same way, and the client answers automatically with
the empty result - no handler is needed. Registering `transport.on_server_request("ping")` on `MCP::Client::HTTP` replaces
the automatic answer.
the empty result - no handler is needed. Over HTTP a ping reaches the client only on a stream that is already open
(the SSE response of an in-flight POST, or the GET listening stream); the client never opens a stream just to receive pings.
Over stdio, a ping that arrives while a response is awaited is answered inline; between requests it is answered when
the next request starts reading. The answer is best effort: a pong that cannot be written (for example, over a broken pipe) is
dropped rather than failing the request whose response is being read. Independently of pings, consider setting `read_timeout:`
on `MCP::Client::Stdio`, since a server that never answers otherwise holds the read until the process exits.

To answer pings yourself, register `transport.on_server_request("ping")` on `MCP::Client::HTTP`; it replaces
the automatic answer and, like any handler registered there, opens the standalone GET listening stream on `connect`,
as described on the [Transports](/client/transports/#server-to-client-requests-elicitation) page.

## Server Side

How servers answer `ping` requests and ping the client themselves is documented on
Expand Down
8 changes: 8 additions & 0 deletions docs/_client/transports.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,14 @@ The stdio transport automatically handles:
- Spawning the server process with `Open3.popen3`
- MCP protocol initialization handshake (`initialize` request + `notifications/initialized`)
- JSON-RPC 2.0 message framing over newline-delimited JSON
- Answering server `ping` requests; see [Answering Server Pings](/client/ping/#answering-server-pings)

{: .note }
> `ping` is the only server-to-client request answered over stdio. A wire-level `elicitation/create`
> or `sampling/createMessage` is ignored on this transport, so a server that sends one waits for an answer
> that never comes; use Streamable HTTP for those, as described below. The SEP-2322 `input_required` route,
> which is how the modern lifecycle asks for the same input, works on every transport, so `on_elicitation`
> and `on_sampling` handlers still fire over stdio; see [Multi Round-Trip Requests](/client/mrtr/).

## HTTP Transport Layer

Expand Down
2 changes: 2 additions & 0 deletions docs/_server/ping.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,5 @@ Server-to-client requests are bounded by a timeout on the Streamable HTTP transp
## Client Side

Pinging the server with `MCP::Client#ping` is documented on the client [Ping](/client/ping/) page.
The Ruby client answers the pings sent with `ServerSession#ping` automatically;
see [Answering Server Pings](/client/ping/#answering-server-pings).