|
|
@@ -2,6 +2,7 @@ import { describe, expect, test } from "bun:test"
|
|
|
import { Client, InMemoryTransport } from "@modelcontextprotocol/client"
|
|
|
import { Server } from "@modelcontextprotocol/server"
|
|
|
import { McpCatalog } from "@/mcp/catalog"
|
|
|
+import { CLIENT_OPTIONS } from "@/mcp"
|
|
|
import { Effect } from "effect"
|
|
|
|
|
|
const options = { toolCallId: "call_mcp", abortSignal: new AbortController().signal } as any
|
|
|
@@ -141,3 +142,44 @@ test("preserves output schema validation across paginated tool discovery", async
|
|
|
await Promise.all([client.close(), server.close()])
|
|
|
}
|
|
|
})
|
|
|
+
|
|
|
+test("accepts and validates draft-07 tool output schemas", async () => {
|
|
|
+ const server = new Server({ name: "draft-07", version: "1.0.0" }, { capabilities: { tools: {} } })
|
|
|
+ let calls = 0
|
|
|
+ server.setRequestHandler("tools/list", () =>
|
|
|
+ Promise.resolve({
|
|
|
+ tools: [
|
|
|
+ {
|
|
|
+ name: "draft-07-tool",
|
|
|
+ inputSchema: { type: "object" as const },
|
|
|
+ outputSchema: {
|
|
|
+ $schema: "http://json-schema.org/draft-07/schema#",
|
|
|
+ type: "object" as const,
|
|
|
+ properties: { value: { type: "string" } },
|
|
|
+ required: ["value"],
|
|
|
+ },
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ }),
|
|
|
+ )
|
|
|
+ server.setRequestHandler("tools/call", () => {
|
|
|
+ calls++
|
|
|
+ return Promise.resolve({ content: [], structuredContent: { value: calls === 1 ? "valid" : 42 } })
|
|
|
+ })
|
|
|
+
|
|
|
+ const client = new Client({ name: "draft-07-test", version: "1.0.0" }, CLIENT_OPTIONS)
|
|
|
+ const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair()
|
|
|
+ await Promise.all([client.connect(clientTransport), server.connect(serverTransport)])
|
|
|
+
|
|
|
+ try {
|
|
|
+ const tools = await Effect.runPromise(McpCatalog.defs(client))
|
|
|
+ expect(tools?.map((tool) => tool.name)).toEqual(["draft-07-tool"])
|
|
|
+ await expect(client.callTool({ name: "draft-07-tool", arguments: {} })).resolves.toMatchObject({
|
|
|
+ structuredContent: { value: "valid" },
|
|
|
+ })
|
|
|
+ await expect(client.callTool({ name: "draft-07-tool", arguments: {} })).rejects.toThrow(/output schema/i)
|
|
|
+ expect(calls).toBe(2)
|
|
|
+ } finally {
|
|
|
+ await Promise.all([client.close(), server.close()])
|
|
|
+ }
|
|
|
+})
|