โ† All posts
RELEASE September 6, 2026 ยท 4 min read

Your coding agent can read production now

SR
Sentrinel Team
Product & engineering

Coding agents fix bugs from a stack trace. Until now, the stack trace had to get to them the way everything else does: someone opens the dashboard, finds the issue, copies the trace, pastes it into a prompt, then goes back for the request body, then back again for the trace. The agent is fast. The person feeding it is the bottleneck.

So we built the other half. Sentrinel now ships an MCP server โ€” for Claude Code, Codex, Cursor, anything that speaks the protocol โ€” and a CLI for everything that does not. Both hand the agent the same thing: your issues, logs, traces and requests, on a key that can see one app and do nothing else.

The session now looks like this:

Look at Sentrinel's top unresolved issue, find the cause in this repo, and fix it.

The agent calls list_issues, picks one, calls get_issue for the stack trace and the ids of the request and trace behind the latest occurrence, calls get_request for the exact body that broke it, and starts reading your code. Nobody pastes anything.

What it gets

Six tools, and the order they are used in is the order you would use them in yourself:

Tool Gives the agent
list_issues the bug list, newest-firing first, with ids
get_issue the stack trace, where it fires, who it hit, and the request and trace ids of the latest occurrence
get_request one captured request: headers, body, response, the error
get_trace the span tree โ€” which call was slow or failed, and inside what
search_logs log lines, each carrying the request and trace they belong to
set_issue_status resolve, ignore or reopen โ€” once the fix has actually shipped

Every renderer ends with the identifiers the agent needs for its next call. An issue does not just show a trace id; it says get_trace <id>. That sounds cosmetic. It is the difference between an agent that pulls the trace and one that asks you where to find it.

The key is the part we spent the time on

An agent's key lives in a config file on a laptop. That is the single most likely place a credential leaks, so we designed it to be safe to lose:

Every read tool carries readOnlyHint, so an agent's own guardrails treat them as safe. set_issue_status is the one write, and the server refuses it for a read-only key regardless of what the agent believes about its own permissions.

Hand it the SDK's ingest key by mistake and it refuses to start, naming the kind you gave it โ€” a 401 from the server would have read as "wrong key" when the truth is "wrong kind of key". The kinds themselves are the subject of the next post.

Setting it up

curl -fsSL https://sentrinel.dev/install-mcp.sh | SENTRINEL_API_KEY=snt_mcp_โ€ฆ bash

That is the whole setup: it installs the server and the CLI, writes the key to ~/.sentrinel/env at 0600, and registers the server with Claude Code. The key is in no config file and in no ps output, which is most of why it is worth doing this way rather than pasting --env flags around.

Issue the key from API Keys โ†’ Generate โ†’ AI agent. Codex and Cursor configs, and every tool's arguments, are in the guide.

The CLI, for everything else

Not every harness speaks MCP. The CLI prints the same Markdown to stdout, so it works with a shell script, a DeepSeek harness, or a prompt you assemble by hand:

sentrinel issues                         # unresolved, last 7 days
sentrinel issue 5f3aโ€ฆ                    # stack trace, request id, trace id
sentrinel request <id>
sentrinel logs --level error --search "card declined"
sentrinel issue 5f3aโ€ฆ | claude -p "Find the cause of this in the current repo and fix it."

Failures go to stderr with exit 1, so a script can tell "no issues" from "could not reach the API". --json gives the raw response when you want to do something else with it.

One thing that surprised us

The server writes nothing to stdout except protocol frames. A single stray console.log there corrupts the stream, silently, and the agent reports that the server "returned nothing". We test for zero bytes on stderr and exactly the expected frames on stdout, because this is the sort of bug that would ship green and fail only in someone else's editor.

The whole thing is under 700 lines. Most of the design went into the key.