Skip to content
Agentic Control Plane

The Sentry MCP server control model, explained

The Sentry MCP server is the page in this series where the grading runs the other way: first-party, hosted at https://mcp.sentry.dev/mcp on Cloudflare Workers with a local stdio fallback (@sentry/mcp-server), wired into Claude Code, Cursor, and VS Code for error triage, and — unusually — shipping with a security document that states its threat model and enforcement points explicitly. Most servers we survey make us reconstruct the control model from flags; Sentry wrote it down. This page is the reference: what ships, how each mechanism behaves, and where even this model ends. Sources: the repo, the security doc, and the skill registry source.

This page covers the server’s own controls. For the cross-server picture, see the MCP server controls comparison; for what a control layer adds on top, the coverage matrix.

What’s at stake on this surface

The surface is read-heavy, and the reads are the point: issue details, event stack traces, breadcrumbs, replays, attachments, source context. That’s exactly the material a coding agent needs to fix a bug, and exactly the material an exfiltration wants — stack traces carry file paths, variable values, request data, and occasionally the secrets your app leaked into an error. The write side is narrower but has one sleeper: DSN creation. A DSN is the address an application sends its telemetry to. An agent that can mint DSNs (create_dsn, under the project-management skill) and also edits application code can repoint where events flow — a standing-configuration write with the same shape as Stripe’s webhook-endpoint creation. The rest of the write surface — resolve/assign/update issues, create projects and teams, create and delete uptime monitors — is recoverable but noisy: an agent that mass-resolves issues has blinded your on-call.

One more thing worth naming precisely, because it circulated as scarier than it is: the June 2026 “agentjacking” discourse around monitoring MCP servers was about deployment defaults, not a code vulnerability. A third-party hardening guide from July 2026 puts it directly: “The attack vector isn’t in Sentry MCP’s code; it’s in the default configuration.” Treat it as commentary on how people wire the server up, not as an incident in the server.

Dual-token OAuth: the client never holds the credential

This is centerpiece one, and no other server in the series does it. The hosted deployment runs two authorization layers: the MCP client authenticates to the MCP server’s own OAuth provider and receives a downstream MCP token; the upstream Sentry token is obtained by the server, stored in the grant’s encrypted props, and — in the doc’s words — “never sent directly to the MCP client.” On each request the worker validates the MCP token, reconstructs the session context, and makes the Sentry API call itself. The doc states the property as a design goal: Sentry credentials are server-held; MCP clients never need direct Sentry API tokens.

Compare the two strong ownership stories in this series. Stripe’s restricted keys put the scoping at the vendor: the client holds a credential, but the vendor enforces what it can do. Sentry puts the credential itself out of the client’s reach: whatever is compromised on the client side — the config file, the agent’s context, the harness — there is no raw Sentry token there to steal. An attacker who obtains the MCP token gets a wrapper bound to one grant’s skills and path constraints, not the org-scoped upstream credential. Refresh doesn’t widen it either: the doc is explicit that refresh reuses the stored grant props rather than re-deriving access. The escape valve is opt-in and honest about being one — a Sentry-Bearer header mode where the client deliberately supplies its own raw token and the worker stores nothing.

Skills and grantedSkills: grant-time authorization done right

Centerpiece two. Tools are grouped into skills: inspect (read-only issues, events, traces, replays, releases, monitors — enabled by default), seer (the AI debugger — enabled by default), triage (“Resolve, assign, and update issues” — disabled by default), and project-management (“Create and modify projects, teams, DSNs, and uptime monitors” — disabled by default). The security doc calls this “the primary authorization mechanism for tool exposure”: tools are registered only when a skill they declare is enabled, so ungranted tools don’t exist on the surface — the same subtraction-not-denial property we credit GitHub’s toolsets for, but bound to the OAuth grant rather than to a launch flag the agent’s config controls. The session’s grantedSkills ride in the token’s encrypted props and are checked at runtime.

Two details show iteration, which is rarer than architecture. First, the write skills defaulting to off is a chosen posture, not an accident — the read path is the product; the write path is opt-in. Second, skills replaced something: the older grantedScopes mechanism survives only for backward compatibility, with a code comment dating its removal — deprecated January 1, 2026. A vendor that ships a coarse authorization model and then replaces it with a finer one, on a schedule, is doing the work most MCP servers haven’t started.

Path constraints, fail-closed grants, SSRF validation: the hardening most servers lack

Three mechanisms that would each be the headline on a lesser page:

  • Org/project path constraints, enforced per request. Connect at /mcp/{org} or /mcp/{org}/{project} and the constraint is stored in the grant and checked on every request — “a token minted for one scoped MCP URL cannot be reused against a broader path.” Scoped sessions also default tools to the constrained org/project and hide discovery tools. This is the closest thing in the series to a resource boundary that travels with the credential.
  • Fail-closed on stale grants. The doc’s sentence deserves quoting because most servers can’t write it: “Stale or invalid grants fail closed: missing props, invalid skills, or rejected upstream tokens are revoked or require re-authentication.” Even removed skills degrade safely — grants holding the retired preprod skill are treated as read-only inspect.
  • SSRF validation on regionUrl. A tool argument that names a host is an SSRF invitation; Sentry validates it — HTTPS required, base host only unless the domain is in an explicit SENTRY_ALLOWED_REGION_DOMAINS allowlist. Most servers in this series don’t validate argument-supplied URLs at all.

Add the grant-time consent screen — first-time clients require user approval, remembered in signed cookies — and multi-tenant checks that verify org access upstream, and you have the most complete defensive checklist we’ve reviewed.

The local server: the strong architecture stays home

The stdio server (npx @sentry/mcp-server@latest --access-token=..., per the README) inverts the headline property: it takes a raw Sentry user auth token — org read plus project, team, and event writes — via flag or SENTRY_ACCESS_TOKEN, on the same machine as the agent. Skill filtering carries over (--skills=inspect,triage to narrow, --disable-skills=seer to subtract; the same as ?skills= query parameters on direct remote auth), but it’s now a launch flag in a config the agent can typically read and often write, and the credential it filters is the real one. The dual-token design is a property of the hosted deployment, not of the server as such. If the choice is available, the hosted server with a project-scoped URL is the strictly stronger posture.

What’s missing: the call-time layer

Now the altitude line, stated precisely, because nothing here is a flaw in what Sentry built — it’s the boundary of what grant-time architecture can express:

  • Skills gate which tools exist, not when they may fire. A grant with triage enabled has authorized every resolve, every assignment, every issue update, for the life of the grant. No native mechanism distinguishes the first update_issue from the five-hundredth, or a resolve on a test project from a resolve on the payments project’s top crash.
  • No approvals. The consent screen fires once, at grant time, for the human connecting the client. No tool call can be held for a human afterward — there is no native way to say “DSN creation requires a yes.”
  • No budgets or velocity limits. The security doc describes no per-session rate or count limits; a runaway loop resolving issues is processed call by call like any other client.
  • No operator-facing audit. Server-side diagnostic logging exists, with deliberate secret redaction — but there is no queryable record of which tools an agent called, with what arguments, under which grant (the general MCP audit gap). The grant decides what can happen; nothing records what did.

Where the native model ends

Sentry is what a vendor taking the MCP-server side of the problem seriously looks like: the credential held out of the client’s reach, authorization bound to the grant instead of the config file, resource constraints checked on every request, failure modes that close instead of open, and a deprecation schedule that proves the model is maintained. Grade it at the top of the comparison table — we do. And the seam is exactly one line: every decision this architecture makes, it makes at grant time. Which skills exist, which org is reachable, which client is approved — all settled before the session’s first tool call, none revisited during it. The best grant-time architecture in the series still cannot say this call, now, needs a human, and still writes nothing down.

The practical posture: use the hosted server, scope the URL to one project, leave triage and project-management off until a task needs them, treat create_dsn as the write to watch, and keep the local stdio server for self-hosted Sentry only. Then put the per-call policy, the approval on the writes, and the record of what actually ran in a layer that decides at call time — the one altitude this model, by its own careful design, never occupies.