import { fromJsonSchema } from "@modelcontextprotocol/server"; import { normalizeRuntimeMessage } from "../../src/runtime/opencode2-events.js"; import { expect, it } from "bun:test"; import { resolveMatchingNativeCall } from "../../src/mcp/native-call-identity.js"; import { allowedQueryTools } from "../../src/runtime/query-mcp-policy.js"; import { QUERY_MCP_AUTOALLOW_TOOL_IDS } from "../../src/runtime/product-mcp-tools.js"; const part = (callID: string, status = "running", input: unknown = { duration: 60 }) => ({ type: "tool", tool: "mcp_tjwater_run_simulation", callID, state: { status, input } }); it("resolves only an exact active persisted native call and fails closed on ambiguity", () => { expect(resolveMatchingNativeCall([{ parts: [part("old", "completed"), part("current")] }], "run_simulation", { duration: 60 })).toBe("current"); expect(resolveMatchingNativeCall([{ parts: [part("current")] }], "run_simulation", { duration: 61 })).toBeNull(); expect(resolveMatchingNativeCall([{ parts: [part("a"), part("b")] }], "run_simulation", { duration: 60 })).toBeNull(); }); it("allows readers only job reads and never autoallows cancellation", () => { const context = { sessionId: "s", clientSessionId: "c", actorKey: "a", projectKey: "p", projectId: "p", traceId: "t", purpose: "task_execution" as const }; const tools = allowedQueryTools(context, true); for (const name of ["get_calculation_job", "get_calculation_result", "list_calculation_jobs"]) expect(tools).toContain(`mcp_tjwater_${name}`); expect(tools).not.toContain("mcp_tjwater_cancel_calculation_job"); expect(tools).not.toContain("mcp_tjwater_run_simulation"); expect(QUERY_MCP_AUTOALLOW_TOOL_IDS).not.toContain("mcp_tjwater_cancel_calculation_job"); }); it("matches omitted MCP defaults against the actual native message-list normalizer", async () => { const schema = fromJsonSchema>({ type: "object", additionalProperties: false, properties: { timeout_seconds: { type: "integer", default: 120 }, dry_run: { type: "boolean", default: true } }, }); for (const input of [{}, { timeout_seconds: 900 }, { dry_run: false }]) { const validated = await schema["~standard"].validate(input); expect(validated.issues).toBeUndefined(); if (!("value" in validated)) throw new Error("MCP input validation failed"); expect(validated.value).toEqual(input); const native = { id: "assistant-message", type: "assistant", time: { created: 1 }, content: [{ type: "tool", id: "native-call", name: "mcp_tjwater_run_simulation", time: { created: 1 }, state: { status: "running", input } }], } as unknown as Parameters[0]; const messages = [normalizeRuntimeMessage(native, "native-session")]; expect(resolveMatchingNativeCall(messages, "run_simulation", validated.value!)).toBe("native-call"); expect(resolveMatchingNativeCall(messages, "run_simulation", { ...validated.value, arbitrary_parameter: true })).toBeNull(); } });