How to record MCP tool calls with a wrap proxy
Some agents keep a transcript you can scan after the fact; some don't. Cursor, for one, exposes no readable session history — reelier scan has nothing to read there. The wrap proxy is the capture path that does not depend on history: reelier mcp --wrap sits in front of your own MCP server and records every tool call losslessly as it happens, so the recording exists the moment the work does.
This guide walks the whole loop with the reelier CLI: front your MCP server with the proxy, record a real workflow through it, compile the captured trace to a SKILL.md, and replay it deterministically. Every command below is real and every output is verbatim from an actual recording.
Before you start
- Reelier installed —
npm i -g reelier(or usenpx -y reelier@latestin place ofreelierin every command below). - One MCP server you can launch by command — the server your agent already calls (e.g.
npx -y @acme/support-mcp). The proxy fronts it; it never replaces it. - An MCP-capable agent or client whose config you can point at a new server, so its calls route through the proxy instead of straight to your server.
- Nothing else. No account, no API key: recording and deterministic replay never call a model.
Put the proxy in front of your MCP server
Start the recorder with your server as its downstream. reelier mcp --wrap connects to that server, re-exposes every one of its tools 1:1 as a pure passthrough, and adds three control tools — reelier_start_recording, reelier_note, and reelier_stop_recording. It speaks MCP over stdio and stays running; there is no stdout to show, because the proxy is now a server your agent talks to.
Register this command as an MCP server in your agent (the same place you configured the real one), so the agent's tool calls flow through the proxy. Because capture happens at the wire, not from a saved transcript, this is the lossless path for any agent with no scannable history. To wrap every server in your config at once instead of by hand, run reelier install.
reelier mcp --wrap "npx -y @acme/support-mcp"Record the workflow through the proxy
With the agent connected, have it call reelier_start_recording with a name, narrate each logical step with reelier_note, run the real tools, then call reelier_stop_recording. The tools pass through unchanged and get logged on the way; only calls made after reelier_start_recording are captured, so you cannot record a workflow retroactively.
The proxy writes a lossless JSONL trace to .reelier/traces/<name>-N.jsonl: one line for the recording metadata (including which server was wrapped and any tool annotations it declared), one for each narration note, and a paired call/result line for every tool invocation. The trace below is exactly what the proxy wrote for a single read-only get_ticket call against a wrapped support server — no CLI command prints it; it is the file on disk.
{"t":"meta","seq":0,"name":"support-ticket-check","startedAt":"2026-07-22T10:42:06.818Z","wrapped":["acme-support"],"toolAnnotations":{"get_ticket":{"readOnlyHint":true}}} {"t":"note","seq":1,"ts":"2026-07-22T10:42:06.821Z","text":"Pull the current status of the priority refund ticket"} {"t":"call","seq":2,"i":0,"ts":"2026-07-22T10:42:06.822Z","tool":"get_ticket","args":{"id":"T-4821"}} {"t":"result","seq":3,"i":0,"ok":true,"ms":2,"body":{"content":[{"type":"text","text":"{\"id\":\"T-4821\",\"subject\":\"Refund not received\",\"status\":\"open\",\"priority\":\"high\",\"customer\":\"acme-co\"}"}]}}
Compile the trace into a SKILL.md
Point reelier compile at the trace the proxy wrote. It reads the recorded calls and emits a SKILL.md — a plain markdown file you check into your repo. No model is involved; the compile is a deterministic pass over the trace.
The compiler writes minimal assertions. The one get_ticket call recorded a clean result, so its step gets exactly one success assertion — status == 200, reelier's check that the recorded call came back clean — and zero brittle value pins. A step whose call had failed or recorded no result would get no assertion at all and replay unchecked, never a false passed. The effect line reads read=1: the get verb, backed by the server's own readOnlyHint, classifies the step read-only, so replaying it writes nothing.
Open questions: (none) appears only because the reelier_note narration named the step's intent — the compiler asks about gaps it refuses to guess, and here there were none.
reelier compile .reelier/traces/support-ticket-check-1.jsonlWrote support-ticket-check.skill.md steps: 1 asserts: 1 binds: 0 effects: read=1 idempotent-write=0 destructive=0 Open questions: (none)
Replay it — read-only, zero tokens
reelier run re-issues the recorded tool calls and checks each assertion. Replaying an MCP step means calling that tool again, so you pass the same server on --wrap at replay time; the runner routes the recorded get_ticket call back through it. At the default --max-level 0 no LLM client is ever constructed, so the replay costs 0 tokens and reproduces the deterministic core of the workflow — nothing re-reasoned.
Replay is read-only by default. This step is a read, so it is safe to repeat forever; a recorded write would not re-fire unless you passed --allow-writes (idempotent writes only), and a destructive step would still need --yes. Note the scope: reelier re-issues MCP/tool calls and the http.get/http.post builtins, not an agent's Bash/Read/Edit/Write — pick workflows whose value is in the tool calls.
reelier run support-ticket-check.skill.md --wrap "npx -y @acme/support-mcp"✓ Step 1 — Pull the current status of the priority refund ticket [passed] 3ms PASSED: 1/1 steps ok, 0 failed, 3ms total
The receipt
$ reelier compile .reelier/traces/support-ticket-check-1.jsonl Wrote support-ticket-check.skill.md steps: 1 asserts: 1 binds: 0 effects: read=1 idempotent-write=0 destructive=0 Open questions: (none) $ reelier run support-ticket-check.skill.md --wrap "npx -y @acme/support-mcp" ✓ Step 1 — Pull the current status of the priority refund ticket [passed] 3ms PASSED: 1/1 steps ok, 0 failed, 3ms total
The trace-to-replay half of the loop, verbatim: the wrap-proxy trace compiled to support-ticket-check.skill.md, then replayed read-only. Produced on 2026-07-22 with reelier v0.14.0 in a scratch directory; the trace came from running reelier mcp --wrap against a local stdio MCP server exposing one read-only get_ticket tool (shown in the commands as the placeholder npx -y @acme/support-mcp). No model was constructed — Level 0, 0 tokens; absolute paths are shortened to the filename.
FAQ
Why not just use reelier scan instead of the proxy?
reelier scan reads saved transcripts (like Claude Code's under ~/.claude/projects) and needs no proxy. But some agents — Cursor among them — expose no readable history, so scan has nothing to read. The wrap proxy captures at the wire as calls happen, the only lossless option when there is no transcript to scan.
Do I need the proxy running when I replay?
You need the downstream MCP server, wrapped the same way. Replaying an MCP step re-issues that tool call, so reelier run takes the same --wrap "<your server>" you recorded with and routes the call back through it. Steps that only used the http.get/http.post builtins replay with no --wrap at all.
The recorded workflow writes data. Is replaying it safe?
Replay is read-only by default — a recorded write does not re-fire unless you pass --allow-writes (which unlocks idempotent writes only; a destructive step still needs --yes). The compile output tells you what you captured: its effects line counts read vs. idempotent-write vs. destructive, so you know before replaying.