Repository navigation
ref(mcp): Send SentryApiService requests through a shared request core - #1737
Merged
Merged
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
createApiClientCore sends a request through the host's transport with the host's headers, turns network failures into readable errors (ConfigurationError for an unreachable host), maps error responses to the status's ApiError through readErrorResponse, and parses JSON bodies. The transport, headers, and logger are injected, so it stays browser-portable. It is the MCP's request path, moved as is; the next commit switches SentryApiService onto it.
request and requestJSON keep their signatures and delegate to createApiClientCore, so no endpoint method changes. SentryApiService supplies its headers (User-Agent, Authorization, MCP attribution), the shared transport, and logWarn under the api.client scope. Its copies of the network error messages and the error-response mapping are deleted. The one difference: the error-response warnings now log the host the request went to, rather than the service's default host, when a call overrides the host.
BYK
approved these changes
Oct 29, 2026
sentry-junior
Bot
force-pushed
the
feat/shared-api-client-core
branch
from
October 29, 2026 21:27
31cc0f4 to
fc6aa08
Compare
BYK
pushed a commit
that referenced
this pull request
Oct 29, 2026
…1741) Task 8.4, part 2 of the shared API client stack ([#1669](#1669)). It used to be stacked on #1737, which has merged, so it now targets `main`. This adds the first shared endpoint wrappers to `toolkit-core`'s `api-client/`, and the MCP's `SentryApiService` now calls them. The code moves as is, so it can go to `@sentry/api` later without changes. **Changes** - `endpoints/organizations` adds `getAuthenticatedUser`, `listOrganizations` and `getOrganization`. Each one takes an `ApiTarget` (the request core plus an origin) and a Standard Schema from the host, and returns that schema's output. `toolkit-core` doesn't depend on Zod or valibot when the code runs. - The request core gains `sdkClient`, which sends one GET to an expected path and rejects any other path or method, and `listPage`, which walks a list endpoint up to a limit and validates each page. These are the MCP's `sdkClient` and `sdkListPage`, moved as is. The only change is that validation now uses Standard Schema. - `SentryApiService` still decides which host to call: the control host for the current user and for the organization list on public SaaS. Its own `sdkClient` and `sdkListPage` copies are deleted, and the teams and projects lists use the shared ones. - `toolkit-core` now depends on `@sentry/api`. To keep a single TypeScript copy, the pnpm catalog's TypeScript moves from `^5.8.3` to `^5.9.3`, and `toolkit-core` and the CLI use `catalog:` instead of pinning their own version. Every workspace package now resolves TypeScript 5.9.3, and 5.8.3 drops out of the lockfile. The cache policy changes one type to match TypeScript 5.9's DOM `BodyInit`. Nothing changes at runtime. **One change in behaviour:** if a response fails its schema in these calls, the error is now the shared `ApiResponseValidationError` instead of a `ZodError`. Both still reach the tool error handler as unexpected errors. <!-- junior-session-footer:start --> <!-- junior-conversation-id:local%3Aweb%3A0ab4fc2bd5a2e23f2c25efcf --> -- [View Junior Session in Sentry](https://sentry.sentry.io/explore/conversations/local%3Aweb%3A0ab4fc2bd5a2e23f2c25efcf/?project=4510944073809921) <!-- junior-session-footer:end --> --------- Co-authored-by: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com>
sentry-junior Bot
added a commit
that referenced
this pull request
Oct 30, 2026
main moved response parsing into toolkit-core's readJsonResponse (#1732, #1737), which still throws a plain Error for an empty or non-JSON body. validateEvents is the only caller that lets a 400 reach that parser, so classify its non-JSON 400s there with createApiError. Successful non-JSON responses stay reportable.
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds the shared request core in
toolkit-core/src/api-client/core.tsand switchesSentryApiServiceonto it. This is the first slice of #1669 task 8.4. #1736 has merged, so this PR now targetsmain.8.4 as written covers the request core and every domain's endpoint wrappers.
SentryApiServiceis about 6,000 lines with about 100 endpoint methods, so I'm splitting 8.4 into the core first, then domain PRs on top. This PR is the core.What changes
createApiClientCore(toolkit-core, browser-portable). The host injects its transport, per-request headers, and logger.request(origin, path, init, { allowStatuses }):<origin>/api/0<path>withContent-Type: application/jsonplus the host's headers (they replace any the caller passes, as before);Unable to connect to <url> - …, as aConfigurationErrorfor ENOTFOUND, EAI_AGAIN, ECONNREFUSED, ETIMEDOUT, and connect timeouts;ApiErrorthroughreadErrorResponse, with the same three warnings as before.requestJsonalso parses the body withreadJsonResponse.SentryApiService.requestandrequestJSONkeep their signatures and delegate to the core, so no endpoint method changes.SentryApiServicesuppliesUser-Agent,Authorization(still aConfigurationErrorfor a malformed token, before anything is sent), theX-Sentry-MCP-*attribution headers, the existing shared transport, andlogWarnunder theapi.clientscope. Its copies of the network error table and the error-response mapping are deleted.Still in mcp-core:
sdkClient, which now goes through the core viarequest, andsdkListPage.sdkClientmeans toolkit-core depends on@sentry/api. Today that resolves a second@sentry/apicopy, because toolkit-core pins TypeScript through the^5.8.3catalog while mcp-core resolves 5.9.3. The domain-wrapper PRs will fix that skew first.sdkListPagestays because its rules differ from the sharedpaginate: an exactper_page, and an error on extra rows or a repeated cursor. Merging them would change behavior, so that waits for the merge step.Docs: the toolkit-core README's API client section and
api-patterns.mddescribe the core.Behavior changes
hostfield. The three error-response warnings (HTML page, unparseable JSON, no stringdetail) now log the host the request actually went to. Before, they logged the service's default host even when a call overrode it, e.g. a regional host. Messages, error classes,detail,responseBody, andretryAfterMsdon't change.This PR does not touch
packages/mcp-server,packages/cli/src/lib/mcp.ts, or the evals stdio entry. The@sentry/mcp-serverretirement PR owns those.Commits
Both commits are hand-written. No codemod.
5710b8e8dAddcreateApiClientCorewith unit testsfc6aa0875SwitchSentryApiServiceonto it, plus docsVerification
pnpm run tsc(including toolkit-core's browser typecheck),pnpm run lint, andnode scripts/check-doc-links.mjspass.core.test.tscases covering headers, header errors, detail mapping, allowed statuses, rate-limit wait, HTML and unreadable bodies, network errors, abort, andrequestJson.client.test.tsMSW suites cover the delegated path unchanged.--
View Junior Session in Sentry