Module: MCPClient::JsonRpcCommon
- Defined in:
- lib/mcp_client/json_rpc_common.rb
Overview
Shared retry/backoff logic for JSON-RPC transports
Instance Method Summary collapse
-
#build_jsonrpc_notification(method, params) ⇒ Hash
Build a JSON-RPC notification object (no response expected).
-
#build_jsonrpc_request(method, params, id) ⇒ Hash
Build a JSON-RPC request object.
-
#initialization_params ⇒ Hash
Generate initialization parameters for MCP protocol.
-
#ping ⇒ Hash
Ping the server to keep the connection alive.
-
#process_jsonrpc_response(response) ⇒ Object
Process JSON-RPC response.
-
#with_retry { ... } ⇒ Object
Execute the block with retry/backoff for transient errors only.
Instance Method Details
#build_jsonrpc_notification(method, params) ⇒ Hash
Build a JSON-RPC notification object (no response expected)
64 65 66 67 68 69 70 |
# File 'lib/mcp_client/json_rpc_common.rb', line 64 def build_jsonrpc_notification(method, params) { 'jsonrpc' => '2.0', 'method' => method, 'params' => params } end |
#build_jsonrpc_request(method, params, id) ⇒ Hash
Build a JSON-RPC request object
51 52 53 54 55 56 57 58 |
# File 'lib/mcp_client/json_rpc_common.rb', line 51 def build_jsonrpc_request(method, params, id) { 'jsonrpc' => '2.0', 'id' => id, 'method' => method, 'params' => params } end |
#initialization_params ⇒ Hash
Generate initialization parameters for MCP protocol
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/mcp_client/json_rpc_common.rb', line 74 def initialization_params capabilities = { 'elicitation' => {}, # MCP 2025-11-25: Support for server-initiated user interactions 'roots' => { 'listChanged' => true }, # MCP 2025-11-25: Support for roots 'sampling' => {} # MCP 2025-11-25: Support for server-initiated LLM sampling # NOTE: we intentionally do NOT declare a client `tasks` capability. That # capability marks the client as a RECEIVER of task-augmented # sampling/elicitation requests, which is not implemented here — this # client only acts as a task REQUESTOR for tools/call (see # Client#call_tool_as_task), which requires no client-side declaration. } { 'protocolVersion' => MCPClient::PROTOCOL_VERSION, 'capabilities' => capabilities, 'clientInfo' => { 'name' => 'ruby-mcp-client', 'version' => MCPClient::VERSION } } end |
#ping ⇒ Hash
Ping the server to keep the connection alive
42 43 44 |
# File 'lib/mcp_client/json_rpc_common.rb', line 42 def ping rpc_request('ping') end |
#process_jsonrpc_response(response) ⇒ Object
Process JSON-RPC response
97 98 99 100 101 |
# File 'lib/mcp_client/json_rpc_common.rb', line 97 def process_jsonrpc_response(response) raise MCPClient::Errors::ServerError, response['error']['message'] if response['error'] response['result'] end |
#with_retry { ... } ⇒ Object
Execute the block with retry/backoff for transient errors only.
Retries genuinely transient failures where the request most likely did not complete at the server: transport/network errors (TransportError, IOError, Errno::ETIMEDOUT/ECONNRESET/EPIPE) and TransientServerError (HTTP 5xx).
It deliberately does NOT retry a plain ServerError. A plain ServerError is raised for a JSON-RPC error response or an HTTP 4xx — cases where the server received and processed (or deterministically rejected) the request. Re-sending those would silently re-execute a non-idempotent operation (e.g. a tools/call), which JSON-RPC provides no way to make safe.
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
# File 'lib/mcp_client/json_rpc_common.rb', line 20 def with_retry attempts = 0 begin yield rescue MCPClient::Errors::TransientServerError, MCPClient::Errors::TransportError, IOError, Errno::ETIMEDOUT, Errno::ECONNRESET, Errno::EPIPE => e attempts += 1 if attempts <= @max_retries delay = @retry_backoff * (2**(attempts - 1)) @logger.debug("Retry attempt #{attempts} after error: #{e.}, sleeping #{delay}s") sleep(delay) retry end raise end end |