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

Markdown twin of https://www.reelier.com/guides/record-mcp-tool-calls — a step-by-step Reelier how-to. Every command below is a real Reelier command and every output block is verbatim, never a mockup.

## Before you start

- Reelier installed — `npm i -g reelier` (or use `npx -y reelier@latest` in place of `reelier` in 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.

## 01 · 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`.

```bash
reelier mcp --wrap "npx -y @acme/support-mcp"
```

## 02 · 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\"}"}]}}
```

## 03 · 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.

```bash
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)
```

## 04 · 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.

```bash
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.

## Related

- [MCP recording — the lossless wrap-proxy capture this guide runs, defined](https://www.reelier.com/learn/mcp-recording)
- [Reelier for Cursor — why an agent with no scannable history needs the wrap proxy](https://www.reelier.com/for/cursor)
- [Guide: compile a skill straight from a session you already recorded](https://www.reelier.com/guides/from-session-compile)
- [Guide: replay these recorded calls as a deterministic MCP server test](https://www.reelier.com/guides/test-mcp-servers)
- [Deterministic replay — what read-once, replay-forever means, defined](https://www.reelier.com/learn/deterministic-replay)

## Sources

- [seldonframe/reelier — the open-source (AGPL-3.0) CLI every command here runs](https://github.com/seldonframe/reelier)
- [Model Context Protocol — the open standard the wrapped tool calls speak](https://modelcontextprotocol.io)
- [Reference MCP servers — the kind of server you point --wrap at](https://github.com/modelcontextprotocol/servers)

Other guides: [How to snapshot-test a Claude Code workflow](https://www.reelier.com/guides/snapshot-test-claude-code-workflows) · [How to replay an agent workflow at 0 LLM tokens](https://www.reelier.com/guides/replay-agent-workflow-zero-tokens) · [How to gate CI on agent drift](https://www.reelier.com/guides/ci-gate-for-agent-drift) · [Replay an agent skill on every PR with the Reelier GitHub Action](https://www.reelier.com/guides/github-action-agent-replay) · [Test your MCP server for regressions by replaying a golden run](https://www.reelier.com/guides/test-mcp-servers) · [Run a deterministic cron agent by scheduling a recorded replay](https://www.reelier.com/guides/deterministic-cron-agents) · [Build an agent audit trail from Reelier run receipts](https://www.reelier.com/guides/agent-audit-trail-receipts) · [Configure BYOK escalation levels: L0, L1, and L2](https://www.reelier.com/guides/byok-escalation-levels) · [Compile a skill from an existing session with reelier from-session](https://www.reelier.com/guides/from-session-compile) · [Diff two agent runs with reelier diff (exit 1 on drift)](https://www.reelier.com/guides/diff-two-agent-runs) · [Convert an LLM agent skill into a deterministic, assertion-checked skill](https://www.reelier.com/guides/convert-agent-skill-deterministic)
