9}
10
11interface MCPContextAPI {
12 // Tool operations
13 listTools: () => Promise<any[]>;
37 * - Renders HTML in a secure iframe
38 * - Provides fullscreen enter/exit affordances
39 * - Exposes MCP context API to iframe content
40 * - Handles iframe communication via postMessage
41 */
46 const [isLoading, setIsLoading] = useState(true);
47
48 // Create MCP context API that will be exposed to iframe
49 const createMCPContext = useCallback((): MCPContextAPI => {
50 const findClientByName = (serverName: string) => {
51 console.log("[MCP/Browser Renderer] Finding client by name:", serverName, mcpClients);
210 const { type, id, method, args } = event.data;
211
212 if (type !== "mcp-api-call") {
213 return;
214 }
219
220 if (typeof methodFunc !== "function") {
221 throw new Error(`Unknown MCP API method: ${method}`);
222 }
223
225
226 iframe.contentWindow?.postMessage({
227 type: "mcp-api-response",
228 id,
229 success: true,
232 } catch (error) {
233 iframe.contentWindow?.postMessage({
234 type: "mcp-api-response",
235 id,
236 success: false,
252 </script>
253 <script>
254 // MCP Context API for iframe content
255 window.mcpContext = {
256 // Async wrapper for postMessage communication
257 async callAPI(method, ...args) {
258 return new Promise((resolve, reject) => {
259 const id = Math.random().toString(36).substr(2, 9);
260
261 const handleResponse = (event) => {
262 if (event.data.type === 'mcp-api-response' && event.data.id === id) {
263 window.removeEventListener('message', handleResponse);
264 if (event.data.success) {
273
274 window.parent.postMessage({
275 type: 'mcp-api-call',
276 id,
277 method,
282 setTimeout(() => {
283 window.removeEventListener('message', handleResponse);
284 reject(new Error('MCP API call timeout'));
285 }, 30000);
286 });
288
289 // Convenience methods
290 async listTools() { return this.callAPI('listTools'); },
291 async callTool(serverName, toolName, args) { return this.callAPI('callTool', serverName, toolName, args); },
292 async listPrompts() { return this.callAPI('listPrompts'); },
293 async getPrompt(serverName, promptName, args) { return this.callAPI('getPrompt', serverName, promptName, args); },
294 async listResources() { return this.callAPI('listResources'); },
295 async readResource(serverName, uri) { return this.callAPI('readResource', serverName, uri); },
296 log(level, message, data) { this.callAPI('log', level, message, data); },
297 requestFullscreen() { this.callAPI('requestFullscreen'); },
298 exitFullscreen() { this.callAPI('exitFullscreen'); },
299 async isFullscreen() { return this.callAPI('isFullscreen'); }
300 };
301