Skip to content

Commit 9d57b7a

Browse files
theo-learnerclaude
andcommitted
feat: include widget HTML as EmbeddedResource for Claude Desktop rendering
Add widget HTML inline as MCP EmbeddedResource (type: "resource", mimeType: "text/html;profile=mcp-app") in tool call content array. Injects response data via DOMContentLoaded script so widget renders immediately without postMessage. Keeps existing _meta for ChatGPT compatibility. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 6245bce commit 9d57b7a

File tree

1 file changed

+26
-6
lines changed

1 file changed

+26
-6
lines changed

src/lib/mcp-server.ts

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -884,13 +884,33 @@ function toStandardToolCallResult(
884884
widgetUri?: string,
885885
widgetSessionId?: string
886886
): Record<string, unknown> {
887+
const content: unknown[] = [
888+
{
889+
type: 'text',
890+
text: JSON.stringify(payload, null, 2),
891+
},
892+
];
893+
894+
// Include widget HTML as EmbeddedResource for Claude Desktop (io.modelcontextprotocol/ui)
895+
if (widgetUri && !isError) {
896+
const html = getWidgetHtml(widgetUri);
897+
if (html) {
898+
// Inject data so widget renders immediately without waiting for postMessage
899+
const dataScript = `<script>window.addEventListener('DOMContentLoaded',function(){try{render(${JSON.stringify(payload)})}catch(e){}});</script>`;
900+
const htmlWithData = html.replace('</body>', dataScript + '</body>');
901+
content.push({
902+
type: 'resource',
903+
resource: {
904+
uri: widgetUri,
905+
mimeType: 'text/html;profile=mcp-app',
906+
text: htmlWithData,
907+
},
908+
});
909+
}
910+
}
911+
887912
return {
888-
content: [
889-
{
890-
type: 'text',
891-
text: JSON.stringify(payload, null, 2),
892-
},
893-
],
913+
content,
894914
structuredContent: payload,
895915
isError,
896916
...(widgetUri && !isError

0 commit comments

Comments
 (0)