Skip to content

adityachilka1/mcp-devtools

mcp-devtools

Chrome DevTools for the Model Context Protocol.

Stop tailing logs. See every tool call your agent makes, why it failed, how long it took, and what it cost — all in a local browser window.

npm license ci stars contributors

Inspect · Profile · Replay · Diff

demo


Why

You're building an MCP server (or just running one) and something is off — the wrong tool fires, a call takes 14 seconds, your agent loops, your token bill triples overnight. Today's options: console.log, the official MCP Inspector (CLI-only, single-server), or grep through 40 MB of JSON-RPC logs.

mcp-devtools is the local-first inspector and profiler that should have shipped with the protocol. Point any MCP client at it instead of your real server, and watch every request and response stream into a browser UI you can search, filter, replay, and diff.

Install

npm install -g @adityachilka/mcp-devtools
# or
pnpm add -g @adityachilka/mcp-devtools

Quick start — proxy mode (recommended)

mcp-devtools sits between your client (Claude Desktop, Cowork, Cursor, your own agent) and your real MCP server. Zero changes to the server.

mcp-devtools proxy \
  --upstream "node ./my-mcp-server.js" \
  --port 7456

Then point your client at http://localhost:7456. Open http://localhost:7456/inspect in your browser.

You get:

  • Timeline — every initialize, tools/list, tools/call, resources/read, and notification in chronological order.
  • Tool view — for any tools/call, the inputs (with schema validation), the response, the latency, and the LLM-attributed token cost.
  • Schema explorer — live view of the server's declared tools, resources, and prompts.
  • Replay — click any past call, edit the arguments, hit run. Re-hits the upstream and shows the diff against the original response.
  • Time travel — scrub a slider to see the protocol state at any point in the session.

Quick start — embed mode

Already have a Node/TypeScript MCP server? Add five lines.

import { createServer } from "@modelcontextprotocol/sdk/server";
import { devtools } from "mcp-devtools/embed";

const server = createServer({ name: "my-server", version: "1.0.0" });
// ... register your tools ...

devtools.attach(server, { port: 7456 });

The DevTools UI is now available at http://localhost:7456/inspect whenever your server is running.

Quick start — record mode

Record a session and share the trace file with a teammate or in a bug report.

mcp-devtools record --upstream "node ./my-mcp-server.js" --out session.mcptrace
mcp-devtools open session.mcptrace      # opens the UI on the recorded trace

.mcptrace files are gzipped JSONL — diffable, grep-able, and small.

Log rotation for long-running sessions

For sessions that may run for hours or days, cap the on-disk footprint with --rotate <size> and --keep <N>:

mcp-devtools record --upstream "node ./my-mcp-server.js" \
  --out session.mcptrace --rotate 10MB --keep 5

When the active trace grows past --rotate <size> (B, KB, MB, GB — case-insensitive, e.g. 1024, 500KB, 10MB, 1GB), the recorder closes the gzip stream cleanly, shifts session.mcptrace.1 → .2 → .3 …, renames the active file to .1, and reopens a fresh session.mcptrace. --keep <N> (default 3) caps how many rotated archives survive; older ones are deleted. Each rotated file is a complete, self-contained gzip archive — gunzip < session.mcptrace.1 works on its own.

mcp-devtools tail already follows rotations: when the active file shrinks, the tail reopens from byte zero, so live monitoring keeps working across rotations.

Size is checked against bytes-fed-to-gzip (pre-compression); the on-disk archive is always smaller since gzip compresses, so --rotate 10MB is an upper bound on the uncompressed payload per archive.

Quick start — profile mode

Recorded a session and want to know where the time went? profile reports per-method p50/p95/p99 latency and the slowest individual calls — Chrome DevTools Performance tab, for MCP.

mcp-devtools profile session.mcptrace
mcp-devtools profile session.mcptrace --json | jq .

Quick start — summary mode

profile answers "where did the time go?" — summary answers "what happened?" in one screen. Combines the headline profile numbers with an error breakdown and (optionally) a cost estimate, so you can triage a recorded session without flipping between subcommands.

mcp-devtools summary session.mcptrace
mcp-devtools summary session.mcptrace --json | jq .
mcp-devtools summary session.mcptrace --model gpt-4o-mini
mcp-devtools summary session.mcptrace --model claude-sonnet-4-6 --pricing-file ./my-prices.yaml

You get:

  • Total frames, wall clock, paired requests, and global error count.
  • Top methods by call count with count / p95 / errorRate (right-aligned, tabular).
  • Top-3 slowest individual calls.
  • USD cost block when --model <id> is passed — identical math to the inspector UI.

Quick start — cost mode (CI gate)

summary --model <id> shows a cost estimate. cost is the same number, wired as a CI gate: one line, non-zero exit when you blow the budget.

# 0 if under budget, 1 if over, 2 on I/O / config error
mcp-devtools cost session.mcptrace --model gpt-4o-mini --budget 0.05
mcp-devtools cost session.mcptrace --model gpt-4o-mini --budget 0.05 --json
mcp-devtools cost session.mcptrace --model claude-sonnet-4-6 --pricing-file ./my-prices.yaml --budget 1.00

Drop straight into a GitHub Actions step — no jq, no shell math:

- run: mcp-devtools cost session.mcptrace --model gpt-4o-mini --budget 0.05

If the active model id isn't in the pricing table (so every tools/call resolves to the unknown-model basis), the gate is held open even with --budget 0. The rule is "we can't measure → don't fail CI" — flipping a build red on a missing model id would punish the wrong person. The human-mode output flags this with an unknown / unable to price note.

Quick start — call mode

Need to fire one tool call against an MCP server from a shell script, a CI step, or a quick local debug session? call is the single-shot, non-interactive entry: spawn (or POST to) the upstream, run initialize → notifications/initialized → tools/call, print the response, exit.

# stdio — spawns the upstream as a child process
mcp-devtools call echo --upstream "node ./my-mcp-server.js" --args '{"text":"hi"}'

# JSON envelope, jq-friendly
mcp-devtools call echo --upstream "node ./my-mcp-server.js" --args '{"text":"hi"}' --json | jq '.result'

# HTTP transport — reuses the proxy's streamable-HTTP support
mcp-devtools call list_repos --transport http --upstream https://example.com/mcp \
  --header 'Authorization: Bearer ${TOKEN}' --json

# Custom timeout (default 10000ms)
mcp-devtools call slow_tool --upstream "node ./srv.js" --timeout 30000

Exit codes: 0 on tool success, 1 on a JSON-RPC error envelope from the server, 2 on transport / config error (missing --upstream, spawn ENOENT, timeout, malformed --args). The JSON envelope is { toolName, ok, result?, error?, durationMs } on a single line — pipes cleanly into jq.

Quick start — bench mode

Want to know how fast serve --replay can drain a trace, and whether a code change regresses that? bench runs the same per-frame replay path inside a tight loop and reports throughput.

# 1 measured run (default)
mcp-devtools bench session.mcptrace

# 5 measured runs + 1 warmup run to discard JIT effects
mcp-devtools bench session.mcptrace --iterations 5 --warmup 1

# JSON envelope for CI / regression tracking
mcp-devtools bench session.mcptrace --iterations 10 --warmup 2 --json | jq '.median.framesPerSecond'

You get a per-run table (warmup rows are dim and asterisked) and a summary block with median / p95 / best / worst for both durationMs and framesPerSecond. Warmup runs stay visible so you can spot first-iteration penalties, but they don't pollute the summary stats.

Quick start — serve mode (replay)

Develop and test MCP clients offline. serve --replay reads a .mcptrace and impersonates the upstream server over stdio: matching requests get the recorded response (with the client's id substituted in), unknown methods get a clean -32601 so the client sees a protocol-level failure instead of a hang.

mcp-devtools serve --replay session.mcptrace             # strict (default)
mcp-devtools serve --replay session.mcptrace --no-strict # canned { result: {} } for unknown methods

Point your client at this command exactly like it would a real MCP server. Identical recorded sessions become deterministic fixtures for CI.

Quick start — tail mode

Recording a long session in one terminal and want to watch frames stream in from another, without opening the inspector? tail is tail -f for .mcptrace: one tidy line per frame, with a latency hint when a response pairs against a request you've already seen.

# Terminal A
mcp-devtools record --upstream "node ./my-mcp-server.js" --out session.mcptrace

# Terminal B
mcp-devtools tail session.mcptrace                    # read from start, then follow
mcp-devtools tail session.mcptrace --from-end         # only show new frames from here on
mcp-devtools tail session.mcptrace --no-follow        # print existing frames and exit

Output looks like:

14:32:11.482 → initialize#1
14:32:11.491 ← #1 (9ms)
14:32:11.503 → tools/list#2
14:32:11.518 ← #2 (15ms)

Where is the direction arrow and #1 is the JSON-RPC id of the response that paired with the earlier request.

is client→server, is server→client. Truncations and rotations are handled — if the file shrinks under us, tail reopens from byte zero.

Features

Live request/response timeline Schema visualizer (tools, resources, prompts)
Per-tool latency histograms Token attribution (per call, per session)
Error grouping and stack traces Replay any call with modified args
Time-travel slider Diff between two recorded sessions
Works with stdio AND streamable HTTP Browser-only — no telemetry, nothing leaves your machine
Export .mcptrace files Open-source, MIT, self-hostable

Architecture

┌────────────────┐   stdio/http     ┌──────────────────┐   stdio/http   ┌─────────────────┐
│   MCP client   │ ────────────────▶│   mcp-devtools   │ ──────────────▶│   upstream MCP  │
│ (Claude, etc.) │                  │   proxy + UI     │                │   server        │
└────────────────┘ ◀────────────────└──────────────────┘ ◀──────────────└─────────────────┘
                                            │
                                            ▼
                                   ┌──────────────────┐
                                   │  local browser   │
                                   │  http://:7456    │
                                   └──────────────────┘

Single binary. No daemon. No cloud. No login.

Integration guides

Step-by-step setup for popular MCP clients:

All three follow the same wrapper pattern — point your client at mcp-devtools proxy instead of your real server, and the inspector picks up everything.

Roadmap

See ROADMAP.md for the full picture. The short version:

  • v0.1 — stdio proxy, recorder, embed API, browser UI
  • v0.1.x--quiet, color-coded timeline, signed binaries, Bun support
  • v0.2 — streamable HTTP transport, replay with diff, schema explorer
  • v0.3 — OpenTelemetry export, VS Code extension, cost dashboard

Contributing

We love contributions — see CONTRIBUTING.md. Good first issues are labeled good-first-issue. Open an issue or start a Discussion before anything ambitious — Discord server coming soon.

Acknowledgements

Built by @adityachilka1. Inspired by Chrome DevTools, React DevTools, and the official MCP Inspector.

License

MIT © 2026 Aditya Chilka.

About

Chrome DevTools for the Model Context Protocol. Inspect, profile, replay, and diff every MCP call your agent makes.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors