/* RFC-1211 AC-3 tests: MCP resources/list exposes every ui:// resource of the active catalog, resources/read serves the committed /.well-known/ui/*.html bytes, and tools/call embeds a {type:"resource"} block for ui-capable capabilities. Not a contract source of truth — the module under test owns the authoritative behavior; fixtures are minimal scaffolding only. RFC-1211: initial test coverage. */ import { test, expect } from "vitest"; import { handleJsonRpcRequest, type McpHandlerContext } from "./handler.ts"; import { MCP_PROTOCOL_VERSION_META_KEY, type JsonRpcRequest } from "./protocol.ts"; import { SUPPORTED_MCP_PROTOCOL_VERSIONS } from "./protocol.ts"; import { buildAgentSurfaceManifest } from "@warpgogol/werkstatt-shared/agent"; import type { CapabilityRecord } from "@warpgogol/werkstatt-shared/ontology"; const SUPPORTED = SUPPORTED_MCP_PROTOCOL_VERSIONS[0]!; const UI_HTML = "preview"; const UI_CAPABILITY: CapabilityRecord = { id: "quote.prepare", version: 1, kind: "action", sideEffect: "none", title: { en: "Preview a quote" }, description: { en: "Validates a quote request." }, input: { type: "object", required: ["email"], additionalProperties: false, properties: { email: { type: "string", format: "email" } }, }, output: { type: "object", required: ["ready"], additionalProperties: false, properties: { ready: { type: "boolean" } }, }, requires: { entitlements: ["agent.actions"], sections: [] }, limits: { perMinutePerIp: 10, maxPayloadBytes: 10240 }, ui: { resource: true }, }; const PLAIN_CAPABILITY: CapabilityRecord = { ...UI_CAPABILITY, id: "lead.submit", ui: undefined, }; function makeCtx(catalog: CapabilityRecord[] = [UI_CAPABILITY]): McpHandlerContext { const manifest = buildAgentSurfaceManifest({ generatedAt: "2026-01-01T00:00:00.000Z", site: "test-site", baseUrl: "https://test.example", languages: { default: "en", supported: ["en"] }, actions: catalog.map((cap) => ({ id: cap.id, url: `/api/agent/v1/actions/${cap.id}`, title: cap.title, inputSchemaRef: `#/components/schemas/${cap.id}-input`, entitlement: "agent.actions" as const, sideEffect: "none" as const, })), mcp: { url: "/api/agent/mcp", protocolVersion: SUPPORTED }, mcpUi: { url: "/.well-known/ui/", uriPrefix: "ui://test-site/" }, }); return { manifest, catalog, ports: { knowledge: { read: async (p: string) => (p.startsWith("/.well-known/ui/") ? UI_HTML : null), }, dispatch: { send: async () => { throw new Error("not used — preview capabilities never dispatch"); }, }, now: () => new Date("2026-01-01T00:00:00.000Z"), }, }; } function req(method: string, params?: Record): JsonRpcRequest { return { jsonrpc: "2.0", id: 1, method, params: { ...params, _meta: { [MCP_PROTOCOL_VERSION_META_KEY]: SUPPORTED }, }, }; } function resultOf(res: Awaited>) { if (!("result" in res)) throw new Error(`expected success, got ${JSON.stringify(res)}`); return res.result; } test("AC-3: resources/list returns every ui:// resource with text/html", async () => { const res = await handleJsonRpcRequest(req("resources/list"), makeCtx()); const { resources } = resultOf(res) as { resources: { uri: string; name: string; mimeType: string }[]; }; const ui = resources.filter((r) => r.uri.startsWith("ui://")); expect(ui).toHaveLength(1); expect(ui[0]).toMatchObject({ uri: "ui://test-site/quote.prepare", name: "quote.prepare", mimeType: "text/html", }); }); test("resources/list: capabilities without ui emit no ui:// entry", async () => { const res = await handleJsonRpcRequest(req("resources/list"), makeCtx([PLAIN_CAPABILITY])); const { resources } = resultOf(res) as { resources: { uri: string }[] }; expect(resources.filter((r) => r.uri.startsWith("ui://"))).toHaveLength(0); }); test("resources/read: ui:// URI returns the committed HTML artifact", async () => { const res = await handleJsonRpcRequest( req("resources/read", { uri: "ui://test-site/quote.prepare" }), makeCtx(), ); const { contents } = resultOf(res) as { contents: { uri: string; mimeType: string; text: string }[]; }; expect(contents).toHaveLength(1); expect(contents[0]).toEqual({ uri: "ui://test-site/quote.prepare", mimeType: "text/html", text: UI_HTML, }); }); test("resources/read: ui:// for a non-ui capability is unknown", async () => { const res = await handleJsonRpcRequest( req("resources/read", { uri: "ui://test-site/lead.submit" }), makeCtx(), ); expect("error" in res).toBe(true); }); test("resources/read: ui:// for a foreign site is unknown", async () => { const res = await handleJsonRpcRequest( req("resources/read", { uri: "ui://other-site/quote.prepare" }), makeCtx(), ); expect("error" in res).toBe(true); }); test("tools/call: ui-capable action embeds a resource content block", async () => { const res = await handleJsonRpcRequest( req("tools/call", { name: "action.quote.prepare", arguments: { email: "agent@example.com" }, }), makeCtx(), ); const { content } = resultOf(res) as { content: { type: string; text?: string; resource?: { uri: string; mimeType: string; text?: string } }[]; }; expect(content[0]!.type).toBe("text"); const block = content.find((c) => c.type === "resource"); expect(block).toBeDefined(); expect(block!.resource).toEqual({ uri: "ui://test-site/quote.prepare", mimeType: "text/html", text: UI_HTML, }); }); test("tools/call: non-ui capability embeds no resource block", async () => { const res = await handleJsonRpcRequest( req("tools/call", { name: "action.lead.submit", arguments: { email: "agent@example.com" }, }), makeCtx([PLAIN_CAPABILITY]), ); const { content } = resultOf(res) as { content: { type: string }[] }; expect(content.every((c) => c.type === "text")).toBe(true); });