Repository navigation
Let MCP clients upload files with a short-lived upload grant - #93
Open
josipmrsic wants to merge 2 commits into
Open
josipmrsic wants to merge 2 commits into
josipmrsic wants to merge 2 commits into
Conversation
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.
After #86, Claude Code signed in through Entra could connect to
/mcp, list, and read, but not publish. This PR fixes the publish step for every MCP client, not only Entra ones.What stood in the way
artifact_create_uploadtells the agent to PUT each file "using the same bearer credential" (credential: "reuse_the_mcp_bearer_credential"). That can't work in two ways:/api/takes API keys only. Decision 0028 keeps OAuth off/api/on purpose, so even the client's own token is refused on the upload URL.So publishing through MCP only worked when the model happened to know an API key. No test covered an OAuth MCP client uploading; every upload test PUT with an API key.
What changes
artifact_create_uploadnow returns an upload grant once per upload:The agent sends it as
Authorization: Beareron that upload's file PUTs, then commits through MCP as before.PUTof a file of its own upload, while openUPLOAD_CLOSED/UPLOAD_EXPIRED401 AUTHENTICATION_REQUIREDartifact_create_upload) and again at commit (artifact_commit_upload, on the live MCP credential). The grant only lets the declared bytes in, and every file is already bound to its size and SHA-256.grant_digestcolumn onstaged_uploads. No new server secret./api/accepts anas_upg_bearer only forPUTon the file route; anywhere else it gets401 AUTHENTICATION_REQUIRED, so no principal-based handler ever sees one.Unchanged: API keys (also on the file PUT), browser sessions,
POST /api/v1/uploads(issues no grant), the commit step, and 0028's rule that/api/takes no OAuth tokens.Decision 0031 has the reasoning and the rejected alternatives: accept the MCP OAuth token on the upload route (breaks the audience binding 0028 relies on), OAuth on all of
/api/(excluded by 0028, and the agent still wouldn't hold the token), and a stateless HMAC grant (needs a new secret per deployment).Storage and migrations
0012_staged_upload_grantEach adds one nullable column with no backfill. Uploads still open during an upgrade have no grant; they keep working with API keys and expire within the hour. #88 and #92 claim the same numbers, so whichever lands later renumbers; happy to rebase.
Spec and tests
implementing, with its proof gap); PUB-001-F gains the grant exception; MCP baseline and skill wording. The decision number assumes Support Microsoft Entra ID for MCP OAuth #86 (0029) and Add artifact owners and an opt-in restricted access setting #88 (0030).tests/conformance/pub-014-upload-grant.test.tsdrives the service and a local server whose MCP credential/api/refuses, like an Entra token. It uploads two files in parallel with the grant and commits through MCP, and refuses the grant on another upload, another route, another method, a changed path, the wrong project, an altered token, after commit, and after expiry. It also checks that the grant never reaches the logs.mcp-modern-http.test.tsnow uploads with the grant and keeps one API-key PUT.Verification
pnpm check, the Postgres suite (19/19), and the browser suite pass locally.