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.tsx

About

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.

Props
tsx
<RpcConsole messages={traffic} onlyProblems={false} />

Examples

A handshake, a refusal and a request still in flight

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'>.

PropTypeDefaultDescription
messagesRpcMessage[]required{ key, direction, method?, id?, kind?, payload?, error?, at?, durationMs? }. key is row identity — several messages share a JSON-RPC id.
onlyProblemsbooleanfalseErrors and unanswered requests only.
emptyLabelstring'No traffic yet.'Levels of the payload to pretty-print.
labelstring'JSON-RPC traffic'—
outLabelstring'Sent'—
inLabelstring'Received'—
pendingLabelstring——

Functions

FunctionSignatureDescription
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.

FieldTypeDescription
keystringRow identity. Not the JSON-RPC id — several messages share that.
direction'out' | 'in'—
method?stringJSON-RPC method. Absent on a response.
id?string | numberJSON-RPC id. Absent on a notification.
kind?'request' | 'response' | 'notification' | 'error'—
payload?unknownThe 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?stringAlready formatted — this component does not own your locale.
durationMs?numberRound-trip in ms. Computed by the caller, or derived from pairing.

Behaviour

TopicDetailDescription
pairingby JSON-RPC idAn outbound request with no inbound response sharing its id is flagged “no reply”. A flat log renders that as an ordinary row.
notificationsnever pairedThey have no id by definition, so they are marked as their own kind rather than looking like an orphaned request.