import { describe, expect, it } from "bun:test"; import { handler, TOOLS } from "./mcp"; import type { CreateDocumentInput, Document, DocumentReader } from "./mcp"; const document: Document = { id: "f401c8d6-3717-4f1d-8473-cfdd0af894e4", title: "Release readiness", source: "# Release readiness\n", revision: 4, }; const creation = { idempotencyKey: "create-plan-1", repository: "githubnext/chopin", baseBranch: "main", baseCommit: "0123456789abcdef0123456789abcdef01234567", title: "Ship MCP creation", brief: { goal: "Create a collaborative plan.", constraints: ["Keep plans immutable through MCP."], settledDecisions: ["Use the documented dialect."], openQuestions: ["Which reviewer owns the rollout?"], repositoryFindings: ["The plan becomes a hosted channel."], }, plan: '# Draft\n\n\nCreated through MCP.\n\n', }; function request( body: unknown, init: RequestInit = {}, ): Request { let headers = new Headers({ authorization: "Bearer allowed", "content-type": "application/json", ...init.headers, }); return new Request("https://chopin.test/mcp", { method: "POST", ...init, headers, body: JSON.stringify(body), }); } function reader(): DocumentReader { return { async list(caller, repository) { return caller === "octocat" && repository === "githubnext/chopin" ? [{ id: document.id, title: document.title }] : []; }, async read(caller, id) { return caller === "octocat" && id === document.id ? document : undefined; }, }; } function endpoint() { return handler({ caller: request => request.headers.get("authorization") === "Bearer allowed" ? "octocat" : undefined, documents: reader(), }); } async function json(response: Response): Promise> { return await response.json() as Record; } describe("the MCP read protocol", () => { it("authenticates initialize, lists repository documents, and reads canonical source", async () => { let mcp = endpoint(); let initialized = await json( await mcp(request({ jsonrpc: "2.0", id: 1, method: "initialize", params: {}, })), ); expect(initialized).toMatchObject({ jsonrpc: "2.0", id: 1, result: { protocolVersion: "2025-03-26", capabilities: { tools: {} }, serverInfo: { name: "chopin" }, }, }); let tools = await json( await mcp(request({ jsonrpc: "2.0", id: 2, method: "tools/list", })), ); expect((tools.result as { tools: unknown[] }).tools).toEqual(TOOLS); let listed = await json( await mcp(request({ jsonrpc: "2.0", id: 3, method: "tools/call", params: { name: "list_documents", arguments: { repository: "githubnext/chopin" } }, })), ); expect((listed.result as { structuredContent: unknown }).structuredContent).toEqual({ documents: [{ id: document.id, title: document.title }], }); let read = await json( await mcp(request({ jsonrpc: "2.0", id: 4, method: "tools/call", params: { name: "read_document", arguments: { id: document.id } }, })), ); expect((read.result as { structuredContent: unknown }).structuredContent).toEqual(document); }); it("keeps the repository-scoped tool schemas static", async () => { expect(TOOLS).toEqual(expect.arrayContaining([ expect.objectContaining({ name: "list_documents", inputSchema: expect.objectContaining({ required: ["repository"], additionalProperties: false, }), }), expect.objectContaining({ name: "read_document", inputSchema: expect.objectContaining({ required: ["id"], additionalProperties: false }), }), ])); }); it("creates a validated canonical document through the host adapter", async () => { let mcp = handler({ caller: () => "octocat", documents: reader(), create: { async create(_caller: string, input: CreateDocumentInput) { return { kind: "created" as const, document: { id: "created", title: input.title, brief: input.brief, source: input.plan, revision: 0, url: "/channels/created", }, }; }, }, }); let result = await json( await mcp(request({ jsonrpc: "2.0", id: 5, method: "tools/call", params: { name: "create_document", arguments: creation }, })), ); expect(result.error).toBeUndefined(); expect((result.result as { structuredContent: Record }).structuredContent) .toMatchObject({ id: "created", title: creation.title, brief: creation.brief, revision: 0, url: "/channels/created", }); expect( (result.result as { structuredContent: { source: string } }).structuredContent.source, ).toMatch(/]*id="[0-7][0-9A-HJKMNP-TV-Z]{25}")(?=[^>]*type="note")/); }); it("returns dialect issues without asking the host to persist an invalid plan", async () => { let created = false; let mcp = handler({ caller: () => "octocat", documents: reader(), create: { async create() { created = true; return { kind: "forbidden" as const }; }, }, }); let result = await json( await mcp(request({ jsonrpc: "2.0", id: 6, method: "tools/call", params: { name: "create_document", arguments: { ...creation, plan: "\n" }, }, })), ); expect((result.result as { isError: boolean }).isError).toBe(true); expect( (result.result as { structuredContent: { issues: unknown[] } }).structuredContent.issues, ).toEqual([expect.objectContaining({ code: "unknown-component", path: "root > Chart[0]", offset: 0, })]); expect(created).toBe(false); }); it("reports a changed idempotent request as a tool conflict", async () => { let mcp = handler({ caller: () => "octocat", documents: reader(), create: { async create() { return { kind: "conflict" as const }; }, }, }); let result = await json( await mcp(request({ jsonrpc: "2.0", id: 7, method: "tools/call", params: { name: "create_document", arguments: creation }, })), ); expect((result.result as { isError: boolean }).isError).toBe(true); expect((result.result as { structuredContent: unknown }).structuredContent).toEqual({ code: "idempotency-conflict", }); }); it("advertises the canonical repository and non-blank channel constraints it enforces", () => { let list = TOOLS.find(tool => tool.name === "list_documents")!; let read = TOOLS.find(tool => tool.name === "read_document")!; expect((list.inputSchema.properties as Record).repository.pattern) .toBe( "^[A-Za-z0-9](?:[A-Za-z0-9]|-(?=[A-Za-z0-9])){0,38}/(?!\\.\\.?$)[A-Za-z0-9._-]{1,100}$", ); expect((read.inputSchema.properties as Record).id.pattern).toBe( "\\S", ); expect((read.inputSchema.properties as Record).id.maxLength) .toBe(128); }); it("does not reveal documents to an unauthenticated caller", async () => { let response = await endpoint()(request({ jsonrpc: "2.0", id: 1, method: "tools/call", params: { name: "list_documents", arguments: { repository: "githubnext/chopin" } }, }, { headers: { authorization: "Bearer denied" } })); expect(response.status).toBe(401); expect(await response.text()).not.toContain(document.title); }); it("reports parse errors and invalid requests with JSON-RPC errors", async () => { let mcp = endpoint(); let malformed = new Request("https://chopin.test/mcp", { method: "POST", headers: { authorization: "Bearer allowed", "content-type": "application/json" }, body: "{", }); expect(await json(await mcp(malformed))).toEqual({ jsonrpc: "2.0", id: null, error: { code: -32700, message: "parse error" }, }); expect(await json(await mcp(request({ jsonrpc: "1.0", id: 4, method: "tools/list" })))).toEqual( { jsonrpc: "2.0", id: 4, error: { code: -32600, message: "invalid request" }, }, ); }); it("rejects declared and streamed request bodies beyond the read-only transport budget", async () => { let mcp = endpoint(); let declared = await mcp( new Request("https://chopin.test/mcp", { method: "POST", headers: { authorization: "Bearer allowed", "content-length": "65537", "content-type": "application/json", }, body: "{}", }), ); let streamed = await mcp( new Request("https://chopin.test/mcp", { method: "POST", headers: { authorization: "Bearer allowed", "content-type": "application/json", }, body: new ReadableStream({ start(controller) { for (let index = 0; index < 3; index++) { controller.enqueue(new Uint8Array(32_768)); } controller.close(); }, }), }), ); for (let response of [declared, streamed]) { expect(response.status).toBe(413); expect(await response.text()).toBe("request too large"); } }); it("rejects non-scalar JSON-RPC ids and scalar initialize or tools-list parameters", async () => { let mcp = endpoint(); for ( let [request_, id] of [ [{ jsonrpc: "2.0", id: { invalid: true }, method: "tools/list" }, null], [{ jsonrpc: "2.0", id: 5, method: "initialize", params: "invalid" }, 5], [{ jsonrpc: "2.0", id: 6, method: "tools/list", params: 1 }, 6], ] ) { expect(await json(await mcp(request(request_)))).toEqual({ jsonrpc: "2.0", id, error: { code: -32600, message: "invalid request" }, }); } }); it("rejects malformed tool arguments and unknown tools without consulting the reader", async () => { let mcp = endpoint(); for ( let [id, name, arguments_, error] of [ [5, "list_documents", { repository: "./chopin" }, "list_documents requires a repository"], [6, "list_documents", { repository: "owner/.." }, "list_documents requires a repository"], [7, "read_document", { id: " \t" }, "read_document requires an id"], [9, "read_document", { id: "x".repeat(129) }, "read_document requires an id"], ] ) { let invalid = await json( await mcp(request({ jsonrpc: "2.0", id, method: "tools/call", params: { name, arguments: arguments_ }, })), ); expect(invalid.error).toEqual({ code: -32602, message: error }); } let unknown = await json( await mcp(request({ jsonrpc: "2.0", id: 8, method: "tools/call", params: { name: "write_document", arguments: {} }, })), ); expect(unknown.error).toEqual({ code: -32601, message: "tool not found" }); }); it("counts read-document ids by JSON Schema characters", async () => { let boundary = await json( await endpoint()(request({ jsonrpc: "2.0", id: 10, method: "tools/call", params: { name: "read_document", arguments: { id: "😀".repeat(128) } }, })), ); expect(boundary.error).toBeUndefined(); expect(boundary.result).toEqual({ content: [], isError: true }); }); it("returns tool-level absence for a missing or inaccessible channel", async () => { let missing = await json( await endpoint()(request({ jsonrpc: "2.0", id: 7, method: "tools/call", params: { name: "read_document", arguments: { id: "missing" } }, })), ); let inaccessible = await json( await handler({ caller: () => "octocat", documents: { async list() { return []; }, async read() { return undefined; }, }, })(request({ jsonrpc: "2.0", id: 8, method: "tools/call", params: { name: "read_document", arguments: { id: document.id } }, })), ); expect(missing.result).toEqual({ content: [], isError: true }); expect(inaccessible.result).toEqual(missing.result); }); it("does not reply to notifications and rejects unknown methods", async () => { let mcp = endpoint(); let notification = await mcp(request({ jsonrpc: "2.0", method: "tools/call", params: { name: "list_documents", arguments: { repository: "githubnext/chopin" } }, })); expect(notification.status).toBe(202); expect(await notification.text()).toBe(""); let unknown = await json( await mcp(request({ jsonrpc: "2.0", id: 8, method: "resources/list", })), ); expect(unknown.error).toEqual({ code: -32601, message: "method not found" }); }); it("negotiates authenticated GET event streams and refuses unsupported methods", async () => { let mcp = endpoint(); let stream = await mcp( new Request("https://chopin.test/mcp", { headers: { authorization: "Bearer allowed", accept: "text/event-stream" }, }), ); expect(stream.status).toBe(200); expect(stream.headers.get("content-type")).toBe("text/event-stream"); let unacceptable = await mcp( new Request("https://chopin.test/mcp", { headers: { authorization: "Bearer allowed", accept: "application/json" }, }), ); expect(unacceptable.status).toBe(406); let unsupported = await mcp( new Request("https://chopin.test/mcp", { method: "PUT", headers: { authorization: "Bearer allowed" }, }), ); expect(unsupported.status).toBe(405); expect(unsupported.headers.get("allow")).toBe("GET, POST"); }); it("honors event-stream Accept quality values", async () => { let mcp = endpoint(); for ( let accept of [ "text/event-stream;q=0", "application/json, text/event-stream; q=0", "text/event-stream;q=0, */*;q=1", "*/*;q=0", ] ) { let response = await mcp( new Request("https://chopin.test/mcp", { headers: { authorization: "Bearer allowed", accept }, }), ); expect(response.status).toBe(406); } let accepted = await mcp( new Request("https://chopin.test/mcp", { headers: { authorization: "Bearer allowed", accept: "text/event-stream;q=0.25" }, }), ); expect(accepted.status).toBe(200); }); });