Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions scripts/test-webmcp.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion src/lib/webmcp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
// a renamed or removed annotation is a build error, not a silent ship.
type BrowserTool = Omit<WebMCP.ModelContextTool, "execute" | "inputSchema"> & {
inputSchema: Record<string, unknown>;
execute: (input: any, options?: { signal?: AbortSignal }) => unknown;

Check warning on line 50 in src/lib/webmcp.ts

View workflow job for this annotation

GitHub Actions / ESLint

Unexpected any. Specify a different type

Check warning on line 50 in src/lib/webmcp.ts

View workflow job for this annotation

GitHub Actions / build

Unexpected any. Specify a different type
};

// Emitted into the IIFE scope; the helpers below reference it by name.
Expand All @@ -63,22 +63,22 @@
// build-time references and write escaping exactly as the final JS needs it.
// ---------------------------------------------------------------------------

let manifestPromise: any = null;

Check warning on line 66 in src/lib/webmcp.ts

View workflow job for this annotation

GitHub Actions / ESLint

Unexpected any. Specify a different type

Check warning on line 66 in src/lib/webmcp.ts

View workflow job for this annotation

GitHub Actions / build

Unexpected any. Specify a different type

// Fetched once, on the first tool call that needs it. Tools that only drive
// the UI (open_search, open_checklist) never trigger it.
function wmcFetchManifest(manifestUrl: string, signal: any): Promise<any> {

Check warning on line 70 in src/lib/webmcp.ts

View workflow job for this annotation

GitHub Actions / ESLint

Unexpected any. Specify a different type

Check warning on line 70 in src/lib/webmcp.ts

View workflow job for this annotation

GitHub Actions / ESLint

Unexpected any. Specify a different type

Check warning on line 70 in src/lib/webmcp.ts

View workflow job for this annotation

GitHub Actions / build

Unexpected any. Specify a different type

Check warning on line 70 in src/lib/webmcp.ts

View workflow job for this annotation

GitHub Actions / build

Unexpected any. Specify a different type
if (signal && signal.aborted) return Promise.reject(signal.reason);
if (!manifestPromise) {
// This request serves every caller; cancelling one must not abort it.
manifestPromise = fetch(manifestUrl, {
headers: { Accept: "application/json" },
})
.then(function (res: any) {

Check warning on line 77 in src/lib/webmcp.ts

View workflow job for this annotation

GitHub Actions / ESLint

Unexpected any. Specify a different type

Check warning on line 77 in src/lib/webmcp.ts

View workflow job for this annotation

GitHub Actions / build

Unexpected any. Specify a different type
if (!res.ok) throw new Error("HTTP " + res.status);
return res.json();
})
.catch(function (err: any) {

Check warning on line 81 in src/lib/webmcp.ts

View workflow job for this annotation

GitHub Actions / ESLint

Unexpected any. Specify a different type

Check warning on line 81 in src/lib/webmcp.ts

View workflow job for this annotation

GitHub Actions / build

Unexpected any. Specify a different type
manifestPromise = null; // let a later call retry
throw err;
});
Expand All @@ -92,12 +92,12 @@
}
signal.addEventListener("abort", aborted, { once: true });
manifestPromise.then(
function (manifest: any) {

Check warning on line 95 in src/lib/webmcp.ts

View workflow job for this annotation

GitHub Actions / ESLint

Unexpected any. Specify a different type

Check warning on line 95 in src/lib/webmcp.ts

View workflow job for this annotation

GitHub Actions / build

Unexpected any. Specify a different type
signal.removeEventListener("abort", aborted);
if (signal.aborted) reject(signal.reason);
else resolve(manifest);
},
function (err: any) {

Check warning on line 100 in src/lib/webmcp.ts

View workflow job for this annotation

GitHub Actions / ESLint

Unexpected any. Specify a different type

Check warning on line 100 in src/lib/webmcp.ts

View workflow job for this annotation

GitHub Actions / build

Unexpected any. Specify a different type
signal.removeEventListener("abort", aborted);
reject(err);
},
Expand All @@ -121,7 +121,7 @@

function wmcManifestError(
manifestUrl: string,
err: any,

Check warning on line 124 in src/lib/webmcp.ts

View workflow job for this annotation

GitHub Actions / ESLint

Unexpected any. Specify a different type

Check warning on line 124 in src/lib/webmcp.ts

View workflow job for this annotation

GitHub Actions / build

Unexpected any. Specify a different type
): Record<string, unknown> {
return wmcToolError(
"MANIFEST_ERROR",
Expand All @@ -133,7 +133,7 @@
);
}

function wmcTokenise(s: any): string[] {

Check warning on line 136 in src/lib/webmcp.ts

View workflow job for this annotation

GitHub Actions / ESLint

Unexpected any. Specify a different type

Check warning on line 136 in src/lib/webmcp.ts

View workflow job for this annotation

GitHub Actions / build

Unexpected any. Specify a different type
return String(s || "")
.toLowerCase()
.replace(/[^a-z0-9\s/_.-]/g, " ")
Expand Down Expand Up @@ -570,7 +570,7 @@
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(
Expand Down
Loading