1(() => { 2 "use strict"; 3 const config = {"endpoint":"https://www.v0.build/docs/api/mcp","tools":["search_docs"],"credentials":"same-origin"}; 4 const provider = [ 5 typeof document !== "undefined" && document.modelContext, 6 typeof navigator !== "undefined" && navigator.modelContext, 7 ].find((candidate) => candidate && typeof candidate.registerTool === "function"); 8 if (!provider || typeof provider.registerTool !== "function") { 9 return; 10 } 11 12 let protocolVersion = null; 13 let requestId = 0; 14 15 async function rpc(method, params, isNotification, signal) { 16 const body = { jsonrpc: "2.0", method }; 17 if (params !== undefined) body.params = params; 18 if (!isNotification) body.id = ++requestId; 19 const headers = { 20 "content-type": "application/json", 21 accept: "application/json, text/event-stream", 22 }; 23 if (protocolVersion) headers["mcp-protocol-version"] = protocolVersion; 24 const res = await fetch(config.endpoint, { 25 method: "POST", 26 credentials: config.credentials, 27 headers, 28 body: JSON.stringify(body), 29 signal, 30 }); 31 if (isNotification) return null; 32 if (!res.ok) { 33 throw new Error("MCP request failed: HTTP " + res.status); 34 } 35 const contentType = res.headers.get("content-type") || ""; 36 if (contentType.includes("text/event-stream")) { 37 return parseSse(await res.text(), body.id); 38 } 39 return unwrap(await res.json(), body.id); 40 } 41 42 function parseSse(text, id) { 43 for (const event of text.split(/\r?\n\r?\n/)) { 44 const data = event 45 .split(/\r?\n/) 46 .filter((line) => line.startsWith("data:")) 47 .map((line) => line.slice(5).replace(/^ /, "")) 48 .join("\n"); 49 if (!data) continue; 50 let message; 51 try { 52 message = JSON.parse(data); 53 } catch { 54 continue; 55 } 56 if ( 57 message && 58 message.id === id && 59 ("result" in message || "error" in message) 60 ) { 61 return unwrap(message, id); 62 } 63 } 64 throw new Error("No MCP response found in event stream"); 65 } 66 67 function unwrap(message, id) { 68 if (message && message.error) { 69 throw new Error( 70 message.error.message || "MCP error " + message.error.code, 71 ); 72 } 73 if (!message || message.id !== id) { 74 throw new Error("Unexpected MCP response"); 75 } 76 return message.result; 77 } 78 79 (async () => { 80 const init = await rpc("initialize", { 81 protocolVersion: "2025-06-18", 82 capabilities: {}, 83 clientInfo: { name: "mcp-handler/webmcp", version: "1.0.0" }, 84 }); 85 protocolVersion = (init && init.protocolVersion) || "2025-06-18"; 86 await rpc("notifications/initialized", undefined, true).catch(() => null); 87 88 let cursor; 89 do { 90 const listed = await rpc("tools/list", cursor ? { cursor } : {}); 91 for (const tool of (listed && listed.tools) || []) { 92 if (!config.tools.includes(tool.name)) continue; 93 try { 94 await provider.registerTool({ 95 name: tool.name, 96 title: tool.title || tool.annotations?.title || tool.name, 97 description: tool.description || tool.title || tool.annotations?.title || tool.name, 98 inputSchema: tool.inputSchema, 99 annotations: { readOnlyHint: tool.annotations?.readOnlyHint === true }, 100 execute: (args, options) => 101 rpc("tools/call", { name: tool.name, arguments: args || {} }, false, options?.signal), 102 }); 103 } catch (error) { 104 console.warn("[mcp-handler/webmcp] failed to register tool " + tool.name + ":", error); 105 } 106 } 107 cursor = listed && listed.nextCursor; 108 } while (cursor); 109 })().catch((error) => { 110 console.warn("[mcp-handler/webmcp] failed to register tools:", error); 111 }); 112})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.