fix(mcp): advertise upload origin in app CSP connectDomains - #453
Merged
Conversation
The Upload to IPFS / Upload to Vault MCP apps do a cross-origin Uppy XHR PUT from the host sandbox (e.g. Claude's assets.claude.ai iframe) to the minted presigned /upload/<token> or /vault-upload/<token> endpoint. The server's own CORS grant was correct, but the app resources advertised no csp.connectDomains, so a host derives a sandbox CSP that blocks the PUT (the reported upload CSP error). Advertise the live upload origin in each upload app resource's read-level _meta.ui.csp.connectDomains. The origin (tunnel/base URL or loopback address) is only known after the server/transport is up — after app registration — so expose an AppResource.ConnectDomainsFunc resolved per resources/read, plus LoopbackServer.Origin() and Upload/VaultHTTPUpload.ConnectOrigins() to compute it. Tests assert both upload app resources advertise the coordinator's loopback origin and, after SetBaseURL, the tunnel origin.
Kody Review CompleteGreat news! 🎉 Keep up the excellent work! 🚀 Kody Guide: Usage and ConfigurationInteracting with Kody
Current Kody ConfigurationReview OptionsThe following review options are enabled or disabled:
|
Code Coverage ReportTotal Coverage: 51.7% Generated from commit: 0078f64 |
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
Fixes the CSP error when uploading a file through the Upload to IPFS / Upload to Vault MCP apps (e.g. in Claude): the app did a cross-origin Uppy XHR PUT from the host sandbox to the minted presigned
/upload/<token>//vault-upload/<token>endpoint, but the app resources advertised noconnectDomains, so the host (Claude) derived a sandbox CSP that blocked the PUT.Diagnosis
Our Go server never set a CSP header and the app docs have no CSP meta tag — the block came from the host's sandbox CSP, which the host derives from the app resource's advertised
_meta.ui.csp.connectDomainsallowlist. Our CORS grant was already correct; the missing piece was advertising the PUT target origin to the host.Change
Advertise the live upload origin in each upload app resource's read-level
_meta.ui.csp.connectDomains:transport.LoopbackServer.Origin()— the origin the routes are served from (base/tunnel URL in HTTP mode, loopback in stdio mode), excludingtrustedOrigins(those are request sources, not destinations).transfer.Upload/transfer.VaultHTTPUploadConnectOrigins()— the origin an Uppy XHR PUT targets, ensuring the loopback listener is running so it's correct at read time.sdk.AppResource.ConnectDomainsFunc— a read-time resolver, because the origin is only known afterserveHTTPresolves the tunnel/base URL, i.e. after app registration. Resolved perresources/read(the value a host uses to render the app);resources/listkeeps the static meta fallback.apps.AppView.ConnectDomainsFuncin bothRegisterIPFSUploadAppandRegisterVaultUploadApp.Tests
internal/mcp/sdk—RegisterAppResourceread-level meta resolvesConnectDomainsFuncdynamically.internal/mcp/upload_ipfs_app_test.go/upload_vault_app_test.go— new tests assert each upload app resource advertises the coordinator's loopback origin viaresources/read, and re-reads the tunnel origin afterSetBaseURL(mirroringserveHTTP).Existing CORS tests already prove the minted endpoint answers the cross-origin preflight and reflects only trusted origins.
This pull request fixes a Content Security Policy (CSP) issue with MCP upload apps by ensuring that the upload origin is properly advertised in the app's
connectDomainsconfiguration.Problem
The IPFS and Vault upload apps perform cross-origin file uploads via Uppy's XHR PUT requests from a sandboxed host environment. These PUT requests target presigned upload endpoints on the server's origin (either the tunnel/base URL in HTTP mode or the loopback address in stdio mode). However, the host's sandbox CSP would block these cross-origin requests because the upload destination origin was not being advertised in the app's
connectDomainsconfiguration.Solution
The changes introduce dynamic resolution of the upload origin at resource read time:
New
ConnectDomainsFunccapability: Added aConnectDomainsFuncfield toAppView,AppResource, and the upload loopback server. This function dynamically resolves the server's live origin when the MCP client reads the app resource, ensuring the advertisedconnectDomainsreflects the actual upload destination.Dynamic read-time resolution: The MCP SDK's
RegisterAppResourcenow callsConnectDomainsFuncat every resource read, overriding the static CSPconnectDomainsfrom the registration-time metadata. This is necessary because the server's public origin (tunnel/base URL or loopback address) is only resolved after the app has been registered.Upload origin resolution: The
UploadandVaultHTTPUploadcoordinators expose aConnectOrigins()method that ensures the loopback listener is active and returns the current server origin (base URL in HTTP mode or loopback origin in stdio mode).Test coverage: Added regression tests for both IPFS and Vault upload apps verifying that:
_meta.ui.csp.connectDomainscorrectly advertises the loopback origin