-
Notifications
You must be signed in to change notification settings - Fork 32
Open
Labels
enhancementNew feature or requestNew feature or request
Description
Lots of people might come to MCP Apps w/ an existing iframe embed, not wanting to reimplement everything.
But some hosts might balk at allowing nested external iframes (which can't be audited easily).
Here is a rough suggestion on how to turn an iframe embed app (supposedly taking its parameters from the URL query params) into an MCP App (which just takes its parameters from the tool outputs, or inputs).
Taking the following embed.ts (normally iframed as https://myhost.com/embed.html?q=some+search), we can have initialization logic that fetches params from the MCP App's tool results instead of from its query params, if we're not iframed.
import { App, PostMessageTransport } from "@modelcontextprotocol/ext-apps";
const isMcpApp = () => window.location.host !== 'myhost.com';
// Returns the query params when embedded, or the MCP tool result' structuredContent
async function getParameters(): Promise<Record<string, string>> {
if (isMcpApp()) {
const app = new McpApp({name: 'Our App', version: ''});
await app.connect(new PostMessageTransport());
return new Promise(resolve => {
app.ontoolresult = ({structuredContent}) => resolve(structuredContent);
// Note: inputs are available too.
});
} else {
return Object.fromEntries([...new URL(window.location.href).searchParams])
}
}
async function main() {
const {q: query} = await getParameters();
...
}
main().catch(...)import { McpServer } from "@modelcontextprotocol/sdk/";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/";
const server = new McpServer({name: 'Example Server', version: '1.0.0'});
const uiHtml = await fetch("dist/embed.html").then(r => t.text());
const resourceUri = 'ui://example';
server.registerResource({
uri: resourceUri,
....,
content: uiHtml,
_meta: {
ui: {
csp: {
connectDomains: ['api.myhost.com']
}
}
}
})
server.registerTool('show-embed', {
inputSchema: z.object({q: z.string()}).shape,
_meta: {
'ui/resourceUri': resourceUri,
}
}, ({message}) => {
return {
content: [],
structuredContent: {q: 'the query'`}
}
})
server.server.connect(new StdioServerTransport())
.then(() => console.error('Server is running');idosal
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request