Repository navigation
feat(sdks): MCP tools for uploads, an x-mcp-name override, and files - #757
Merged
Merged
Conversation
…p-name An operation with a multipart/form-data body is now a tool. Each top-level binary field takes a data: URI string (RFC 2397) with format: uri. The handler decodes it into a File with the type and name from the URI and checks its size against the operation's x-mcp-max-file-bytes override, which the plugin requires. A malformed URI, a URL, or a file over the limit returns an isError result and sends nothing; the tool never downloads a URL. Other non-JSON bodies, such as form-encoded ones, still get no tool. An x-mcp-name override replaces the generated tool name, for names over 64 characters. Operation IDs, and so the SDK function names, stay as they are. The plugin still throws on an invalid name, and now suggests x-mcp-name when the generated one is too long. The support file copied into catalogs, rule-promotions and cart-checkout-order gains the two upload helpers; their tools are unchanged.
The files package ships a ./mcp export with 4 tools, generated from a new files-standalone@v1 bundle that carries a written description for each. files_create_a_file uploads a data: URI of at most 8,388,608 bytes, the API's default 8MB limit. page[limit] and page[offset] on getAllFiles were typed string in the spec while the zod schemas parse them as numbers, so the generated handler did not type-check. A spec correction types them as integers, which changes those two fields in types.gen.ts from string to number. sdk.gen.ts and zod.gen.ts are unchanged.
|
The latest updates on your projects. Learn more about Vercel for GitHub. 6 Skipped Deployments
|
🦋 Changeset detectedLatest commit: 65f947c The changes in this PR will be included in the next version bump. This PR includes changesets to release 4 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
This was referenced Oct 16, 2026
Merged
Each data: URI file field now carries x-mcp-file with its maxSize, the file-input marker in the MCP File Uploads Working Group's drafts (SEP-2356, SEP-2631), so a host that recognises it can offer a file picker. The limit is the operation's x-mcp-max-file-bytes.
The latest SEP-2356 draft drops the name= parameter from data: URIs and asks servers that need the file name to declare a separate string argument. Each upload field now has an optional <field>_name next to it, such as file_name. The handler names the File from it, else from a name= parameter (still accepted for the earlier draft), else after the field, and does not send it to the API. The plugin throws if the body already has a <field>_name.
A File uploads section in the SDKs README names the sources: the rollout notes on #735, SEP-2356 and SEP-2631 from the MCP File Uploads Working Group (both closed unmerged, work continuing in experimental-ext-file-uploads), RFC 2397 and SEP-1303. It compares what the latest drafts ask for with what the tool does, lists where it departs, and says how it was verified, including the live upload against a store. The files README links to it.
dataUriFields returned the body schema's own type, so <field>_name existed at runtime but not in TypeScript: a direct handler call with file_name was an excess-property error, and a wrapping handler could not read it. The schema type now includes each <field>_name as an optional string, and the decoded body type drops it before the SDK function is called. A files type test covers both.
This was referenced Oct 19, 2026
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.
Closes #750. Part of #735.
Summary
The plugin now generates tools for uploads and takes an
x-mcp-nameoverride. The files package ships./mcpwith 4 tools.data:URI in aformat: uristring, markedx-mcp-filewithmaxSize; the filename in a separate string argument, not aname=parameter; any other scheme rejected and never fetched; and failures returned asisErrorresults naming the field. The<field>_nameargument wins;name=is still accepted for the earlier draft. No in-house prior art existed:epcc-api-mcphandles no uploads, and the TypeScript SDK prototype adds only types.x-mcp-max-file-bytesis required on any operation that uploads a file. The plugin throws without it, and the field's description states the limit. The rollout notes didn't say where the limit comes from, and the APIs document different ones (files 8MB, pim 50MB, inventories and subscriptions none), so each operation states its own.createAFilehas a limit of 8,388,608 bytes, from the spec's "8MB by default". A store with a raised limit still gets 8 MiB from this tool.files-standalone@v1bundle and generates from it, so its overrides live in the spec. The bundle alone leftsdk.gen.ts,types.gen.tsandzod.gen.tsbyte-identical.One deliberate change to
types.gen.tsThe fix also belongs in the service: files.svc !687 types the two parameters as integers in its spec. The service parses them with
strconv.Atoi. Files is the only Elastic Path spec that declares them asstringwithformat: int64. Once that change reaches the published spec, the correction file here can go.The spec types
page[limit]andpage[offset]ongetAllFilesasstringwithformat: int64. The zod schemas parse them as numbers, so the generated handler didn't type-check (rollout note 2).files_service_corrections.yamltypes them as integers, which changes 4 lines oftypes.gen.ts:sdk.gen.tsandzod.gen.tsare unchanged, and the request on the wire is the same. A TypeScript caller passing"10"now gets a type error, so the changeset says so. Confirmed in review: keep the correction here and fix the service spec.Files package choices
files_get_all_filesis 37.6% andfiles_create_a_fileis 26.5%, both over a quarter. With 4 tools that's expected and isn't the shared-schema problem:get_all_filesis large because of its filter description,create_a_filebecause of the upload field.Evidence
mcp-plugin.test.tswith the new fixture failed:getWidgetHistoryEntryRevisionAttachmentByIdentifiers gives the invalid tool name …, and the multipart operation had no tool.After: 45 plugin tests pass. They cover a multipart part carrying the decoded bytes, name and type; percent-encoded data; a size at and over the limit; a malformed URI, invalid base64 and a URL, each sending nothing; an optional body; a missing or invalid
x-mcp-max-file-bytes; anx-mcp-namethat's valid, too long or has a space; thex-mcp-filemarker; and the<field>_nameargument, including its precedence overname=and a body that already has such a field.McpServer. Through a realClient,files_get_all_fileswithpage[limit]: 2returned 2 files, andfiles_get_a_filereturned the first one.Client):isErrorresult, and no request was sent.files_create_a_fileuploaded a 70-byte PNG. The API kept the name, typeimage/pngand size 70.files_get_a_fileread it back, and the file link returned the same bytes.files_delete_a_fileremoved it, and a read afterwards returned 404.name=parameter, then with the newfile_namefield. Both times the API stored the name sent.Merge Danger
Door: two-way
Blast Radius: small
New
./mcpsubpath and an optional peer, so the main entry is untouched apart from thegetAllFilespaging types above. The plugin change affects only packages that adopt it; the three that already have are regenerated byte-identically apart from the support copy.