RPC Console
The JSON-RPC wire between a client and an MCP server. Requests and responses are paired by id, which is what produces the latency figure and what makes an unanswered request visible — the single most useful thing this view can show.
src/components/ui/rpc-console.tsxAbout
From the component's own source, where it was written.
The JSON-RPC wire between a client and an MCP server.
When an MCP integration misbehaves, the answer is almost always in the traffic: a method that was never called, a capability that was not negotiated, an error code buried in a response nobody read. A console that shows only tool calls hides all three.
**Requests and responses are paired by id, not just listed.** That pairing is what produces the latency figure and what makes an unanswered request visible — a request with no matching response is the single most useful thing this view can show, and a flat log renders it as an ordinary row.
Notifications have no id by definition, so they are never paired and are marked as their own kind rather than looking like an orphaned request.
Payloads are collapsed. An initialize response carries every capability the server has, and expanding it by default buries the next twenty messages.
Install
npx astralyx-ui add rpc-console
Usage
import { RpcConsole } from '@/components/ui/rpc-console'
<RpcConsole messages={traffic} />Composer
Change the props and the source below follows.
<RpcConsole messages={traffic} onlyProblems={false} />Examples
A handshake, a refusal and a request still in flight
<RpcConsole messages={traffic} />API
Generated from the source, so it cannot fall behind the code. One table per exported component, then hooks, functions and types.
RpcConsole
Extends Omit<ComponentProps<'div'>, 'children'>.
| Prop | Type | Default | Description |
|---|---|---|---|
| messages | RpcMessage[] | required | { key, direction, method?, id?, kind?, payload?, error?, at?, durationMs? }. key is row identity — several messages share a JSON-RPC id. |
| onlyProblems | boolean | false | Errors and unanswered requests only. |
| emptyLabel | string | 'No traffic yet.' | Levels of the payload to pretty-print. |
| label | string | 'JSON-RPC traffic' | — |
| outLabel | string | 'Sent' | — |
| inLabel | string | 'Received' | — |
| pendingLabel | string | — | — |
Functions
| Function | Signature | Description |
|---|---|---|
| rpcUnanswered | (messages: RpcMessage[]) => Set<string> | A request with no response sharing its id is still in flight — or lost. |
Types
RpcMessage
The JSON-RPC wire between a client and an MCP server.
| Field | Type | Description |
|---|---|---|
| key | string | Row identity. Not the JSON-RPC id — several messages share that. |
| direction | 'out' | 'in' | — |
| method? | string | JSON-RPC method. Absent on a response. |
| id? | string | number | JSON-RPC id. Absent on a notification. |
| kind? | 'request' | 'response' | 'notification' | 'error' | — |
| payload? | unknown | The params or result, pretty-printed by the caller or passed raw. |
| error? | { code: number; message: string } | Error code and message, when the response carried one. |
| at? | string | Already formatted — this component does not own your locale. |
| durationMs? | number | Round-trip in ms. Computed by the caller, or derived from pairing. |
Behaviour
| Topic | Detail | Description |
|---|---|---|
| pairing | by JSON-RPC id | An outbound request with no inbound response sharing its id is flagged “no reply”. A flat log renders that as an ordinary row. |
| notifications | never paired | They have no id by definition, so they are marked as their own kind rather than looking like an orphaned request. |