Skip to content

feat(mcp): Accept an <org>/<project> target for sentry mcp - #1800

Merged
BYK merged 1 commit into
mainfrom
feat/mcp-target-positional
Nov 2, 2026
Merged

BYK merged 1 commit into
mainfrom
feat/mcp-target-positional

Conversation

@sentry-junior

@sentry-junior sentry-junior Bot commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

Follow-up to #1731, part of the CLI-first refactor in #1357. sentry mcp now takes the same <org>/<project> target as the rest of the CLI:

sentry mcp acme/        # limit every call to one organization
sentry mcp acme/web     # limit calls to one project
npx @sentry/mcp-server acme/web

Behavior

  • Parsing: the optional [<org>/[<project>]] positional is read by the CLI's shared org/project parser. That's parseOrgProjectInput, the side-effect-free form of parseOrgProjectArg, so a pasted URL can't change the server context. Only forms that name an org are accepted: acme/ sets the org, and acme/web sets the org and project.
  • Bare slug: a bare acme is refused with a hint to pass acme/, because every other command reads a bare slug as a project search.
  • URLs: scheme://… targets are refused with a hint to set SENTRY_URL, because the host comes from env. The check runs before the shared parser, which doesn't recognize URLs like https://acme.sentry.io/issues/.
  • More than one project: acme/web/api, acme/web,api, and invalid slugs (?, #, …) are refused.
  • Flags: --org/--project and their deprecated --organization-slug/--project-slug aliases still work. If a target and a flag disagree, that's a ValidationError, like the existing alias conflicts in mergeMcpArgs. Matching values are fine. acme/ combined with --project=web scopes to acme/web.
  • Default command (@sentry/mcp-server): isMcpInvocation() treats a first word that names no route as mcp's target. This matches Stricli, which routes an unknown first token to the default command as a positional. So npx @sentry/mcp-server acme/web starts the server without the CLI's telemetry or recovery middleware. Route names (mcp, auth, help) still win over a target.

Ambiguity with route names

Under @sentry/mcp-server, a word that matches a route is always the route. An org that happens to be called auth has to be written as auth/, which already gets parsed as a target because it isn't a route name. A bare word is never a valid target anyway. So npx @sentry/mcp-server issue (someone trying a CLI command the slim bundle doesn't have) now reaches the target parser and fails with 'issue' names no command, and a target needs an organization: …. issue list fails on Stricli's arity check (Too many arguments, expected 1 but encountered "list"). Before this change, both failed with expected 0 arguments. The bundle test now asserts these messages.

Docs

  • --help examples, the generated command docs, and the sentry-cli skill (SKILL.md, references/mcp.md) are all regenerated.
  • The mcp docs fragment has a new "Limit the server to an organization or project" section with an MCP client config.
  • docs/testing/stdio.md lists the target next to --org/--project.
  • The mcp.sentry.dev setup docs aren't changed here, so this PR doesn't close Update mcp.sentry.dev stdio setup for the new flags #1786.

Checks

  • pnpm run lint, pnpm run check:generated, and pnpm run docs:check pass. tsc --noEmit for packages/cli passes, and the workspace pnpm run tsc showed no type errors.
  • Focused vitest suites pass: test/lib/mcp/*, mcp-command, mcp-start, mcp-auth, mcp-login, arg-parsing (unit and property), completion-coverage, completions.property, fragment-commands, generate-skill-markdown, cli-startup, app-identity, help-graphics, and test/commands (148 files).
  • In this sandbox, test/lib/completions.test.ts has two EACCES/EPERM cases that fail the same way on main, so they're unrelated to this change.
  • The @sentry/mcp-server bundle builds at 3,639,734 bytes, +1.4 KB over main and under the 3.75 MiB budget. test:bundle passes 15/15.

via @BYK.

--

View Session in Sentry

`sentry mcp [<org>/[<project>]]` scopes the server like --org and
--project do: `acme/` limits every call to an organization, `acme/web`
to a project. The target goes through the CLI's shared org/project
parser (parseOrgProjectInput, the side-effect-free parseOrgProjectArg).

A bare `acme` is refused with a hint to pass `acme/`, since every other
command reads it as a project search. URLs are refused with a hint to
set SENTRY_URL, since the host comes from the environment. A target and
--org/--project (or their deprecated aliases) that disagree are a
ValidationError, like the existing alias conflicts in mergeMcpArgs.

Where `mcp` is the default command (`@sentry/mcp-server`), a first word
that names no route is the target, so `npx @sentry/mcp-server acme/web`
starts the server without the CLI's telemetry. Route names still win.

Refs #1357, #1731

Co-Authored-By: BYK <126780+BYK@users.noreply.github.com>
@vercel

vercel Bot commented Nov 2, 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 Nov 2, 2026 1:58pm UTC

Request Review

@BYK
BYK merged commit bc0c3ec into main Nov 2, 2026
27 checks passed
@BYK
BYK deleted the feat/mcp-target-positional branch November 2, 2026 14:21

This branch was successfully deployed

1 active deployment
Preview — 340cdcd9 Deployed Nov 2, 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.

Update mcp.sentry.dev stdio setup for the new flags

1 participant