Skip to content

feat(mcp-server): Turn @sentry/mcp-server into a stdio proxy to the hosted MCP - #1743

Closed
sentry-junior[bot] wants to merge 1 commit into
ref/retire-mcp-server-packagefrom
feat/mcp-server-stdio-proxy
Closed

sentry-junior[bot] wants to merge 1 commit into
ref/retire-mcp-server-packagefrom
feat/mcp-server-stdio-proxy

Conversation

@sentry-junior

@sentry-junior sentry-junior Bot commented Oct 29, 2026

Copy link
Copy Markdown
Contributor

Stacked on #1731. That PR moves the full stdio server into sentry mcp. This one keeps @sentry/mcp-server and replaces its deprecation shim with a small stdio proxy to the hosted Sentry MCP. Once this merges, the @sentry/mcp-server work is done and the package can be published again. The design is in #1669 ("@sentry/mcp-server stays as a stdio proxy", task 11.6).

What the proxy does

  • The sentry-mcp bin connects stdin/stdout to https://mcp.sentry.dev/mcp over Streamable HTTP. It sends --access-token / SENTRY_ACCESS_TOKEN as Authorization: Sentry-Bearer <token>. The hosted MCP routes that header before OAuth, so the proxy has no auth flow of its own.
  • It forwards JSON-RPC messages unchanged in both directions: requests, responses, notifications (progress, logging, list_changed), and server-initiated messages on the standalone GET stream. After initialize it sets the negotiated MCP-Protocol-Version on later HTTP requests.
  • If an upstream request fails (401, a 400 for bad skills, a network error), the client gets a JSON-RPC error for that request id and the details go to stderr. Nothing but protocol output goes to stdout.
  • When stdin closes, it waits for in-flight requests to finish, sends DELETE for the session, and exits 0. On SIGINT/SIGTERM it exits right away.

Flags. The old local server's flags map onto the hosted URL where the hosted MCP supports them:

  • --organization-slug / --project-slug become /mcp/<org>/<project>.
  • --skills / MCP_SKILLS and --disable-skills / MCP_DISABLE_SKILLS become query params. --all-skills sends nothing, since that is the hosted default.
  • --experimental becomes ?experimental=1.
  • --mcp-url / MCP_URL sets the hosted origin, for testing. In the old CLI this flag already meant the MCP origin, while --url meant the Sentry URL, so --url keeps that meaning.

SaaS only. The hosted MCP serves only sentry.io; regional and org subdomains go through sentry.io. If --host, --url, SENTRY_HOST, or SENTRY_URL names any other host, or --insecure-http is set, the proxy exits 1 and points to npx -y sentry mcp, which runs the tools locally against any host. The local embedded-agent flags (--agent-provider, --openai-*, --anthropic-*) also exit 1 with that pointer, so a chosen LLM endpoint is never silently swapped for the hosted one. --sentry-dsn and the agent env vars (OPENAI_API_KEY, ...) only print a warning. With no token, and for sentry-mcp auth ..., the proxy exits 1 and explains how to create a token or use npx -y sentry mcp with sentry auth login.

Dependency footprint. The sources are plain JS in bin/ and lib/. tsdown bundles them with @modelcontextprotocol/sdk (catalog version, now a devDependency) into one file, dist/sentry-mcp.js, on prepack. The published package has no runtime dependencies. npm pack --dry-run shows 3 files: 77.6 kB packed, 335 kB unpacked. A clean npm install of the tarball adds 1 package (344 KB). Depending on the SDK unbundled would add 96 packages (27 MB), because the SDK brings express, hono, ajv, and others. scripts/check-workspace-deps.mjs now rejects any workspace dependency from @sentry/mcp-server, and there is a test for that. Docs that called the package deprecated or retired now describe both entry points. server.json is unchanged and still points at sentry mcp.

Tests

  • Unit tests for flag and env mapping, precedence, the missing-token and self-hosted errors, the rejected flags, and the warnings.
  • An end-to-end test that runs the bin against a local stateful Streamable HTTP MCP server built from the SDK. It covers initialize, tools/list, a tools/call with progress and logging notifications, a list_changed on the GET stream, and a client-to-server notification. It also checks that every request carries Sentry-Bearer and the negotiated protocol version, and covers a rejected token returned as a JSON-RPC error, draining on stdin close, and a clean exit on SIGTERM.

Open questions:

  • When the hosted MCP gets a Sentry-Bearer token that Sentry rejects, its tool error says "Authorization Expired … Please re-authorize". That wording fits OAuth users, not proxy users with a static token. Changing it belongs in mcp-cloudflare, so it is not part of this PR.
  • The proxy rejects self-hosted hosts even when --mcp-url points to a custom deployment, because it cannot tell which Sentry host that deployment serves.

via BYK.

--

View Junior Session in Sentry

…osted MCP

Keep @sentry/mcp-server instead of retiring it, and replace the
deprecation shim with a small proxy: the sentry-mcp bin forwards stdio
JSON-RPC to the hosted MCP's Streamable HTTP endpoint with
Authorization: Sentry-Bearer <token>. Old flags map onto the hosted URL
(org/project path, skills, experimental); self-hosted hosts and local
embedded-agent flags exit with an error pointing to `npx -y sentry mcp`.

The MCP SDK is bundled with tsdown, so the published package has no
runtime dependencies, and lint:deps rejects any workspace dependency.

Co-Authored-By: BYK <burak.kaya@sentry.io>
@vercel

vercel Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
sentry-local Ready Ready Preview Oct 29, 2026 10:21pm UTC

Request Review

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 0fbbff6. Configure here.

"OPENROUTER_REASONING_EFFORT",
];

const LOOPBACK_HOSTS = new Set(["localhost", "127.0.0.1", "[::1]"]);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IPv6 localhost HTTP URLs rejected

Low Severity

LOOPBACK_HOSTS lists [::1], but URL.hostname for an IPv6 URL is ::1 without brackets, so http://[::1]:… fails the loopback check and is rejected as a non-HTTPS MCP URL.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 0fbbff6. Configure here.

if (!closing) {
log(`Sentry MCP: ${describe(error)}`);
}
};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remote errors leave requests hanging

Medium Severity

remote.onerror only logs. In-flight ids stay in pending, so the client never gets a JSON-RPC error after a mid-session drop, and stdin-close drain never finishes. A failed local.send also skips closeWhenDrained, which can leave the process running.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 0fbbff6. Configure here.

@sentry-junior

sentry-junior Bot commented Oct 29, 2026

Copy link
Copy Markdown
Contributor Author

Closing in favor of shipping @sentry/mcp-server as a slim bundle of the CLI's own sentry mcp server (reworked in #1731). That keeps one implementation and works with self-hosted Sentry, which a proxy to the hosted MCP can't do.

@sentry-junior sentry-junior Bot closed this Oct 29, 2026
sentry-junior Bot added a commit that referenced this pull request Oct 29, 2026
The stdio proxy to the hosted MCP (#1743) is closed in favor of bundling
the CLI's own server, which keeps one implementation and works with
self-hosted Sentry. Update the design decision, rollout step, proposal,
and task 11.6 to match #1731.

Co-Authored-By: BYK <burak.kaya@sentry.io>

This branch was successfully deployed

1 active deployment
Preview — 0fbbff64 Deployed Oct 29, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk: medium PR risk score: medium

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants