45 lines · 1.9 KB · JavaScript
RawDownload
// Verify sunpeak's inspector advertises the MCP-Apps UI *client* capability to// the upstream MCP server.//// executor gates inline UI rendering on that advertisement (per the MCP-Apps// spec: a server mounts inline only when the host says it can render// `text/html;profile=mcp-app`). A host that doesn't advertise it gets the// deep-link fallback instead of the widget — which would make this whole suite// pass while testing the wrong delivery path.//// sunpeak used to construct its Client with no capabilities at all and we// patched the shipped file. As of 0.20.69 it declares the capability itself, so// this is now a CHECK rather than a patch. It stays fatal: if a future sunpeak// drops the capability, the harness must fail loudly at install time rather// than silently degrade.import { readFileSync, existsSync } from "node:fs";import { fileURLToPath } from "node:url";import { dirname, resolve } from "node:path"; const here = dirname(fileURLToPath(import.meta.url));const target = resolve(here, "../node_modules/sunpeak/bin/commands/inspect.mjs"); if (!existsSync(target)) {  console.error(`[check-sunpeak] ${target} not found. Is sunpeak installed?`);  process.exit(1);} const src = readFileSync(target, "utf8");const EXTENSION_ID = "io.modelcontextprotocol/ui";const MIME_TYPE = "text/html;profile=mcp-app"; if (!src.includes(EXTENSION_ID) || !src.includes(MIME_TYPE)) {  console.error(    [      "[check-sunpeak] the inspector no longer advertises MCP-Apps client support.",      `  expected both ${EXTENSION_ID} and ${MIME_TYPE}`,      `  in: ${target}`,      "Without it executor returns its deep-link fallback and these tests would pass",      "while testing nothing. Pin a sunpeak version that advertises the capability,",      "or restore a patch here that injects it into the Client constructor.",    ].join("\n"),  );  process.exit(1);} console.log("[check-sunpeak] inspector advertises MCP-Apps UI client capability");