Skip to main content
Workflows Library MCP Directory Realtime AI News Sponsor Tier Subscribe
Front Page / AI Tools / Deep Dive

Build a Sentry MCP Server for Agentic Error Triage & Release Monitoring in 2026

An error feed is exactly what an agent should triage: pull issues, check the release that broke, drill into a stack trace. Build a Python FastMCP server for Sentry with read-first tools and guarded writes.

Deepak Bagada

Deepak Bagada

CEO, SaaSNext

Aug 14, 2026 Published
|
Aug 14, 2026 Updated
|
10 Minutes Reading Time
Core Takeaways for Founders & Builders
  • Sentry's error feed becomes agent-callable via typed FastMCP tools — issues, search, detail, release health.
  • Read-first triage: list/search/detail/health are read-only; resolve and comment are the only writes.
  • A scoped Sentry auth token injected via env; read-only by default, event:write only if agents resolve issues.
  • Every resolve carries a reason string and consumes a per-session write budget — no runaway backlog clearing.
  • Every tool call writes a JSONL audit line so error-feed reads and writes are attributable.

By Deepak Bagada, CEO at SaaSNext & Principal AI Architect.

The observability stack that used to be read by humans is now read by agents. Sentry has become the default error-tracking and release-health platform for production teams, and it is also one of the platforms that adopted MCP explicitly in 2026 — which makes sense, because an error feed is exactly the kind of high-signal, high-volume data an agent should triage: pull the newest issues, group them by fingerprint, check which release introduced the regression, and open a fix. Doing that by clicking through a dashboard is a full-time job; doing it through typed MCP tools is a background task an engineer supervises.

This guide builds a production Sentry MCP server in Python with FastMCP: issue enumeration and search, event and stack-trace retrieval, release health, and two guarded writes (resolving an issue and commenting) — secured with a scoped Sentry auth token and read-first by default. It follows the governance-first architecture we catalogue in the MCP directory, and it is designed to feed the incident-response and alert-triage patterns in our AI workflows library.

Server Design Overview

graph TD
  A[Engineer / Agent] --> M[Sentry MCP Server]
  M --> T1[list_issues]
  M --> T2[search_issues]
  M --> T3[get_issue_detail]
  M --> T4[get_release_health]
  M --> T5[resolve_issue]
  M --> T6[add_comment]
  T1 --> S[Sentry API]
  T2 --> S
  T3 --> S
  T4 --> S
  T5 --> S
  T6 --> S
  S --> K[Scoped Auth Token]
  M --> L[Audit Log]

The server is a read-first triage surface with two explicit, rate-limited writes. Issue listing, search, detail, and release health are the workhorses — agents can answer "what broke, when, and in which release" without a human touching the console. Resolving an issue and adding a comment are the only state-changing tools, and both are named, audited, and gated behind a budget, because a mis-issued resolve is how signal disappears.

Part 1 — Authentication and setup

.env

SENTRY_AUTH_TOKEN=sntrys_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
SENTRY_ORG=acme-corp
SENTRY_PROJECT=checkout-api
SENTRY_API_BASE=https://sentry.io/api/0
AUDIT_LOG=./audit.jsonl
WRITE_BUDGET_PER_SESSION=20

auth.py

import os, json, time

def headers() -> dict:
    # Sentry auth tokens are bearer credentials; scope them to read + narrow write.
    return {
        "Authorization": f"Bearer {os.environ['SENTRY_AUTH_TOKEN']}",
        "Content-Type": "application/json",
    }

def audit(tool: str, meta: dict) -> None:
    line = json.dumps({"ts": time.time(), "tool": tool, **meta})
    with open(os.environ["AUDIT_LOG"], "a") as f:
        f.write(line + "
")

def write_budget_ok() -> bool:
    # Counts writes this process has performed; enforced in the write tools.
    return write_count() < int(os.environ["WRITE_BUDGET_PER_SESSION"])

Sentry issues tokens per user and per scope: read-only tokens for the triage tools, and a token with event:write + project:write only if agents should resolve issues. The audit helper appends a JSONL line for every tool call, and write_budget_ok enforces a per-session write budget — an agent can triage thousands of issues but only resolve a bounded number per session, which is the correct posture when an AI is touching the state of a production error feed.

Part 2 — The FastMCP server

server.py

import os, httpx
from fastmcp import FastMCP

server = FastMCP(name="sentry-triage", version="2.1.0")
API = os.environ["SENTRY_API_BASE"]
ORG = os.environ["SENTRY_ORG"]
PROJECT = os.environ["SENTRY_PROJECT"]

@server.tool(description="List the newest issues for the project, optionally by status.")
def list_issues(status: str = "unresolved", limit: int = 25) -> list:
    params = {"project": PROJECT, "query": f"is:{status}", "limit": limit}
    r = httpx.get(f"{API}/projects/{ORG}/{PROJECT}/issues/",
                  params=params, headers=headers(), timeout=15)
    r.raise_for_status()
    audit("list_issues", {"status": status, "limit": limit})
    return [{
        "id": i["id"], "title": i["title"],
        "level": i["level"], "count": i["count"],
        "first_seen": i["firstSeen"], "last_seen": i["lastSeen"],
        "permalink": i["permalink"],
    } for i in r.json()]

@server.tool(description="Search issues by free-text query and filters.")
def search_issues(query: str, status: str = "unresolved", limit: int = 25) -> list:
    params = {"project": PROJECT, "query": f"is:{status} {query}", "limit": limit}
    r = httpx.get(f"{API}/projects/{ORG}/{PROJECT}/issues/",
                  params=params, headers=headers(), timeout=15)
    r.raise_for_status()
    audit("search_issues", {"query": query, "limit": limit})
    return [{"id": i["id"], "title": i["title"], "count": i["count"]}
            for i in r.json()]

@server.tool(description="Get full detail for one issue, including stack trace metadata.")
def get_issue_detail(issue_id: str) -> dict:
    r = httpx.get(f"{API}/issues/{issue_id}/", headers=headers(), timeout=15)
    r.raise_for_status()
    audit("get_issue_detail", {"issue_id": issue_id})
    return r.json()

The pattern repeats cleanly: typed tools translate to Sentry API calls, responses are trimmed to the fields an agent needs, and every call is audited. The inputSchema for each tool is inferred from the Python signature by FastMCP, so any MCP client can introspect the tools before calling. Trimming the response — title, level, count, first/last seen, permalink — is what keeps triage loops cheap: the agent gets the signal without pulling the full stack trace until it actually drills in.

Part 3 — Release health and the guarded writes

releases.py

from fastmcp import FastMCP
import httpx, os

API = os.environ["SENTRY_API_BASE"]
ORG = os.environ["SENTRY_ORG"]

@server.tool(description="Get release health: crash-free rate and error counts per release.")
def get_release_health(release: str | None = None, limit: int = 10) -> list:
    params = {"project": PROJECT, "summary": "1", "limit": limit}
    if release:
        params["query"] = release
    r = httpx.get(f"{API}/organizations/{ORG}/releases/",
                  params=params, headers=headers(), timeout=15)
    r.raise_for_status()
    audit("get_release_health", {"release": release or "latest", "limit": limit})
    return [{"version": rel["version"],
             "crash_free_rate": rel.get("crashFreeRate"),
             "error_count": rel.get("errorCount")} for rel in r.json()]

@server.tool(description="Resolve an issue. Write operation, rate-limited per session.")
def resolve_issue(issue_id: str, reason: str) -> dict:
    if not write_budget_ok():
        raise ValueError("write budget exceeded for this session")
    if not reason.strip():
        raise ValueError("reason is required so resolves are reviewable")
    r = httpx.put(f"{API}/issues/{issue_id}/", headers=headers(),
                  json={"status": "resolved"}, timeout=15)
    r.raise_for_status()
    audit("resolve_issue", {"issue_id": issue_id, "reason": reason})
    return {"issue_id": issue_id, "status": "resolved", "reason": reason}

@server.tool(description="Add a comment to an issue. Write operation, rate-limited.")
def add_comment(issue_id: str, comment: str) -> dict:
    if not write_budget_ok():
        raise ValueError("write budget exceeded for this session")
    r = httpx.post(f"{API}/issues/{issue_id}/comments/", headers=headers(),
                   json={"comment": comment}, timeout=15)
    r.raise_for_status()
    audit("add_comment", {"issue_id": issue_id})
    return {"issue_id": issue_id, "comment_id": r.json()["id"]}

The writes are where the governance lives. resolve_issue demands a reason and refuses to act without one, and both writes consume the per-session budget — an agent cannot resolve the entire backlog in one runaway loop. The reason string is the reviewable artifact: when an engineer audits the session, every state change carries its justification. That bounded-write posture is the same one we recommend across every server in the MCP directory.

Part 4 — Client configuration and launch

mcpServers config

{
  "mcpServers": {
    "sentry-triage": {
      "command": "python",
      "args": ["-m", "sentry_triage_mcp"],
      "env": {
        "SENTRY_AUTH_TOKEN": "${SENTRY_AUTH_TOKEN}",
        "SENTRY_ORG": "acme-corp",
        "SENTRY_PROJECT": "checkout-api",
        "WRITE_BUDGET_PER_SESSION": "20"
      }
    }
  }
}

main.py

from server import server
import releases  # registers release health + write tools

if __name__ == "__main__":
    server.run(transport="stdio")  # desktop; or transport="http" for remote

The mcpServers block wires the server into Claude Desktop, Cursor, or any MCP client: python -m sentry_triage_mcp starts it, env injects the scoped token (never a literal secret), and the typed tools appear automatically. stdio serves desktop agents; HTTP serves remote or stateless MCP 2026-07-28 deployments behind a gateway, where the token stays on the server side and clients authenticate at the edge. Deployment guidance for both transports lives in the MCP directory.

Security & governance checklist

  1. Read-first triage. List, search, detail, and release health are read-only; resolve and comment are the only writes.
  2. Scoped tokens. A read-only token by default; event:write and project:write only if agents should change issue state.
  3. Write budget per session. Resolves and comments consume a bounded budget, so a runaway loop cannot clear the backlog.
  4. Reason required. Every resolve carries a reason string — the reviewable artifact for audits.
  5. Audit every call. JSONL audit of tool, timestamp, and parameters; error-feed reads must be attributable.

Frequently Asked Questions

Q: Why expose Sentry through MCP instead of the dashboard?

A: Because triage is the task: an agent can pull the newest issues, search by fingerprint, check which release introduced a regression, and drill into a stack trace without a human clicking through the console — while the engineer supervises typed tool calls and the audit trail.

Q: How is Sentry authentication handled?

A: A scoped Sentry auth token used as a bearer credential, injected via environment variables. Use a read-only token by default and add event:write/project:write scopes only if agents should resolve issues or comment.

Q: Which tools are safe to expose read-first?

A: list_issues, search_issues, get_issue_detail, and get_release_health are read-only and safe. resolve_issue and add_comment are state-changing and carry a per-session write budget plus a mandatory reason field.

Q: Can this server run for remote agents?

A: Yes. The HTTP transport serves the same tools for remote or stateless MCP 2026-07-28 deployments, typically behind a gateway where the Sentry token stays server-side and OAuth handles client auth at the edge.

Q: How do I keep token costs low on triage?

A: Trim every tool response to the fields an agent needs, filter issues at the API level with the query parameter, and fetch full stack traces only in get_issue_detail — which agents should call after narrowing to a handful of candidates.

Executive Briefing

Enjoyed this breakdown? Get our morning dispatch in your inbox.

Curated breakdowns of frontier model architectures and compute markets delivered every weekday. Zero fluff.

Frequently Asked Questions
Because triage is the task: an agent can pull the newest issues, search by fingerprint, check which release introduced a regression, and drill into a stack trace without a human clicking through the console — while the engineer supervises typed tool calls and the audit trail.
A scoped Sentry auth token used as a bearer credential, injected via environment variables. Use a read-only token by default and add event:write/project:write scopes only if agents should resolve issues or comment.
list_issues, search_issues, get_issue_detail, and get_release_health are read-only and safe. resolve_issue and add_comment are state-changing and carry a per-session write budget plus a mandatory reason field.
Yes. The HTTP transport serves the same tools for remote or stateless MCP 2026-07-28 deployments, typically behind a gateway where the Sentry token stays server-side and OAuth handles client auth at the edge.
Trim every tool response to the fields an agent needs, filter issues at the API level with the query parameter, and fetch full stack traces only in get_issue_detail after narrowing to a handful of candidates.
Deepak Bagada
Author Profile

Deepak Bagada

CEO, SaaSNext

Deepak Bagada is the CEO of SaaSNext and founder of Daily AI World. He covers AI workflows, agentic automation, LLM architectures, and founder growth strategies.

Related Intelligence Analysis

Briefing AI Tools

Vercel AI SDK Tool Calling React: 5 Steps (2026)

Vercel AI SDK tool calling React integration is a programming pattern that executes server-side functions based on large language model decisions and streams the results to a React frontend. By combining streamText with...

Deepak Bagada Deepak Bagada
12m read
Breaking AI Tools

Fact-Density vs. Word Count: The New SEO for 2026

Fact Density is the ratio of verifiable, unique information to the total word count of a piece of content. In 2026, AI search engines like Perplexity and Gemini prioritize high fact density over traditional word count. A...

Deepak Bagada Deepak Bagada
4m read
Audio Briefing
Accessibility Preferences
High Contrast Mode
Accessible Reading Font

Keyboard Shortcuts

Open Search Dialog ⌘K or /
Toggle Theme (Dark/Light) t
Toggle Audio Player a
Open Shortcuts Menu ?
Close Active Dialog Esc