MCP Log Viewer

Debugging a stdio MCP server is awkward because the protocol owns stdout — JSON-RPC frames and your own console.log lines end up interleaved in the same stream, and the messages are dense single-line JSON. Paste that captured output here and this tool separates the protocol frames from stray logs, pairs each request with its response by id, flags requests that never got an answer, and surfaces error frames — turning a wall of JSON into a readable request/response timeline. It runs entirely in your browser: nothing you paste is uploaded.

0
Messages
0
Requests
0
Errors
0
Stray output

    How to Use This Tool

    1. Capture the stream — redirect your MCP server's stdout to a file, or copy it from your client's log pane. Paste it here; nothing leaves your browser.
    2. Scan the timeline — requests, responses, notifications, errors, and stray output are separated and labeled, in order.
    3. Follow the ids — each response is tagged with the method it answers; requests with no reply are marked pending.
    4. Zero in on errors — error frames and unanswered requests are counted at the top so you can jump straight to what broke.

    Making Sense of stdio MCP Traffic

    The Model Context Protocol's stdio transport is the simplest way to run a local MCP server: the client launches the server as a subprocess and they exchange JSON-RPC 2.0 messages over standard input and output, one message per line. That simplicity has a sharp edge — because the protocol owns stdout, any stray write to stdout from your server code (a leftover print, a library's debug line) is injected into the same stream as the protocol frames, where it is at best noise and at worst enough to break the client's parser. The standard fix is to send all logging to stderr or a file, but you still routinely end up staring at a captured stream that mixes both.

    This viewer untangles that stream. It walks the text and pulls out every balanced JSON object or array — handling dense single-line frames, pretty-printed multi-line objects, and Content-Length-framed messages alike — then classifies each as a request, response, notification, or error by its JSON-RPC shape. Everything it cannot parse as a JSON-RPC message is set aside as stray output, so the protocol conversation and the debug noise are finally separated instead of interleaved.

    The most useful view it produces is the request/response pairing. JSON-RPC ties a reply to its call through the id field, so the viewer labels each response with the method that triggered it and flags any request whose id never received a reply. A request left pending is often the whole story of a bug: a tool handler that threw and never responded, or a call the server silently dropped. Reading that from raw logs by hand means scanning for matching id numbers across hundreds of lines; here it is counted for you at a glance.

    Frequently Asked Questions

    What input does it expect?
    The captured standard-output stream from a stdio-transport MCP server — the newline-delimited JSON-RPC 2.0 messages your client and server exchange, typically mixed with stray lines like startup banners, console.log debug output, or stack traces. You can paste the raw stream as-is; the parser extracts the JSON frames wherever they appear (including pretty-printed multi-line objects and Content-Length-framed messages) and treats everything else as stray output.
    Why is debugging a stdio MCP server so awkward?
    In the stdio transport, the MCP protocol communicates over standard output, so anything else a server writes to stdout — a stray print or console.log — lands in the same stream as the JSON-RPC frames and can even corrupt them. The common advice is to log to stderr or a file instead, but when you are handed a raw capture after the fact, you still need to untangle the two. That is what this viewer does: it pulls the valid JSON-RPC messages out of the noise and shows the stray lines separately.
    How does it pair requests and responses?
    JSON-RPC matches a response to its request by the id field. The viewer records the method of each request by id, then when it sees a response or error with the same id it labels it with the originating method (shown as ↳ tools/call, for example). Requests whose id never receives a response or error are flagged as pending — often the exact clue you need, since a hung or crashed handler shows up as a request with no matching reply.
    Is my log uploaded anywhere?
    No. All parsing happens in your browser with JavaScript — nothing you paste is sent to Janeer or any server. MCP logs can contain internal method names, arguments, and error details, so keeping the parsing local means you can inspect a real capture without the content leaving your machine.
    What do the message types mean?
    → req is a request (has a method and an id); ← res is a successful response (has a result and the matching id); ✕ err is an error response (carries an error object with a code and message); • note is a notification (a method with no id, so it expects no reply); and · out is stray output — anything that was not a valid JSON-RPC message.