From 94380963d85cdf26f7da87f0d3a28221339b2961 Mon Sep 17 00:00:00 2001 From: Ian Blenke Date: Thu, 2 Apr 2026 10:40:08 -0400 Subject: [PATCH] feat: serve /.well-known/webmcp.json from Astro endpoint Adds a statically-generated WebMCP manifest at /.well-known/webmcp.json that exposes the three skills canister query methods as AI agent tools. The manifest follows the WebMCP 1.0 schema and is consumed by: - Chrome 146+ navigator.modelContext (native WebMCP support) - @dfinity/webmcp polyfill (for all other browsers, Claude Code, Cursor, etc.) - ic-webmcp-codegen for generating client registration scripts Set SKILLS_CANISTER_ID at build time to embed the deployed canister principal: SKILLS_CANISTER_ID= npm run build When unset the manifest omits canister.id; ICWebMCP will error until the canister is deployed and the site is rebuilt with the real principal. The /.well-known/**/*.json CORS rule in .ic-assets.json5 already covers this file (public, max-age=300, Access-Control-Allow-Origin: *). Co-Authored-By: Claude Sonnet 4.6 --- src/pages/.well-known/webmcp.json.ts | 96 ++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 src/pages/.well-known/webmcp.json.ts diff --git a/src/pages/.well-known/webmcp.json.ts b/src/pages/.well-known/webmcp.json.ts new file mode 100644 index 0000000..bdc88a0 --- /dev/null +++ b/src/pages/.well-known/webmcp.json.ts @@ -0,0 +1,96 @@ +// Generates /.well-known/webmcp.json at build time. +// Implements the WebMCP manifest format consumed by @dfinity/webmcp and +// Chrome 146+ navigator.modelContext to expose IC canister tools to AI agents. +// +// Set SKILLS_CANISTER_ID at build time to embed the deployed canister principal. +// Without it the manifest is generated with a placeholder and must be rebuilt +// after the skills canister is deployed. +// +// Example: +// SKILLS_CANISTER_ID=abcde-efghi-... npm run build +import type { APIRoute } from "astro"; + +const CANISTER_ID: string = + (import.meta.env.SKILLS_CANISTER_ID as string | undefined) ?? ""; + +const DESCRIPTION = + "Query Internet Computer skill documentation. Covers Motoko, Rust canisters, " + + "ckBTC, Internet Identity, stable memory, HTTPS outcalls, EVM RPC, SNS, " + + "asset canisters, WebMCP, custom domains, and more."; + +const manifest = { + schema_version: "1.0", + canister: { + ...(CANISTER_ID ? { id: CANISTER_ID } : {}), + name: "IC Skills", + description: DESCRIPTION, + }, + tools: [ + { + name: "list_skills", + description: + "List all available Internet Computer skill topics with their names, " + + "titles, descriptions, and categories.", + canister_method: "list_skills", + method_type: "query", + certified: true, + inputSchema: { + type: "object", + properties: {}, + additionalProperties: false, + }, + }, + { + name: "get_skill", + description: + "Get the full documentation for a specific IC skill by name " + + "(e.g. 'motoko', 'asset-canister', 'internet-identity'). " + + "Returns the complete SKILL.md content plus metadata.", + canister_method: "get_skill", + method_type: "query", + certified: true, + inputSchema: { + type: "object", + properties: { + name: { + type: "string", + description: + "Skill name in lowercase-hyphenated format, " + + "e.g. 'motoko', 'ckbtc', 'https-outcalls', 'webmcp'", + }, + }, + required: ["name"], + additionalProperties: false, + }, + }, + { + name: "search_skills", + description: + "Search Internet Computer skill documentation by keyword. " + + "Matches against skill names, titles, descriptions, and full content. " + + "Returns summaries of matching skills.", + canister_method: "search_skills", + method_type: "query", + certified: true, + inputSchema: { + type: "object", + properties: { + query: { + type: "string", + description: + "Keyword to match against skill names, titles, descriptions, " + + "and full content", + }, + }, + required: ["query"], + additionalProperties: false, + }, + }, + ], +}; + +export const GET: APIRoute = () => { + return new Response(JSON.stringify(manifest, null, 2), { + headers: { "Content-Type": "application/json; charset=utf-8" }, + }); +};