Skip to content

Conversation

@antonpk1
Copy link
Contributor

Summary

This PR adds true bidirectional message relay to the rawhtml proxy mode, enabling full two-way communication between the parent window and the inner iframe.

Problem

Currently, the proxy only relays messages in one direction:

  • ✅ Inner iframe → Parent: Working
  • ❌ Parent → Inner iframe: Only ui-html-content is handled

This limitation prevents parent windows from sending custom messages to the inner iframe, restricting interactive capabilities.

Solution

Modified the message event listener in index.html to relay all messages from parent to inner iframe (not just ui-html-content):

// Before: Only ui-html-content was handled
if (event.source === window.parent && event.data && event.data.type === 'ui-html-content') {
  // handle HTML content
}

// After: All parent messages are relayed
if (event.source === window.parent) {
  if (event.data && event.data.type === 'ui-html-content') {
    // handle HTML content
  } else {
    // relay other messages to inner iframe
    inner.contentWindow.postMessage(event.data, '*');
  }
}

Benefits

This enables MCP-UI applications to implement:

  • ✨ Parent-initiated UI updates
  • ✨ Action acknowledgments
  • ✨ State synchronization
  • ✨ Custom event handling
  • ✨ Bidirectional protocols

Backward Compatibility

✅ Fully backward compatible - existing ui-html-content flow is unchanged

Testing

Tested with:

  • Serving the proxy via Python HTTP server
  • Custom messages from parent to inner iframe
  • Verified message relay in both directions using console logging

🤖 Generated with Claude Code

This enhancement adds true bidirectional communication between the parent
window and the inner iframe in rawhtml mode.

Previously, the proxy only relayed messages from the inner iframe to the
parent window. This created a limitation where the parent could not send
custom messages (other than ui-html-content) to the inner iframe.

Changes:
- Modified message event listener to handle all parent messages
- Added relay logic to forward non-ui-html-content messages to inner iframe
- Maintains backward compatibility with existing ui-html-content flow
- Enables full two-way communication for UI actions and custom protocols

This allows MCP-UI applications to implement interactive features that
require bidirectional communication, such as:
- Parent-initiated UI updates
- Action acknowledgments
- State synchronization
- Custom event handling

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@idosal idosal requested a review from Copilot October 24, 2025 16:57
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 enables bidirectional message relay in the rawhtml proxy mode by allowing the parent window to send custom messages to the inner iframe, complementing the existing iframe-to-parent communication.

  • Modified the message event listener to relay all parent messages to the inner iframe
  • Preserved the existing ui-html-content handling logic
  • Added a conditional relay for non-content messages

Comment on lines +69 to +71
if (inner && inner.contentWindow) {
inner.contentWindow.postMessage(event.data, '*');
}
Copy link

Copilot AI Oct 24, 2025

Choose a reason for hiding this comment

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

Using wildcard origin '*' in postMessage allows any origin to receive messages. Consider restricting to specific origins or validating event.origin before relaying messages to prevent potential security vulnerabilities.

Copilot uses AI. Check for mistakes.
Comment on lines +69 to +71
if (inner && inner.contentWindow) {
inner.contentWindow.postMessage(event.data, '*');
}
Copy link

Copilot AI Oct 24, 2025

Choose a reason for hiding this comment

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

The message is relayed without any validation of event.origin or event.data structure. Consider adding origin validation (checking event.origin against expected parent origins) before relaying messages to improve security.

Copilot uses AI. Check for mistakes.
Copy link
Collaborator

@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.

Great catch, thanks @antonpk1 !

@idosal idosal changed the title feat: Enable bidirectional message relay in rawhtml proxy mode fix: enable bidirectional message relay in rawhtml proxy mode Oct 24, 2025
@idosal idosal merged commit f0bdefb into MCP-UI-Org:main Oct 24, 2025
8 checks passed
github-actions bot pushed a commit that referenced this pull request Oct 24, 2025
…nt/v5.14.1) (2025-10-24)

### Bug Fixes

* Enable bidirectional message relay in rawhtml proxy mode ([#138](#138)) ([f0bdefb](f0bdefb))
github-actions bot pushed a commit that referenced this pull request Oct 25, 2025
…er/v5.13.1) (2025-10-25)

### Bug Fixes

* Enable bidirectional message relay in rawhtml proxy mode ([#138](#138)) ([f0bdefb](f0bdefb))
* ensure Apps SDK adapter is bundled properly and initialized wth config ([#137](#137)) ([4f7c25c](4f7c25c))
github-actions bot pushed a commit that referenced this pull request Nov 4, 2025
# 1.0.0 (2025-11-04)

### Bug Fixes

* add a bridge to pass messages in and out of the proxy ([#38](#38)) ([30ccac0](30ccac0))
* bump client version ([75c9236](75c9236))
* **client:** specify iframe ([fd0b70a](fd0b70a))
* **client:** styling ([6ff9b68](6ff9b68))
* dependencies ([887f61f](887f61f))
* Enable bidirectional message relay in rawhtml proxy mode ([#138](#138)) ([f0bdefb](f0bdefb))
* ensure Apps SDK adapter is bundled properly and initialized wth config ([#137](#137)) ([4f7c25c](4f7c25c))
* export RemoteDomResource ([2b86f2d](2b86f2d))
* export ResourceRenderer and HtmlResource ([2b841a5](2b841a5))
* exports ([3a93a16](3a93a16))
* fix file extension reference in package.json ([927989c](927989c))
* iframe handle ([#15](#15)) ([66bd4fd](66bd4fd))
* lint ([4487820](4487820))
* lint ([d0a91f9](d0a91f9))
* minor typo ([a0bee9c](a0bee9c))
* move react dependencies to be peer dependencies ([#91](#91)) ([f672f3e](f672f3e)), closes [#90](#90)
* package config ([8dc1e53](8dc1e53))
* packaging ([9e6babd](9e6babd))
* pass ref explicitly using iframeProps ([#33](#33)) ([d01b5d1](d01b5d1))
* publish ([0943e7a](0943e7a))
* ref passing to UIResourceRenderer ([#32](#32)) ([d28c23f](d28c23f))
* remove shared dependency ([e66e8f4](e66e8f4))
* rename components and methods to fit new scope ([#22](#22)) ([6bab1fe](6bab1fe))
* rename delivery -> encoding and flavor -> framework ([#36](#36)) ([9a509ed](9a509ed))
* Ruby comment ([b22dc2e](b22dc2e))
* support react-router ([21ffb95](21ffb95))
* text and blob support in RemoteDOM resources ([ec68eb9](ec68eb9))
* trigger release ([aaca831](aaca831))
* typescript ci publish ([e7c0ebf](e7c0ebf))
* typescript types to be compatible with MCP SDK ([#10](#10)) ([74365d7](74365d7))
* update deps ([4091ef4](4091ef4))
* update isUIResource to use EmbeddedResource type ([#122](#122)) ([5a65a0b](5a65a0b)), closes [#117](#117)
* use targetOrigin in the proxy message relay ([#40](#40)) ([b3fb54e](b3fb54e))
* validate URL ([b7c994d](b7c994d))
* wc dist overwrite ([#63](#63)) ([9e46c56](9e46c56))

### Documentation

* bump ([#4](#4)) ([ad4d163](ad4d163))

### Features

* add convenience function isUIResource to client SDK ([#86](#86)) ([607c6ad](607c6ad))
* add embeddedResourceProps for annotations ([#99](#99)) ([b96ec44](b96ec44))
* add proxy option to externalUrl ([#37](#37)) ([7b95cd0](7b95cd0))
* add remote-dom content type ([#18](#18)) ([5dacf37](5dacf37))
* add Ruby server SDK ([#31](#31)) ([5ffcde4](5ffcde4))
* add sandbox permissions instead of an override ([#83](#83)) ([b1068e9](b1068e9))
* add ui-request-render-data message type ([#111](#111)) ([26135ce](26135ce))
* add UIResourceRenderer Web Component ([#58](#58)) ([ec8f299](ec8f299))
* auto resize with the autoResizeIframe prop ([#56](#56)) ([76c867a](76c867a))
* change onGenericMcpAction to optional onUiAction ([1913b59](1913b59))
* **client:** allow setting supportedContentTypes for HtmlResource ([#17](#17)) ([e009ef1](e009ef1))
* consolidate ui:// and ui-app:// ([#8](#8)) ([2e08035](2e08035))
* pass iframe props down ([#14](#14)) ([112539d](112539d))
* refactor UTFtoB64 (bump server version) ([#95](#95)) ([2d5e16b](2d5e16b))
* send render data to the iframe ([#51](#51)) ([d38cfc7](d38cfc7))
* separate html and remote-dom props ([#24](#24)) ([a7f0529](a7f0529))
* support adapters ([#127](#127)) ([d4bd152](d4bd152))
* support generic messages response ([#35](#35)) ([10b407b](10b407b))
* support metadata in Python SDK ([#134](#134)) ([9bc3c64](9bc3c64))
* support passing resource metadata ([#87](#87)) ([f1c1c9b](f1c1c9b))
* support proxy for rawHtml ([#132](#132)) ([1bbeb09](1bbeb09))
* support ui action result types ([#6](#6)) ([899d152](899d152))
* switch to ResourceRenderer ([#21](#21)) ([6fe3166](6fe3166))

### BREAKING CHANGES

* The existing naming is ambiguous. Renaming delivery to encoding and flavor to framework should clarify the intent.
* exported names have changed
* removed deprecated client API
* (previous one didn't take due to semantic-release misalignment)
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.

3 participants