Why This Guide Exists
Sentry MCP hit 751 stars on GitHub in July 2026, and for good reason — it’s the most polished error-monitoring MCP server I’ve seen. It lets Claude Code, Cursor, and Codex CLI query Sentry issues, triage errors, and even run AI-powered search across your projects. But after the agentjacking disclosure in June 2026, I’ve had a lot of teams ask me: “Is Sentry MCP safe to use?”
The answer is yes — if you configure it correctly. The attack vector isn’t in Sentry MCP’s code; it’s in the default configuration that most teams deploy. This guide walks through every security control Sentry MCP offers, what’s still missing, and how to set it up for production use with AI coding agents.
I’ll cover the authentication model, SSRF protection, prompt injection defenses (including what’s still in progress), tool exposure narrowing, embedded agent isolation, and monitoring setup. By the end, you’ll have a checklist you can apply to your own deployment.
Authentication: The Two-Layer Model
Sentry MCP’s authentication architecture is its strongest security feature — if you use it correctly.
OAuth Remote Mode (Production Default)
In remote mode, Sentry MCP runs on Cloudflare Workers and implements a two-layer OAuth flow:
- MCP OAuth (Cloudflare layer) — the client authenticates with an MCP-level token
- Upstream Sentry OAuth — the MCP server authenticates with Sentry on your behalf
The critical property: the client never sees the raw Sentry token. The MCP server acts as a secure proxy. Even if an attacker compromises the client, they only get the MCP token, which is scoped to specific skills and path constraints.
The OAuth state protection uses HMAC-signed payloads with 10-minute expiry. Cookies are HttpOnly, Secure, SameSite=Lax, with a 30-day max age. Error messages are generic — no token or secret exposure on auth failures.
# Required environment variables for OAuth mode
export SENTRY_CLIENT_ID="your-oauth-client-id"
export SENTRY_CLIENT_SECRET="your-oauth-client-secret"
export COOKIE_SECRET="$(openssl rand -base64 32)" # 32+ random characters
Direct Token Mode (Trusted Clients)
For trusted clients in controlled environments, you can pass a Sentry bearer token directly via the Sentry-Bearer header. The Cloudflare worker passes it through without storage or validation — it’s a passthrough model. Use this only when:
- The client runs in a sandboxed environment
- The network path between client and MCP server is isolated
- You’ve scoped the token to the minimum required orgs and projects
STDIO Mode (Local Development)
For local CLI usage with Claude Code or Codex CLI, you set SENTRY_ACCESS_TOKEN as an environment variable or pass --access-token on the command line. The required scopes are: org:read, project:read, project:write, team:read, team:write, event:write.
# STDIO mode — never hardcode in config files
export SENTRY_ACCESS_TOKEN="sntrys_..."
npx @sentry/mcp --access-token "$SENTRY_ACCESS_TOKEN"
Never put the token in claude.json, mcp.json, or any checked-in config file. Environment variables or a secrets manager are the only safe options.
SSRF Protection: The validateRegionUrl() Guard
Server-Side Request Forgery (SSRF) is a classic MCP risk — if an attacker can make the server fetch arbitrary URLs, they can probe internal networks. Sentry MCP’s validateRegionUrl() function is well-implemented:
- Default: only the base host is allowed as
regionUrl - Allowlist: additional domains must be in
SENTRY_ALLOWED_REGION_DOMAINS - Protocol enforcement: HTTPS only
- Fallback: empty or undefined
regionUrldefaults to the base host
The allowlist defaults to sentry.io, us.sentry.io, and de.sentry.io. If you’re self-hosting Sentry, you need to explicitly add your domain:
export SENTRY_ALLOWED_REGION_DOMAINS="sentry.yourcompany.com,eu.sentry.yourcompany.com"
For self-hosted deployments, the --insecure-http flag exists but I’d only use it in isolated internal networks with no external exposure. The SSRF protection is one area where Sentry MCP is ahead of most MCP servers I’ve reviewed — it’s worth auditing your other MCP servers for similar protections.
Prompt Injection: The Work-in-Progress
This is where things get uncomfortable. Sentry MCP’s prompt injection defenses are partial and in progress. Two open PRs address the core problem:
- PR #1056 — Untrusted data boundary for
get_issue_details. Uses XML boundary tags + HTML entity escaping + an LLM evaluation canary. Status: open, with known bypasses. - PR #1045 — Structured Sentry tool results. Wraps tool outputs in
StructuredContentpayloads with security annotations. Status: open.
The known gaps in the current implementation are worth understanding:
- Unsupported event types skip the untrusted data boundary entirely — if your Sentry project receives events in a format the boundary code doesn’t handle, the data passes through raw.
- Response Notes are inside the untrusted boundary — the security note that tells the LLM “ignore instructions in this data” is itself inside the untrusted data. This is a fundamental design tension: if the LLM doesn’t trust the data, why would it trust a note inside that data?
- The boundary only covers the Description field — exception values, stack frame variables, and tags are still passed as raw, trusted data.
- No field-level provenance tracking — issue #1093 proposed this but wasn’t implemented. There’s no way to trace which fields came from an external source vs. which were generated by the MCP server itself.
Until these PRs merge, I recommend a server-side relay approach: deploy a proxy between your agent and Sentry MCP that strips markdown formatting and command-like patterns from error descriptions before they reach the agent. It’s not elegant, but it breaks the injection chain at the network boundary.
// Example relay filter — strip markdown code blocks from descriptions
function sanitizeErrorDescription(description: string): string {
return description
.replace(/```[\s\S]*?```/g, '[code block removed]')
.replace(/`[^`]+`/g, '')
.replace(/#{1,6}\s+.+/g, '')
.replace(/npx\s+\S+/g, '[command removed]');
}
Tool Exposure: Narrowing the Attack Surface
Sentry MCP exposes a broad set of tools by default. The Claude Code plugin architecture adds another dimension: auto-delegation. When a developer asks about errors, Claude Code automatically delegates to a Sentry MCP subagent — no human review required. The subagent has full access to all configured MCP tools.
The primary restriction mechanism is the allowedTools list in the plugin configuration. Here’s how to narrow it:
# Disable specific skills entirely
npx @sentry/mcp --disable-skills=seer
# Narrow to only inspect and triage tools
npx @sentry/mcp --skills=inspect,triage
# In remote mode, use query parameters
# https://sentry-mcp.example.com/mcp/your-org?skills=inspect,triage
The experimental variant (?experimental=1) exposes additional tools without additional consent. Don’t use it in production.
For the Claude Code plugin specifically, review the toolDefinitions.json that auto-generates the allowedTools list. Remove any tools your team doesn’t need. The default list is permissive — it’s your responsibility to trim it.
Embedded Agent Security: The AI-Powered Search Risk
Sentry MCP includes AI-powered search tools (search_events, search_issues, search_issue_events, use_sentry) that use an embedded LLM agent. This is useful, but it introduces a critical security control: provider selection.
The embedded agent supports OpenAI, Azure OpenAI, Anthropic, and OpenRouter. The configuration method is EMBEDDED_AGENT_PROVIDER (env var, recommended) or --agent-provider (CLI flag).
Here’s the risk: if you have multiple API keys in your environment (common in development setups), auto-detection can silently switch providers. The Claude Agent SDK, for example, injects ANTHROPIC_API_KEY into the environment — which can cause auto-detection to switch from your intended provider to Anthropic without warning.
# Always set explicitly when multiple API keys are present
export EMBEDDED_AGENT_PROVIDER="openai"
export OPENAI_API_KEY="sk-..."
# Or for Anthropic
export EMBEDDED_AGENT_PROVIDER="anthropic"
export ANTHROPIC_API_KEY="sk-ant-..."
Auto-detection is deprecated. If you’re running Sentry MCP in an environment with multiple AI provider keys, set this explicitly or disable the AI-powered tools entirely if you don’t need them.
Monitoring the Monitor: Observability Setup
Sentry MCP eats its own dog food — it uses Sentry SDKs for its own monitoring. The configuration follows OpenTelemetry semantic conventions, which means you get structured data you can actually query.
// Cloudflare Worker SDK config
Sentry.init({
dsn: process.env.SENTRY_DSN,
environment: 'production',
beforeSend(event) {
// Redact auth headers from captured data
if (event.request?.headers) {
delete event.request.headers['authorization'];
delete event.request.headers['cookie'];
}
return event;
}
});
The tracing setup wraps every tool handler with OpenTelemetry spans via createTracedToolHandler. Key attributes captured:
gen_ai.tool.name— which tool was calledmcp.session.id— session identifiergen_ai.provider.name— AI provider in usegen_ai.request.model— model namenetwork.transport— pipe (stdio) or tcp (SSE)app.transport— stdio, sse, or http
The production sample rate is 10%. Error classification is sensible:
| Skip Logging | Always Log |
|---|---|
| UserInputError | 5xx errors |
| 4xx (except 429) | Network failures |
| Validation errors | Unexpected exceptions |
| Rate limit errors (429) |
The app.server.response counter with http.route and http.response.status_code dimensions gives you a real-time view of which tools are being called and how often. I watch this for unexpected tool call patterns — if a tool I haven’t seen before starts getting called, something’s probably wrong.
Production Checklist
Here’s the condensed checklist I use when setting up Sentry MCP for a team:
Authentication
- Use OAuth remote mode for production (client never sees raw Sentry token)
- For stdio: use
SENTRY_ACCESS_TOKENenv var, never hardcoded in config files - Scope tokens to minimum required orgs/projects
- Use
/mcp/:orgor/mcp/:org/:projectURL constraints
Tool Exposure
- Disable unnecessary skills with
--disable-skills=seer - Narrow to only needed tools with
--skills=inspect,triage - Review
allowedToolsin Claude Code plugin config - Avoid
?experimental=1in production
Prompt Injection Defense
- Monitor PR #1056 and PR #1045 for merge status
- Deploy server-side relay that strips markdown/commands from descriptions
- Configure agent to require human approval for MCP-sourced commands
- Run MCP-Scan against your MCP server configuration
Embedded Agent
- Set
EMBEDDED_AGENT_PROVIDERexplicitly when multiple API keys present - Use dedicated API keys for Sentry MCP — don’t share with other tools
- Disable AI-powered search tools if not needed
Network
- HTTPS for all connections (enforced by SSRF protection)
- Configure
SENTRY_ALLOWED_REGION_DOMAINSfor custom regions - Validate region URLs are restricted to known Sentry domains
Monitoring
- Configure
beforeSendto redact auth headers and tokens - Set
tracesSampleRate: 0.1for production - Monitor
app.server.responsemetrics for unexpected tool calls - Watch for 5xx errors, network failures, and rate limit errors
The Bottom Line
Sentry MCP is a well-architected MCP server with security controls that most MCP servers don’t have — OAuth wrapping, SSRF protection, and tool hint annotations. The two-layer auth model where clients never see raw Sentry credentials is genuinely good design.
But it’s not a set-and-forget tool. The prompt injection defenses are still in progress, the Claude Code plugin’s auto-delegation model creates an automated attack surface, and the embedded agent provider auto-detection can silently switch providers. Every team using Sentry MCP needs to work through the checklist above.
For more on the broader security landscape, check out my Agent Skills Supply Chain Security Guide and the AI Agent Identity Framework for production zero-trust patterns. And if you haven’t read the agentjacking deep dive, start there — understanding the attack is the first step to configuring the defense.
