Skip to content

fix(mcp): Accept 1h and minute periods; guide models to find_organizations on missing org - #1678

Merged
BYK merged 2 commits into
mainfrom
fix/mcp-org-context-recovery
Oct 27, 2026
Merged

BYK merged 2 commits into
mainfrom
fix/mcp-org-context-recovery

Conversation

@sentry-junior

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

Copy link
Copy Markdown
Contributor

Problem

Telemetry from sentry/mcp-server (spans over 7 days, extrapolated from 0.3 sampling, so user counts are lower bounds):

  • Missing organizationSlug: about 23.8K failures from 861+ users. One user sent ~17.7K of them, all search_issues with period:"1h". Without them it's ~6.1K failures across ~860 users. All of these came in on the unscoped /mcp URL. They fail in the MCP SDK's input validation before any handler runs, so the zod error message is the only place to add guidance without changing the schema.
  • period: "1h" on search_issues: about 25.6K failures from ~50 users, mostly that same user.
  • Minute periods: values like 30m, 15m and 10m on search_errors, search_logs and search_traces were never accepted. That's about 1.5K failures from ~300 users. Sentry reads m as minutes (read-only GET check: 30m returned 28 errors, against 1,269 for 24h), and the issues endpoint accepts statsPeriod=1h.

Changes

  • SEARCH_ISSUES_PERIOD_VALUES now includes 1h.
  • ParamPeriod now accepts minutes (/^\d+[mhdw]$/), and the rejection message says "(minutes)".
  • A missing or null organizationSlug now returns: Required. Call find_organizations() to list your organizations, then retry with organizationSlug set to one of their slugs. This works on SDK v1 and v2 and doesn't change the JSON schema.
  • Tool definitions are regenerated. Token overhead goes up by 13 (10,066 → 10,079).

Held back

  • Defaulting to the user's only org. This would mean making organizationSlug optional on ~50 tools, and fetching the org list plus a region lookup on every call that has no org. That's the org endpoint, cache and region-routing code that docs(openspec): Expose the CLI's commands as the MCP, on @sentry/api #1669 reworks, so it's left for that work.
  • Listing the user's orgs in the error, with a ready-to-copy retry. Same blocker: the SDK rejects the call before our handler sees it.

Checks

  • pnpm run tsc and pnpm run lint pass.
  • mcp-core: 1847 passed, 6 skipped.

Risk

A model that means months by 3m would get 3 minutes of data. Telemetry shows callers mean minutes; there are only a handful of 6m/12m. None of this fixes the stuck script.

via BYK.

--

View Junior Session [Sentry]

sentry-junior Bot and others added 2 commits October 26, 2026 23:41
`search_issues` limits `period` to an enum without `1h`, and the shared
`ParamPeriod` regex rejects minute windows such as `30m`. The MCP SDK
rejects these before the handler runs.

In `sentry/mcp-server` over the 7 days to 2026-10-26, about 26K
`search_issues` calls failed on `period: "1h"`. A single user sent about
25K of those; the other ~50 users sent about 500. Minute periods (`30m`,
`15m`, `10m`, ...) failed about 1.5K times for ~300 users on
`search_errors`, `search_logs`, and `search_traces`.

Sentry's `statsPeriod` already treats `m` as minutes: a read-only check
returned 28 errors for `30m` against 1,269 for `24h`, and the issues
endpoint accepts `statsPeriod=1h`.

Add `1h` to the `search_issues` enum and accept `m` in `ParamPeriod`.
The other `search_issues` windows stay bounded.

Co-Authored-By: Burak Yigit Kaya <126780+BYK@users.noreply.github.com>
Sessions without an organization constraint need `organizationSlug` on
most tools. When a call omits it, the MCP SDK rejects the arguments
before the handler runs and returns zod's generic message, such as
`organizationSlug: Invalid input: expected string, received undefined`.

In `sentry/mcp-server` over the 7 days to 2026-10-26, about 24K tool
calls failed this way. A single user sent about 17.7K of them. The rest
came from about 860 users, mostly on `search_issues`, `search_errors`,
and `find_projects`.

The SDK validates before the handler, so the zod issue message is the
only place to add guidance. A missing or null slug now returns
`Required. Call find_organizations() to list your organizations, then
retry with organizationSlug set to one of their slugs.` Other invalid
values keep their current messages. The JSON schema and token count do
not change.

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

vercel Bot commented Oct 27, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
Project Deployment Actions Updated
sentry-local Skipped Skipped Oct 27, 2026 3:00pm UTC

Request Review

@github-actions github-actions Bot added the risk: medium PR risk score: medium label Oct 27, 2026
@BYK
BYK merged commit bff836c into main Oct 27, 2026
36 checks passed
@BYK
BYK deleted the fix/mcp-org-context-recovery branch October 27, 2026 15:17
BYK added a commit that referenced this pull request Nov 3, 2026
…1836)

When a tool call leaves out `organizationSlug` and the login can reach
exactly one organization, the call now uses that organization. When the
login can reach several, a tool that requires the slug fails with a
retry the model can run as is, plus the other organizations. This is the
MCP version of the CLI recovery in #1634, and it finishes the part #1678
held back. The server never chooses between organizations.

## Why now
Over the last 7 days (`sentry/mcp-server` spans, extrapolated counts):
- `organizationSlug: Required` failures: about 4.3K, from search_issues,
find_projects, search_errors, search_logs, and calls through
execute_sentry_tool. `get_sentry_resource` adds about 1.9K more with
"`organizationSlug` is required when not using a URL".
- The script that sent about 89% of the earlier ~31K/week has stopped.
The rest is spread out: no user accounts for more than 2 of the 40
sampled failures.

## How it works
- **No schema or handler edits.** `getFilteredInputSchema` makes a
required `organizationSlug` optional at registration time, so the MCP
SDK no longer rejects the call before our code runs. Then
`prepareToolCallParams` runs `applyDefaultOrganization`. Both top-level
calls and `execute_sentry_tool` go through it, before
`withRoutedCredential`, so stdio account routing (#1802) gets the
defaulted slug.
- It runs only when the call has no slug after constraint injection and
no Sentry URL parameter (it reuses `getTargetOrganizationSlug`).
Org-scoped sessions never reach it.
- **One organization:** the call uses its slug. If the tool takes
`regionUrl` and the caller didn't set one, the call also gets the
organization's `regionUrl`. On self-hosted that value is empty, so
`regionUrl` stays unset.
- **Several organizations:** for a required slug, the error looks like
``Retry example: `search_issues(organizationSlug='org-a', period='1h')`
`` and lists the other organizations. Catalog tools get the
`execute_sentry_tool(name=…, arguments=…)` form, and values equal to a
schema default are left out. For an optional slug (URL-or-ID tools such
as `get_sentry_resource`), the call runs as before.
- **Listing fails** (for example, a token without `org:read`): the error
falls back to the find_organizations hint from #1678.
- **Multiple logins:** organizations from every account are merged.

## Fit with #1669
- The organization list comes from `SentryApiService.listOrganizations`,
which already uses the shared `endpoints/organizations` wrapper and
transport (#1722, #1737). No new endpoint code.
- The resolve step lives in mcp-core's constraint and param-prep layer.
The design keeps that layer in mcp-core ("an MCP tool fills them from
tool parameters and session constraints"), so 11.3 can keep it as is.
- The MCP hosts don't wire a `CacheStore` yet (7.1 is still open).
Instead, the list is memoized per context and credential for 5 minutes,
which matches the `stable` tier. When 7.1 lands, the `/organizations/`
request gets cached per identity on its own, and this memo can be
dropped. It doesn't conflict with 8.4–8.7 or 11.x.
- This doesn't complete a task in the plan. The closest is 11.3's
resolve step.

## Token cost
`measure-tokens` is unchanged at 9,014. That script reads the raw tool
schemas, and those didn't change. In the registered schemas,
`organizationSlug` is no longer in the `required` list on 8 direct
tools, which comes to 5,014 → 4,990 input-schema tokens.

## Open questions
- A `null` slug still gets the find_organizations hint. Accepting `null`
would add `anyOf` to every schema.
- When an optional-slug tool like `get_sentry_resource` is called by a
user with several organizations, it keeps its own error. It doesn't list
the organizations yet.

<!-- junior-request-attribution:start -->
via @BYK.
<!-- junior-request-attribution:end -->

<!-- junior-session-footer:start -->
<!-- junior-conversation-id:agent%3A0222050e9c46ef2289687231ff960e16 -->

--

[View
Session](https://junior-prod.sentry.dev/conversations/agent%3A0222050e9c46ef2289687231ff960e16)
[[Sentry]](https://sentry.sentry.io/explore/conversations/agent%3A0222050e9c46ef2289687231ff960e16/?project=4510944073809921)

<!-- junior-session-footer:end -->

---------

Co-authored-by: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com>
Co-authored-by: BYK <126780+BYK@users.noreply.github.com>

This branch was previously deployed

2 inactive deployments
Actions — 117ef664 Deployed Oct 27, 2026 by sentry-junior[bot] via eval #1377
Preview — 117ef664 Deployed Oct 26, 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.

1 participant