feat(mcp-server): enable action file fields via an upload side-channel - #1814
Open
stefanoamorelli wants to merge 1 commit into
Open
feat(mcp-server): enable action file fields via an upload side-channel#1814stefanoamorelli wants to merge 1 commit into
stefanoamorelli wants to merge 1 commit into
Conversation
The agent expects action file fields as base64 data URIs, which cannot pass through an MCP client. The payload would transit the model's context window and exceed most clients' body limits, so actions with File fields could not run over MCP at all. Add an opt-in fileUploads option backed by a pluggable UploadStorage interface. POST /files (bearer-protected) returns a pre-authorized upload URL plus a signed handle bound to the requesting user. executeAction swaps "$uploadedFile:<handle>" values for the data URI before calling the agent, so the model only ever exchanges the small handle and the bytes bypass both the server and the model on upload. The handle is a JWT signed with authSecret, so the server stays stateless and horizontally scalable. Redemption enforces the size cap (a pre-authorized upload URL cannot always cap the object size), re-verifies an optional sha256 pin against the downloaded bytes so substituted content cannot be redeemed, and runs under a per-process concurrency bound so worst-case memory stays at maxBytes times the slot count. getActionForm leaves handles unresolved on purpose because it echoes values back into the model's context. The route matcher only claims /files when the feature is enabled, so a host app's own /files keeps working otherwise. Signed-off-by: Stefano Amorelli <stefano@amorelli.tech>
Member
|
Hello again @stefanoamorelli :), |
Member
|
Hello, thank you very much for your contribution. |
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.
Action forms with File fields cannot run over MCP today, because MCP itself has no file upload mechanism yet. Tool arguments are JSON, so a file has to travel as a base64 data URI through the model's context window, and it exceeds most clients' payload limits on the way. The spec is heading toward the same pattern this PR uses. SEP-13061 explored binary elicitation, SEP-23562 specified declarative file inputs as RFC 2397 data URIs, and the open SEP-26313 adds out-of-band upload negotiation (
files/authorizeUpload). Its motivation states that implementations today rely on ad hoc argument conventions, hosted-storage handles, inline base64, or harness-specific rewriting.I add an opt-in
fileUploadsoption backed by a pluggableUploadStorageinterface, with no new dependency in the package.POST /filesreturns a pre-authorized upload URL plus a signed handle bound to the requesting user, andexecuteActionswaps$uploadedFile:handles for thedata:<mediatype>;name=<filename>;base64,...URI the agent already expects, the same shape SEP-2356 specifies. The model only ever exchanges the small handle. Redemption enforces a size cap, an optional sha256 pin, and a per-process download concurrency bound. Once SEP-2631 lands, this side-channel can map onto the standardizedfiles/authorizeUploadflow without changing the storage contract. The README documents the flow with a sequence diagram and an S3 example.Footnotes
SEP-1306, binary mode elicitation for file uploads (superseded). https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1306 ↩
SEP-2356, file input support for tools and elicitation (closed in favor of SEP-2631). https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2356 ↩
SEP-2631, file objects and transfer (open). https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2631 ↩