> ## Documentation Index
> Fetch the complete documentation index at: https://ctpf.q-uestionable.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Session Replay

> Re-send captured MCP messages against a live server for testing and validation

Session replay sends previously captured client-to-server messages against a live MCP server, collecting responses for analysis, testing, and reproduction.

## Basic Workflow

1. **Capture** a session:

```bash theme={null}
ctpf proxy start \
  --transport stdio \
  --target-command "python my_server.py" \
  --session-file session.json
```

Interact with your agent or client normally. The proxy saves all messages to `session.json`.

2. **Replay** the captured messages:

```bash theme={null}
ctpf proxy replay \
  --session-file session.json \
  --target-command "python my_server.py" \
  --output results.json
```

The replay engine resends client-to-server messages and captures new responses.

## Replay Command Reference

```bash theme={null}
ctpf proxy replay --session-file FILE [OPTIONS]
```

**Options:**

| Option             | Required | Type   | Description                                                            |
| ------------------ | -------- | ------ | ---------------------------------------------------------------------- |
| `--session-file`   | Yes      | string | Path to the captured session file                                      |
| `--target-command` | Yes\*    | string | Command to start the target server (stdio)                             |
| `--target-url`     | Yes\*    | string | URL of the target server (SSE/HTTP)                                    |
| `--output`         | No       | string | Save replay results to JSON file                                       |
| `--timeout`        | No       | float  | Per-message response timeout in seconds (default: 10.0)                |
| `--no-handshake`   | No       | flag   | Skip synthetic handshake (only if session already includes initialize) |

\* Either `--target-command` or `--target-url` is required.

## Auto-Handshake

By default, replay sends a synthetic MCP handshake before replaying messages:

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": "__handshake__",
  "method": "initialize",
  "params": {
    "protocolVersion": "2024-11-05",
    "capabilities": {},
    "clientInfo": {
      "name": "mcp-proxy-replay",
      "version": "0.1.0"
    }
  }
}
```

This ensures the server is ready to accept tool calls. Use `--no-handshake` only if:

* Your captured session already starts with an `initialize` request
* You want to replay the exact sequence as captured (including handshake)

## Modifying Arguments Before Replay

Replay sends messages exactly as captured. To modify arguments:

1. Export the session JSON or inspect it to find the target message
2. Edit the message's `payload` field directly in the JSON file
3. Replay the modified session

**Example:**

```json theme={null}
{
  "proxy_id": "msg-001",
  "sequence": 5,
  "direction": "client_to_server",
  "payload": {
    "jsonrpc": "2.0",
    "id": 2,
    "method": "tools/call",
    "params": {
      "name": "search",
      "arguments": {
        "query": "modified search term"
      }
    }
  }
}
```

## Output Format

Replay results are written to JSON with a detailed record of each message:

```json theme={null}
{
  "results": [
    {
      "original_request": {
        "id": "msg-001",
        "method": "tools/call",
        "jsonrpc_id": 1
      },
      "sent_message": {
        "jsonrpc": "2.0",
        "id": 1,
        "method": "tools/call",
        "params": { ... }
      },
      "response": {
        "jsonrpc": "2.0",
        "id": 1,
        "result": { ... }
      },
      "error": null,
      "duration_ms": 145.2
    }
  ]
}
```

**Result fields:**

| Field              | Description                                             |
| ------------------ | ------------------------------------------------------- |
| `original_request` | The ProxyMessage from the captured session              |
| `sent_message`     | The actual SessionMessage sent to the server            |
| `response`         | The server's response (null if notification or timeout) |
| `error`            | Error description if replay failed (null on success)    |
| `duration_ms`      | Round-trip time in milliseconds                         |

## Handling Timeouts

Use `--timeout` to adjust the per-message timeout:

```bash theme={null}
ctpf proxy replay \
  --session-file session.json \
  --target-command "python slow_server.py" \
  --timeout 30.0 \
  --output results.json
```

Messages that exceed the timeout are recorded with a timeout error and continue to the next message.

## Filtering Replayed Messages

Only client-to-server messages are replayed. Server-to-client messages in the session are skipped:

* `client_to_server` messages (requests and notifications) are replayed in order
* `server_to_client` messages (responses and notifications) are ignored
* Notifications (no JSON-RPC id) are sent without waiting for a response

## Use Cases

### Reproduce Security Findings

Capture a vulnerable interaction, then replay it to confirm the finding:

```bash theme={null}
# 1. Capture the attack sequence
ctpf proxy start \
  --transport stdio \
  --target-command "python app.py" \
  --session-file attack.json

# 2. Replay against the target to confirm
ctpf proxy replay \
  --session-file attack.json \
  --target-command "python app.py" \
  --output confirmation.json

# 3. Compare responses
```

### Test Compatibility

Verify a new server version behaves the same as the old:

```bash theme={null}
# Replay sessions against new server
ctpf proxy replay \
  --session-file v1_capture.json \
  --target-command "python server_v2.py" \
  --output v2_results.json

# Compare with original v1_results.json
```

### Debug Intermittent Issues

Capture a failing interaction, then replay it repeatedly:

```bash theme={null}
ctpf proxy replay \
  --session-file failing_session.json \
  --target-command "python server.py" \
  --output replay_1.json

ctpf proxy replay \
  --session-file failing_session.json \
  --target-command "python server.py" \
  --output replay_2.json

# Compare results to identify variability
```

<Note>
  Only client-to-server messages are replayed. Server responses are discarded from the original session and newly captured during replay. This allows testing the server against the same client sequence while isolating server-side changes.
</Note>
