Skip to content

Conversation

@aharvard
Copy link
Collaborator

@aharvard aharvard commented Oct 30, 2025

Summary

This PR upgrades @mcp-ui/client to better handle messages from MCP-UI iframes and also decouples the MCP-UI iframe CSP from Goose's top-level CSP set for Electron.

Our top-level CSP previously blocked external fonts, stylesheets, scripts, and media. We now use an MCP-UI Proxy with a permissive CSP inside a sandboxed iframe for security. This creates a parent-child iframe architecture in Goose.

Demo

Now, Goose can load external fonts inside MCP-UI iframes and MCP-UI resources can send request-render-data to get the theme value from goose (as shown here in mcp-ui docs)

goose-proxy-csp-fonts.mov

Now, Goose can load external video and audio media files (unmute video below for sound).

goose-proxy-csp-media.mov

Type of Change

  • Feature
  • Bug fix
  • Refactor / Code quality
  • Performance improvement
  • Documentation
  • Tests
  • Security fix
  • Build / Release
  • Other (specify below)

Testing

Manual testing with aharavrd mcp as shown in videos above.

Related Issues

No issue or discussions to link.

Note

This work enables MCP-UI interoperability between Goose and ChatGPT by addressing two blockers:

  1. Sandboxed iframe with permissive CSP - Implements ChatGPT's approach of using a 3rd party sandboxed origin with a lax CSP, enabling capabilities like remote script execution. This follows MCP-UI's documented pattern (used by Postman).

  2. Render data support - Adds full render data implementation, which is currently missing in Goose.

This unblocks @idosal and @liady from targeting Goose for cross-platform MCP-UI development with the Apps SDK.


async function startMcpUIProxyServer(): Promise<number> {
return new Promise((resolve, reject) => {
const expressApp = express();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice - and this looks like it is already in the dependencies from electron?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just a note regarding the deletions in this file: previously we were over-handling messages form the iframe, upgrading @mcp-ui/client and using a proxy takes most of this off our plate.

@aharvard aharvard marked this pull request as ready for review October 31, 2025 13:32
@aharvard
Copy link
Collaborator Author

.bundle

@aharvard aharvard requested a review from michaelneale October 31, 2025 13:45
@liady
Copy link

liady commented Oct 31, 2025

@aharvard looks good! Glad this also uses the SDK functionality instead of custom Goose code.
Good proxy implementation 👍. I think we should probably make this code reusable from the SDK somehow at some point.

@aharvard
Copy link
Collaborator Author

Thanks for looking @liady!

I think we should probably make this code reusable from the SDK somehow at some point.

^ yeah, you read my mind!

Copy link

@idosal idosal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great @aharvard !

cc @evalstate - this should remove the limitations on the HF MCP-UI tools

@angiejones angiejones requested a review from Copilot November 2, 2025 19:16
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements an MCP-UI proxy server to enable secure rendering of MCP UI resources in the Goose Desktop application. The proxy server allows controlled iframe embedding of external content while maintaining security through token-based authentication and origin validation.

Key changes:

  • Added an HTTP server using Express to serve MCP-UI proxy HTML files with token-based security
  • Integrated the @mcp-ui/client library (updated to v5.14.1) for rendering MCP UI resources
  • Implemented security controls including random token generation, header injection, and origin validation

Reviewed Changes

Copilot reviewed 6 out of 7 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
ui/desktop/static/mcp-ui-proxy.html New proxy HTML page that handles iframe embedding for both raw HTML and external URLs with content security policy
ui/desktop/src/main.ts Adds Express HTTP server for MCP-UI proxy with security middleware, port management, and Electron session configuration
ui/desktop/src/preload.ts Exposes getMcpUIProxyUrl API to renderer process for fetching the proxy server URL
ui/desktop/src/components/MCPUIResourceRenderer.tsx Refactors action handlers, removes custom type definitions in favor of imported types, and configures proxy URL support
ui/desktop/package.json Updates @mcp-ui/client dependency from v5.13.0 to v5.14.1
ui/desktop/package-lock.json Updates lock file for @mcp-ui/client v5.14.1
ui/desktop/forge.config.ts Adds static directory to packaged resources
Files not reviewed (1)
  • ui/desktop/package-lock.json: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copilot AI review requested due to automatic review settings November 3, 2025 13:08
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 6 out of 7 changed files in this pull request and generated 3 comments.

Files not reviewed (1)
  • ui/desktop/package-lock.json: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

aharvard and others added 2 commits November 3, 2025 08:17
Use lowercase 'x-mcp-ui-proxy-token' when injecting header to match Express's normalized header names for consistency and clarity.
Copilot AI review requested due to automatic review settings November 3, 2025 13:21
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 6 out of 7 changed files in this pull request and generated 1 comment.

Files not reviewed (1)
  • ui/desktop/package-lock.json: Language not supported
Comments suppressed due to low confidence (1)

ui/desktop/src/components/MCPUIResourceRenderer.tsx:1

  • Comment on line 332 contains a typo: 'MPC-UIs' should be 'MCP-UIs'.
import {

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copilot AI review requested due to automatic review settings November 10, 2025 22:02
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 7 out of 8 changed files in this pull request and generated 3 comments.

Files not reviewed (1)
  • ui/desktop/package-lock.json: Language not supported

@aharvard
Copy link
Collaborator Author

I chatted with @DOsinga about moving the server into the Rust backend, and @alexhancock will perform the maneuver. Thanks, guys!

@aharvard
Copy link
Collaborator Author

Thanks @alexhancock for moving the proxy server from Electron to the backend in #5749

@DOsinga and @michaelneale — can we get another look? If everything is in order, I'd like to merge!

@michaelneale
Copy link
Collaborator

would that live mcp sampling test have anytihng to do with this - or just bad luck?

* origin/main: (60 commits)
  chore: incorporate LF feedback (#5787)
  docs: quick launcher (#5779)
  Bump auto scroll threshold (#5738)
  fix: add one-time cleanup for linux hermit locking issues (#5742)
  Don't show update tray icon if GOOSE_VERSION is set (#5750)
  fix: get win node path from registry (#5731)
  Handle spaces in extension names also (#5770)
  Remove empty settings card for Scheduling Engine (#5771)
  fix windows cli build (#5768)
  fix: Implement a CredentialStore for auth (#5741)
  blog post: How to Successfully Migrate Your App with an AI Agent (#5762)
  Simplify finding `goosed` (#5739)
  More time for goosed (#5746)
  Match lower case (#5763)
  scan recipe for security when saving recipe (#5747)
  feat: trying grok for live test (#5732)
  Platform Extension MOIM (Minus One Info Message) (#5027)
  docs: remove hackathon banner (#5756)
  Fix: Recipes respect the quiet flag (#5743)
  docs: update cli commands (#5744)
  ...
Copilot AI review requested due to automatic review settings November 18, 2025 13:26
@aharvard aharvard dismissed michaelneale’s stale review November 18, 2025 13:28

dismissing stale review to unblock merge checks

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 14 out of 15 changed files in this pull request and generated 2 comments.

Files not reviewed (1)
  • ui/desktop/package-lock.json: Language not supported

@aharvard
Copy link
Collaborator Author

aharvard commented Nov 18, 2025

would that live mcp sampling test have anytihng to do with this - or just bad luck?

FYI gpt-5-mini sampling test kept failing. I got it to pass on the second manual re-run.

All checks passed.

Ready to merge?

@zanesq
Copy link
Collaborator

zanesq commented Nov 18, 2025

Ran copilot security review and this came up as potentially important. Wondering if worth addressing @alexhancock or @DOsinga

**Secret in query string (critical)**
You place the secret in the proxy URL query (…/mcp-ui-proxy?secret=...), then load that page and—if it embeds an external target iframe—the external target can receive the proxy page URL as the referrer (document.referrer / Referer header). That means the secret can leak to third-party sites when the proxy iframe loads external URLs. This is a high-risk leak.
Recommendation: never put long-lived secrets in the URL. Use one of:
Deliver short-lived session token via a Set-Cookie (HTTP-only) from the server and read it via State on the proxy endpoint.
POST the secret to the proxy page (i.e. open a small HTML page that receives the secret via POST and stores it in JS memory), or have the server render the proxy page without the secret in the URL and provide the secret to the iframe via a safer channel (cookie, server session).
Use a one-time ephemeral token generated server-side for that UI session, not your main secret key.
At minimum, set Referrer-Policy to no-referrer on the proxy HTML and send Referrer-Policy response header so the browser won't send the full URL as the referer — but this is still weaker than avoiding secrets in URLs.

**Solution**
Remove secret from the query string. Provide the secret via:
a short-lived token (server-generated) embedded in the proxy page or a cookie, or
by having Electron call the proxy page and then postMessage the secret into it after load (so it’s never in the URL).

@zanesq
Copy link
Collaborator

zanesq commented Nov 18, 2025

Copilot also mentioned this, created a PR for this change, @aharvard is testing it out

Add a Referrer-Policy header/meta tag (e.g. no-referrer) on the proxy HTML to help prevent accidental leak if secret is ever in the URL.

Copilot AI review requested due to automatic review settings November 18, 2025 19:31
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@zanesq zanesq merged commit 9d5d8c0 into main Nov 19, 2025
24 of 26 checks passed
katzdave added a commit that referenced this pull request Nov 19, 2025
…xt-test

* 'main' of github.com:block/goose:
  chore: Add Adrian Cole to Maintainers (#5815)
  [MCP-UI] Proxy and Better Message Handling (#5487)
  Release 1.15.0
  Document New Window menu in macOS dock (#5811)
  Catch cron errors (#5707)
  feat/fix Re-enabled WAL with commit transaction management (Linux Verification Requested) (#5793)
  chore: remove autopilot experimental feature (#5781)
  Read paths from an interactive & login shell (#5774)
  docs: acp clients (#5800)
wpfleger96 added a commit that referenced this pull request Nov 20, 2025
* main: (33 commits)
  fix: support Gemini 3's thought signatures (#5806)
  chore: Add Adrian Cole to Maintainers (#5815)
  [MCP-UI] Proxy and Better Message Handling (#5487)
  Release 1.15.0
  Document New Window menu in macOS dock (#5811)
  Catch cron errors (#5707)
  feat/fix Re-enabled WAL with commit transaction management (Linux Verification Requested) (#5793)
  chore: remove autopilot experimental feature (#5781)
  Read paths from an interactive & login shell (#5774)
  docs: acp clients (#5800)
  Provider error proxy for simulating various types of errors (#5091)
  chore: Add links to maintainer profiles (#5788)
  Quick fix for community all stars script (#5798)
  Document Mistral AI provider (#5799)
  docs: Add Community Stars recipe script and txt file (#5776)
  chore: incorporate LF feedback (#5787)
  docs: quick launcher (#5779)
  Bump auto scroll threshold (#5738)
  fix: add one-time cleanup for linux hermit locking issues (#5742)
  Don't show update tray icon if GOOSE_VERSION is set (#5750)
  ...
michaelneale added a commit that referenced this pull request Nov 24, 2025
* main: (48 commits)
  [fix] generic check for gemini compat (#5842)
  Add scheduler to diagnostics (#5849)
  Cors and token (#5850)
  fix sessions coming back with empty messages (#5841)
  markdown export from URL (#5830)
  Next camp refactor live (#5706)
  Add out of context compaction test via error proxy (#5805)
  fix: Add backward compatibility for conversationCompacted message type (#5819)
  Add /agent/stop endpoint, make max active agents configurable (#5826)
  Handle 404s (#5791)
  Persist provider name and model config in the session (#5419)
  Comment out the flaky mcp callers (#5827)
  Slash commands (#5718)
  fix: remove setx calls to not permanently edit the windows shell PATH (#5821)
  fix: Parse maas models for gcp vertex provider (#5816)
  fix: support Gemini 3's thought signatures (#5806)
  chore: Add Adrian Cole to Maintainers (#5815)
  [MCP-UI] Proxy and Better Message Handling (#5487)
  Release 1.15.0
  Document New Window menu in macOS dock (#5811)
  ...
BlairAllan pushed a commit to BlairAllan/goose that referenced this pull request Nov 29, 2025
Co-authored-by: Copilot <[email protected]>
Co-authored-by: Alex Hancock <[email protected]>
Co-authored-by: Zane <[email protected]>
Signed-off-by: Blair Allan <[email protected]>
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.

7 participants