Route stdio MCP tool calls to the stored account that knows the org

オープン
#1,756 コメント 1 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

評価

難易度
5/5
見積もり時間
1週間以上
初心者へのやさしさ
38/100
issue の種類
機能追加
明瞭さ
おおむね明確
活発さ
活発
技術スタック
node.js, typescript

調査の方向性

Start with the dependency-direction rule in AGENTS.md, then read ServerContext in packages/mcp-core/src/types.ts, apiServiceFromContext(), and the CLI host in packages/cli/src/lib/mcp.ts. Trace selectAccountForOrg in packages/cli/src/lib/db/auth.ts and region handling in packages/cli/src/lib/region.ts and internal/tool-helpers/resolve-region-url.ts. Run the relevant MCP and CLI tests; done means org-scoped calls use the owning account safely, cross-org tools merge results, and hosted/static-token behavior remains unchanged.

索引モデルが issue の本文から書いたものです。

説明

Problem

The CLI stores several accounts and picks the right one for each command based on the targeted organization (selectAccountForOrg in packages/cli/src/lib/db/auth.ts, called from resolveOrgRegion in packages/cli/src/lib/region.ts). The stdio MCP server (@sentry/mcp-server and sentry mcp, which share the CLI's credential store after #1731) does not.

The server resolves one effective account at startup and uses it for every tool call. A token refresh after a 401 stays on that same account. Asking about an org that belongs to another stored login fails. The only workarounds are sentry auth switch plus a restart, or configuring a second MCP server with a different SENTRY_HOST or a static SENTRY_ACCESS_TOKEN.

Why it doesn't work today

  • ServerContext in mcp-core carries a single accessToken: string (packages/mcp-core/src/types.ts). All tools build their API client with apiServiceFromContext() (about 63 call sites), and the region cache (internal/tool-helpers/resolve-region-url.ts) reads the same token.
  • MCP tools use mcp-core's API client, not the CLI's, so the CLI's org-based selection never runs.
  • mcp-core must not import the CLI (see the dependency-direction rule in AGENTS.md), and the hosted MCP has one OAuth grant per session. So this has to be an optional capability that only the stdio host provides.

Proposed approach

  1. mcp-core: add an optional resolver to ServerContext, e.g. resolveCredential({ organizationSlug }) => Promise<{ accessToken, sentryHost, sentryProtocol }>. apiServiceFromContext() takes the org and uses the resolver when present; otherwise it uses accessToken. Key the region cache by the resolved credential. The hosted MCP stays unchanged.
  2. CLI host (packages/cli/src/lib/mcp.ts): implement the resolver with the selectAccountForOrg rules, running each call inside withStoredAccount(). That function already isolates account scope per call through withEnv and AsyncLocalStorage, so overlapping tool calls are safe. Refresh-on-401 targets the account that made the call. An unknown org falls back to the active account. One tool call never mixes identities.
  3. Cross-org tools (find_organizations, whoami): query every usable account and merge the results, as sentry org list does with listUsableAccountsInScope(). The CLI already records which account saw each org in the regions cache (packages/cli/src/lib/db/regions.ts), so later calls route automatically.
  4. Opt-outs and pins: --access-token / SENTRY_ACCESS_TOKEN disables routing. --organization-slug picks the account once at startup. An explicit server (SENTRY_HOST/SENTRY_URL) limits candidates to accounts on that server, matching the CLI.

An alternative would route inside an injected fetch by parsing /organizations/{slug}/ from request URLs. It touches fewer files, but it is implicit and misses endpoints whose paths do not include the org. The explicit resolver is preferred.

Scope

  • First version: route only between accounts on the same server.
  • Later: mixing self-hosted and sentry.io accounts in one server needs a host per account and the region-URL validation (validateRegionUrl) checked against the right server.

Acceptance

  • With two stored sentry.io accounts that each own a different org, one running stdio server can call org-scoped tools on both orgs without auth switch or a restart.
  • find_organizations lists orgs from all usable accounts.
  • A 401 refreshes only the account that made the call.
  • The hosted MCP and static-token setups behave as before.
  • Tests cover concurrent tool calls for different orgs and verify that each call sends its own account's token.

Related

  • #1731: @sentry/mcp-server as a slim bundle that shares CLI auth (prerequisite)
  • #1669: shared API layer proposal; task group 11 (task 11.4, CLI capabilities injected into mcp-core) is the natural home
  • #1396: CLI multi-account mode (done)
  • #845: earlier --profile request for the stdio transport, closed as not planned; this approach needs no per-process profiles

via BYK.

--

View Session in Sentry

主要言語
TypeScript
スター
949
フォーク
171
平均マージ
1日 2時間
マージ済み PR(30日)
261

環境構築

このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

getsentry/toolkit のほかの issue

getsentry/toolkit の issue をすべて見る

似ている issue

TypeScript の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。