Repository navigation
feat(mcp-cloudflare): Cache Sentry API responses in memory behind MCP_RESPONSE_CACHE - #1833
Open
sentry-junior[bot] wants to merge 2 commits into
Open
sentry-junior[bot] wants to merge 2 commits into
sentry-junior[bot] wants to merge 2 commits into
Conversation
…_RESPONSE_CACHE Wire the shared byte-budgeted memory store into the hosted MCP. The cache is off unless MCP_RESPONSE_CACHE is `memory` or `tiered` (memory only until the R2 tier lands). Entries are keyed by a SHA-256 of the MCP grant's user and grant IDs from the wrapper token, so one grant never reads another's responses; requests without a grant, such as Sentry-Bearer direct tokens, are not cached. SentryApiService takes an optional responseCache and sends through a caching transport for its token. apiServiceFromContext drops it when a credential router can swap tokens. Writes run in waitUntil. Adds hit/miss/stale lookup, write (with encoding), and eviction metrics, memory gauges, and a one-time log when an isolate reaches its budget. Co-Authored-By: BYK <126780+BYK@users.noreply.github.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 2d512db. Configure here.
Cancel the transport's body copy whenever the cache does not read it, including JSON responses the policy refuses to store. Let getResponseCache infer its return type: CI lints before building mcp-core, so the ResponseCache | undefined union tripped no-redundant-type-constituents. Co-Authored-By: BYK <126780+BYK@users.noreply.github.com>
This was referenced Nov 3, 2026
This branch was previously 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.

Task 7.1 of the #1669 plan, plus the 7.5 metrics. It wires the shared memory store (#1696) and cache policy (#1688) into the hosted MCP behind
MCP_RESPONSE_CACHE.Off by default. Only
memoryortieredturns it on. An unset,off, or unknown value means no caching. This PR changes no wrangler config, so every deployed environment stays uncached.tieredbehaves likememoryuntil the R2 tier lands in the stacked follow-up.Identity isolation. Each cache key's identity is a SHA-256 of
["mcp-grant", userId, grantId]. Both values come from the validated wrapper token (userId:grantId:secret), so a grant never reads another grant's entries, even for the same user and URL. The identity survives a wrapper-token refresh. Requests without a grant ID are not cached, and that includes Sentry-Bearer direct tokens. In mcp-core,SentryApiServicetakes an optionalresponseCacheand sends through a caching transport bound to its token.apiServiceFromContextdrops the cache whenever acredentialRouteris set, because routed calls run with other tokens.Storage. There is one 24 MiB memory store per isolate. Writes run in
ctx.waitUntil(). Non-JSON bodies, such as attachments, are skipped before they are read. A write invalidates only the writing grant's entries.Isolation tests:
SentryApiServiceinstances over one shared store, with an upstream that answers perAuthorization. The same URL never returns the other identity's body, and a write by A leaves B's entry in place./mcptool calls. The same grant hits the cache. Another grant for the same user, another user, a malformed wrapper token, and a Sentry-Bearer token all go to the API. With the flag unset, nothing is cached.Metrics (7.5).
app.response_cache.lookup(hit/miss/stale),app.response_cache.write(with the bodyencoding),app.response_cache.eviction, and two gauges:memory.bytesandmemory.entries. The first budget eviction in an isolate also writes a one-time info log. They are documented indocs/operations/monitoring.md, and the cache is described indocs/cloudflare/architecture.md.toolkit-core's memory store gains anonEvictcallback for this.Pending, needs a deployed Worker (CI deploys only from
main, so this PR gets no preview):5.20261019.1-beta) hasnode:zlibzstd. On a deployed Worker withMCP_RESPONSE_CACHE=memory,app.response_cache.writegrouped byapp.response_cache.encodingshould showzstd. If it only showsbr, brotli stays the hosted codec, and the doc needs updating to say so.Not in scope: the
freshinput (6.3). When it lands, itsfresh()callback goes oncreateCachingTransportinmcp-core/src/api-client/client.ts.via @BYK.
--
View Session [Sentry]