// 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");
// 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");