feat(mcp): bump @contentrain/mcp to 1.10.0 — session fingerprint + media tool classes#145
Merged
Conversation
…dia tool classes Write-path safety: git/transaction, git/branch-lifecycle, core/ops and providers/github chunk graphs are byte-identical between 1.8.1 and 1.10.0 (hash-suffix noise only) — the bump does not touch the content write path. A real staging save after merge stays on the checklist. - deps: @contentrain/mcp 1.8.1→1.10.0, @contentrain/types 0.7.0→0.8.0, @contentrain/query ^6.1.1→^6.2.1 - loopback server: pass 1.10.0's sessionFingerprint, derived from the SAME x-cr-* tenant headers resolveProvider reads (helper in mcp-cloud-runtime.ts) — a stolen Mcp-Session-Id replayed with another project's headers now 404s and the client re-initializes cleanly - tool classes: MEDIA_* sets derived from the new TOOL_REQUIREMENTS availability contract; media tools excluded from the content write set (they pass through the media facet, never git — no brain invalidation, no auto-merge reconcile) and from content:read - scopes: media:read → list/get, media:write → ingest/update/delete; scopeForTool routes media step-up challenges. ADVERTISED_SCOPES unchanged — the loopback provider has no media facet yet, so the MCP server hides the tools; flip advertising when the facet ships - 1.10.0 closes the PR4 audit gap: openWorldHint present on all 24 tools (ingest is the only openWorldHint:true, delete is destructive) - tests: media class partition + scope derivations, tenant-fingerprint unit suite; managed e2e smoke green on the new package
ABB65
added a commit
that referenced
this pull request
Jul 13, 2026
Implements RepoProvider.media on the loopback provider so
contentrain_media_list/get/ingest/update/delete work on both MCP Cloud
surfaces, with policy at the proxy and mechanism at the loopback.
- server/utils/mcp-media-facet.ts: the contract MediaProvider as a
deterministic passthrough over Studio's ee media stack — cursor
pagination, tenant isolation (get→null / update+delete→404 on foreign
assets), and the ingest quota dance (fetchRemoteMedia SSRF/MIME/size →
reserveStorageIfAllowed → upload source:'agent' → reconcile/release).
Returns null when useMediaProvider() is null (CE / no R2) so the
tools stay hidden.
- proxy: STUDIO_HEADERS + x-cr-{project-id,workspace-id,media-owner,plan},
injected ONLY when mediaEligible (media stack + plan media.upload +
cdn_enabled + owner). Media tools are excluded from the empty-allowlist
"unrestricted" rule — a key needs media_enabled or an explicit listing,
so existing keys never silently gain URL ingest / destructive delete.
- loopback: resolveProvider builds the facet from the four proxy headers;
git.ts carries RepoProvider.media; the tenant fingerprint gains the
project id so an eligibility flip re-inits the session within a request.
- key surface: mcp_cloud_keys.media_enabled (migration 018, default false)
+ create route + panel "Allow media tools" toggle + Media badge.
- OAuth: advertisedScopes() adds media:read/media:write only where the
media stack is configured; the 4 well-known routes inject availability;
scope→tool mapping + step-up already routed media (from #145).
- deps already at 1.10.0 (#145). openWorldHint present on all 24 tools.
- tests: facet unit suite (18), fingerprint + scope/metadata units,
proxy eligibility matrix + key media gate + oauth media path, contract
media_enabled column case. lint/typecheck clean; unit+integration+nuxt
1048, contract 105, managed e2e 12/12 (media absent without R2).
Co-authored-by: Contentrain <[email protected]>
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.
What
Studio integration for
@contentrain/mcp1.10.0 (+@contentrain/types0.8.0,@contentrain/query^6.2.1) — the two items upstream flagged for Studio, plus the media groundwork.Write-path safety (bump rule)
Per the post-1.8.0 lesson, the git internals were diffed before trusting the mocked suite:
git/transaction,git/branch-lifecycle,core/opsandproviders/githubchunk graphs are byte-identical between 1.8.1 and 1.10.0 (only hash-suffix noise). The bump does not touch the content write path. A real staging save after merge remains the final check.Session fingerprint (tenant binding)
The loopback server now passes 1.10.0's
sessionFingerprint, derived from the samex-cr-*headersresolveProviderreads (mcpTenantFingerprintinmcp-cloud-runtime.ts, unit-tested). Sessions are bound to the tenant identity they were created with — replaying anMcp-Session-Idwith another project's headers 404s and the client re-initializes against its own provider. Closes cross-tenant session-id replay on the shared loopback.Media tools (5 new; 24 total)
MEDIA_*tool classes derive from the newTOOL_REQUIREMENTSavailability contract (media: truefacet requirement) — upstream's suggested source of truth.media:read→media_list/media_get,media:write→ingest/update/delete; step-up challenges route media tools to the right scope.ADVERTISED_SCOPESunchanged — Studio's loopback provider doesn't implement the media facet yet, so the MCP server hides the tools fromtools/listentirely. Scope enforcement is already correct for the day the facet ships; advertising flips then (remaining Studio work per upstream: loopback media facet implementation + MCP key scope model).Bonus
1.10.0 closes PR4's upstream audit gap:
openWorldHintis now present on all 24 tools (media_ingestis the onlyopenWorldHint: true;media_deleteisdestructiveHint: true) — the OpenAI annotation requirement is fully satisfied.Tests
Media class partition pins (disjoint metadata/read/write/media/lifecycle), media scope derivations + no-leak into content scopes, tenant-fingerprint unit suite (stability, per-component sensitivity, missing-header behavior).
pnpm lint✓ ·pnpm typecheck✓ · unit+integration+nuxt 1004 ✓ · managed e2e smoke 12/12 on 1.10.0 ✓