# AI coding agents (/docs/ai-agents)

A coding agent such as Claude Code, Cursor, Codex or Copilot reads your code,
but it can't see what the code does when it runs. It doesn't know how many
queries a page makes, where the N+1 is or what failed. The Tracepanel agent
runs an [MCP](https://modelcontextprotocol.io) server that gives the coding
agent this information. The server answers from your project's traces. Each
issue in its answers comes with its place in the code and its fix.

## The loop [#the-loop]

With the server connected, the agent can check its own fix:

<Steps>
<Step>
You ask "Why is `/api/orders` slow?" The agent calls `find_traces` to find the
request, then `get_trace` to read it. The trace has an N+1 with 50 queries at
`shop/api.py:40`. In this Django app, the fix is to add `select_related()`.
</Step>
<Step>
The agent changes the code.
</Step>
<Step>
The agent calls `wait_for_trace` with a search such as `route:/api/orders`.
While it waits, it makes the request again with curl or a test.
</Step>
<Step>
The agent calls `compare_traces` on the two traces. It reads that the queries
dropped from 101 to 3, the time dropped from 31 ms to 4 ms, and the N+1 is
fixed.
</Step>
</Steps>

The server tells the agent this loop when it connects, so you don't have to.

## Connect it [#connect-it]

The MCP server is part of the agent. It runs from your project's directory,
because it reads the traces in `.tracepanel/` there:

```bash
tracepanel-agent mcp [--dir DIR] [--values]
```

`--dir` names the store directory when it isn't `.tracepanel`. `--values` is
described in [What the model sees](#what-the-model-sees). Add the server to
your coding agent:

<Tabs items={["Claude Code", "Cursor", "VS Code", "Codex"]}>
<Tab value="Claude Code">

```bash
claude mcp add --scope project tracepanel -- tracepanel-agent mcp
```

</Tab>
<Tab value="Cursor">

Add this to `.cursor/mcp.json`:

```json
{
  "mcpServers": {
    "tracepanel": {
      "command": "tracepanel-agent",
      "args": ["mcp"]
    }
  }
}
```

</Tab>
<Tab value="VS Code">

Add this to `.vscode/mcp.json`:

```json
{
  "servers": {
    "tracepanel": {
      "type": "stdio",
      "command": "tracepanel-agent",
      "args": ["mcp"]
    }
  }
}
```

</Tab>
<Tab value="Codex">

Add this to `.codex/config.toml`:

```toml
[mcp_servers.tracepanel]
command = "tracepanel-agent"
args = ["mcp"]
```

</Tab>
</Tabs>

The coding agent must find `tracepanel-agent` on its `PATH`. If it can't,
give the full path to the program.

<Callout title="In the Python SDK">
The `tracepanel` package installs `tracepanel-agent` into your virtualenv.
It also offers `tracepanel mcp`, which runs the same server. It passes the
store directory from the project's settings as `--dir`. With uv, use
`uv run tracepanel mcp` as the command:

```bash
claude mcp add --scope project tracepanel -- uv run tracepanel mcp
```

Without uv, run it from the project's virtualenv, as in
`.venv/bin/tracepanel mcp`. See [Command line](/docs/python/cli#tracepanel-mcp).
</Callout>

<Callout title="In the JavaScript SDK">
`@tracepanel/js` installs the agent into `node_modules`, off the `PATH`. Use
`npx tracepanel mcp`, which runs the same server with the project's store, as
the command:

```bash
claude mcp add --scope project tracepanel -- npx tracepanel mcp
```

In a JSON config, that is `"command": "npx"` with `"args": ["tracepanel",
"mcp"]`. See [Command line](/docs/javascript/cli#tracepanel-mcp).
</Callout>

Then run your app as usual with Tracepanel on, and ask the agent. Before the
app records its first trace, the tools answer that there are no traces yet.

## Tools [#tools]

Every tool only reads. A search takes free text and filters, as in the
[console](/docs/console#search). Examples are `route:/api/* status>=500`,
`has:n+1 duration>200ms` and `kind:task state:FAILURE since:1h`.

| Tool | Parameters | What it returns |
| --- | --- | --- |
| `find_traces` | `query`, `limit` up to 50, default 10 | Recent requests, tasks and commands, newest first. Each line has the trace's id, its time, its SQL count and SQL time, and the kinds of its issues. |
| `get_trace` | `id`, `focus` | One trace: its issues with their place in the code and their fix, the error with its stack, the call tree with repeats folded, warnings and related tasks. |
| `wait_for_trace` | `query`, `after`, `timeout_s` up to 120, default 30 | The next trace that matches, recorded after the trace `after` or after the call. It returns the trace as `get_trace` does. |
| `compare_traces` | `before`, `after` | What changed between two traces: time, SQL count and SQL time, status, the issues fixed and the new ones. |
| `list_issues` | `query`, `limit` up to 100, default 20 | The project's issues, one per place in the code, most recent first. Each has its place, its fix, how often it happened, its endpoints and its fingerprint. |
| `get_issue` | `fingerprint` | One issue in detail, when it was first seen, and its latest traces. |
| `list_endpoints` | `query`, `limit` up to 100, default 20 | HTTP endpoints, busiest first: calls, p50 and p95 time, average SQL per call, errors and traces with issues. |
| `list_calls` | `query`, `limit` up to 100, default 20 | Calls to databases, Redis, caches, HTTP services and other systems across all traces, grouped by statement or operation, heaviest first: how often each runs, the most per trace, the total and slowest time, its place in the code, a sample trace and the `call:` filter that finds its traces. A search such as `system:sql op:select` or `system:redis failed:true` narrows them. |
| `search_logs` | `query`, `limit` up to 200, default 50 | Log records, newest first, with their level, logger and trace. A search such as `level>=warning logger:app.*` narrows them. |

`get_trace` takes a `focus`:

- `issues`, the default, shows the branches of the call tree with issues,
  errors and most of the time.
- `tree` shows the whole call tree.
- `sql` shows every statement, grouped.
- `logs` shows every log record.

The tree folds repeats into one line, such as `SELECT auth_user ×50`, and says
how much it left out. An answer stays under about 4,000 tokens. A longer one
ends with a note on how much was cut and asks for a narrower search or focus.

While the Tracepanel agent serves the console, `get_trace` and
`wait_for_trace` end with a link to the trace in the console. You can open the
same trace that the coding agent read.

## What the model sees [#what-the-model-sees]

An agent sends its tool answers to its model's provider. So by default, the
answers leave out the values in your data. SQL comes without its parameters,
as in `WHERE id = %s`, and errors come without their local variables. The
answers do include log messages, paths and the names of views and tasks.

`--values` adds SQL parameters and local variables. Values under
names that look like secrets, such as passwords, tokens and keys, stay masked
with or without `--values`.

```bash
claude mcp add --scope project tracepanel -- tracepanel-agent mcp --values
```
