diff --git a/scripts/test-webmcp.mjs b/scripts/test-webmcp.mjs index 37d5747c..c1277ba0 100644 --- a/scripts/test-webmcp.mjs +++ b/scripts/test-webmcp.mjs @@ -35,6 +35,44 @@ async function loadTools(fetch) { return tools; } +for (const origin of [ + "https://preview.example.pages.dev", + "http://localhost:4321", +]) { + test(`topic reads use the current deployment at ${origin}`, async () => { + const page = manifest.pages[0]; + const path = `/spec/${page.category}/${page.slug}.md`; + const markdown = readFileSync( + new URL(`../dist${path}`, import.meta.url), + "utf8", + ); + const requests = []; + const tools = await loadTools(async (url) => { + // Resolve from a nested page and enforce the deployed connect-src 'self'. + const resolved = new URL( + url, + `${origin}/spec/${page.category}/${page.slug}/`, + ); + requests.push(resolved.href); + if (resolved.origin !== origin) + throw new TypeError("Blocked cross-origin fetch"); + if (resolved.pathname === "/webmcp-manifest.json") return response(); + assert.equal(resolved.pathname, path); + return { ok: true, text: async () => markdown }; + }); + + const result = await tools.get_topic.execute({ + slug: page.slug, + limit: 500, + }); + assert.equal(result, markdown); + assert.deepEqual(requests, [ + `${origin}/webmcp-manifest.json`, + `${origin}${path}`, + ]); + }); +} + for (const cancelledCaller of ["first", "second"]) { test(`cancelling the ${cancelledCaller} caller leaves the shared fetch usable`, async () => { let finish; diff --git a/src/lib/webmcp.ts b/src/lib/webmcp.ts index fe91712e..30490114 100644 --- a/src/lib/webmcp.ts +++ b/src/lib/webmcp.ts @@ -570,7 +570,7 @@ export async function webmcpManifest() { summary: e.data.summary, order: e.data.order, url: `${site.url}/spec/${e.data.category}/${slug}/`, - mdUrl: `${site.url}/spec/${e.data.category}/${slug}.md`, + mdUrl: `/spec/${e.data.category}/${slug}.md`, }; }) .sort(