Skip to content

fix(mcp): advertise upload origin in app CSP connectDomains - #453

Merged
pcfreak30 merged 1 commit into
developfrom
fix/mcp-apps-connect-domains-csp
Aug 22, 2026
Merged

fix(mcp): advertise upload origin in app CSP connectDomains#453
pcfreak30 merged 1 commit into
developfrom
fix/mcp-apps-connect-domains-csp

Conversation

@pcfreak30

@pcfreak30 pcfreak30 commented Aug 22, 2026

Copy link
Copy Markdown
Member

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 no connectDomains, 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.connectDomains allowlist. 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), excluding trustedOrigins (those are request sources, not destinations).
  • transfer.Upload / transfer.VaultHTTPUpload ConnectOrigins() — 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 after serveHTTP resolves the tunnel/base URL, i.e. after app registration. Resolved per resources/read (the value a host uses to render the app); resources/list keeps the static meta fallback.
  • Wired via apps.AppView.ConnectDomainsFunc in both RegisterIPFSUploadApp and RegisterVaultUploadApp.

Tests

  • internal/mcp/sdkRegisterAppResource read-level meta resolves ConnectDomainsFunc dynamically.
  • 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 via resources/read, and re-reads the tunnel origin after SetBaseURL (mirroring serveHTTP).

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 connectDomains configuration.

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 connectDomains configuration.

Solution

The changes introduce dynamic resolution of the upload origin at resource read time:

  1. New ConnectDomainsFunc capability: Added a ConnectDomainsFunc field to AppView, 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 advertised connectDomains reflects the actual upload destination.

  2. Dynamic read-time resolution: The MCP SDK's RegisterAppResource now calls ConnectDomainsFunc at every resource read, overriding the static CSP connectDomains from 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.

  3. Upload origin resolution: The Upload and VaultHTTPUpload coordinators expose a ConnectOrigins() 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).

  4. Test coverage: Added regression tests for both IPFS and Vault upload apps verifying that:

    • The read-level _meta.ui.csp.connectDomains correctly advertises the loopback origin
    • The advertised origin updates dynamically when the coordinator's base URL is set (simulating HTTP/tunnel mode)

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-ai

kody-ai Bot commented Aug 22, 2026

Copy link
Copy Markdown

Kody Review Complete

Great news! 🎉
No issues were found that match your current review configurations.

Keep up the excellent work! 🚀

Kody Guide: Usage and Configuration
Interacting with Kody
  • Request a Review: Ask Kody to review your PR manually by adding a comment with the @kody start-review command at the root of your PR.

  • Validate Business Logic: Ask Kody to validate your code against business rules by adding a comment with the @kody -v business-logic command.

  • Provide Feedback: Help Kody learn and improve by reacting to its comments with a 👍 for helpful suggestions or a 👎 if improvements are needed.

Current Kody Configuration
Review Options

The following review options are enabled or disabled:

Options Enabled
Bug
Performance
Security
Business Logic

Access your configuration settings here.

@github-actions

Copy link
Copy Markdown

Code Coverage Report

Total Coverage: 51.7%

Generated from commit: 0078f64
Repository: LumeWeb/pinner-cli

@pcfreak30
pcfreak30 merged commit 3ee3912 into develop Aug 22, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant