Uh oh!
There was an error while loading. Please reload this page.
feat: add ui/download-file method for host-mediated file downloads - #475
Conversation
Add a new ui/download-file JSON-RPC request that allows MCP App views to request file downloads through the host. Since MCP Apps run in sandboxed iframes where direct downloads are blocked (allow-downloads not set), this provides a host-mediated mechanism for file exports. Spec changes (draft): - Add ui/download-file request to Requests (View → Host) section - Add downloadFile capability to HostCapabilities - Document host behavior requirements (confirmation dialog, filename sanitization, base64 decoding, size limits) SDK changes: - Add McpUiDownloadFileRequest/Result interfaces to spec.types.ts - Add downloadFile() method to App class - Add ondownloadfile setter to AppBridge class - Add DOWNLOAD_FILE_METHOD constant - Generate Zod schemas Example: - Add download demo to integration-server (exports JSON with server time) - Capability check: only shows download button when host advertises downloadFile capability Based on developer feedback requesting file export capabilities for visualization tools, document editors, and data analysis apps.
antonpk1
commented
Feb 19, 2026
ochafik
commented
Feb 20, 2026
cc/ @connor4312@nickcoai for input too :-) |
This is kind of neat
|
Replace custom {filename, content, mimeType, encoding} params with
standard MCP resource types: EmbeddedResource for inline content and
ResourceLink for host-resolved references.
New params shape:
params: { contents: (EmbeddedResource | ResourceLink)[] }
This reuses existing MCP primitives instead of inventing new ones,
and enables hosts to show resource 'bubbles' or resolve ResourceLink
URIs via resources/read on the MCP server.antonpk1
commented
Feb 20, 2026
thank you @connor4312 |
| * For `EmbeddedResource` with `blob`, host MUST decode the content from base64 before creating the file. | ||
| * For `ResourceLink`, host MAY fetch the resource on behalf of the app or open the URI directly. | ||
| * Host MAY reject the download based on security policy, file size limits, or user preferences. | ||
| * Host SHOULD sanitize filenames to prevent path traversal. |
There was a problem hiding this comment.
I think this is no longer relevant in the resources world
There was a problem hiding this comment.
Good call — removed the two bullets that were just restating standard EmbeddedResource/ResourceLink behavior. Kept the download-specific ones (confirmation dialog, filename derivation, security policy, path sanitization). Updated in f07bdfb.
Remove bullets that restate standard EmbeddedResource/ResourceLink behavior already defined in the MCP resource spec. Keep download-specific host behavior (confirmation dialog, filename derivation, security policy, path sanitization).
There was a problem hiding this comment.
can you add a test to app-bridge.test.ts that exercices the two ends?
Uh oh!
There was an error while loading. Please reload this page.
| The `contents` array uses standard MCP resource types (`EmbeddedResource` and `ResourceLink`), avoiding custom content formats. For `EmbeddedResource`, content is inline via `text` (UTF-8) or `blob` (base64). For `ResourceLink`, the host can retrieve the content directly from the URI. | ||
| Host behavior: |
There was a problem hiding this comment.
@antonpk1 should we provide some guidance on payload size? postMessage can be fairly constrained (depending on both browser and device).
idosal
commented
Feb 24, 2026
* chore: bump ext-apps to 1.1.2 Changes since 1.1.1: - feat: add ui/download-file method for host-mediated file downloads (#475) - pdf-server: robust path validation + folder/file root support (#497) - ci: auto-fix prettier formatting in pre-commit hook and CI (#498) * fix: sync local SDK build into node_modules for examples npm workspaces hoists example dependencies to the root node_modules, but installs the published registry copy of @modelcontextprotocol/ext-apps instead of linking to the local source. This causes type-check failures when examples use features not yet published to npm. Add scripts/link-self.mjs which copies the freshly-built dist/ and package.json into the hoisted node_modules copy after each SDK build, ensuring examples always type-check against the latest local types. See: npm/feedback#774 * Revert "fix: sync local SDK build into node_modules for examples" This reverts commit e3387e8.
What
Add a new
ui/download-fileJSON-RPC request that allows MCP App views to request file downloads through the host.Why
MCP Apps run in sandboxed iframes where direct file downloads are blocked (
allow-downloadsis not set). Based on developer feedback, many apps need file export capabilities — visualization tools (SVG/PNG export), document editors, data analysis tools, and any app producing downloadable artifacts.ui/download-fileprovides a host-mediated mechanism for this, consistent with the existingui/open-linkpattern.Design: MCP Resource Types
Following feedback to reuse existing MCP primitives, the params use standard MCP resource types instead of custom fields:
EmbeddedResource— Inline content viaresource.text(UTF-8) orresource.blob(base64). The host creates a blob and triggers the download directly.ResourceLink— A reference URI the host resolves viaresources/readon the MCP server. This avoids passing large content through postMessage and lets hosts show resource "bubbles" or use native download mechanisms.This approach:
EmbeddedResource,ResourceLink) instead of inventing new content formatsResourceLinkfor cases where the host can fetch directly, avoiding unnecessary data transfer through the iframeChanges
Spec (
specification/draft/apps.mdx)ui/download-filerequest to "Requests (View → Host)" section with examples for bothEmbeddedResourceandResourceLinkdownloadFilecapability toHostCapabilitiesresources/readSDK
spec.types.ts:McpUiDownloadFileRequestuses(EmbeddedResource | ResourceLink)[],McpUiDownloadFileResult,downloadFileinMcpUiHostCapabilities,DOWNLOAD_FILE_METHODconstantapp.ts:App.downloadFile()method with JSDoc examples for embedded text, embedded blob, and resource linkapp-bridge.ts:AppBridge.ondownloadfilesetter with JSDoc example showing both resource typestypes.ts: Re-exports,AppRequest/AppResultunion additionsgenerate-schemas.ts: AddedEmbeddedResourceSchema,ResourceLinkSchemato external type listgenerated/: Auto-generated Zod schemas using SDK schema importsExample
integration-server: Two side-by-side demo buttons:EmbeddedResource(text content)ResourceLink(host resolves viaresources/read)integration-server/server.ts: Registers a sample downloadable resource atresource:///sample-report.txtProtocol
App SDK Usage
Security
ui/open-link)allow-downloadson iframe — download is always host-mediatedResourceLink, host resolves via MCPresources/read(no direct HTTP fetch from iframe)