1import { assert, describe, it } from "@effect/vitest"
2import { Schema } from "effect"
3import * as McpSchema from "effect/ai/McpSchema"
4
5describe("McpSchema", () => {
6 it("should preserve custom metadata when a request is decoded and encoded", () => {
7 const decode = Schema.decodeUnknownSync(McpSchema.RequestMeta)
8 const encode = Schema.encodeSync(McpSchema.RequestMeta)
9 for (const progress of [{}, { progressToken: "progress-1" }, { progressToken: 1 }]) {
10 const request = {
11 _meta: { ...progress, marker: "request", custom: { values: [null, true, 42, "value"] } }
12 }
13 assert.deepStrictEqual(encode(decode(request)), request)
14 }
15 })
16
17 const decodeCreateMessage = Schema.decodeUnknownSync(McpSchema.CreateMessage.payloadSchema)
18
19 it("allows create-message metadata to be omitted", () => {
20 assert.doesNotThrow(() => decodeCreateMessage({ messages: [], maxTokens: 1 }))
21 })
22
23 it("requires create-message metadata to be an object", () => {
24 assert.throws(() => decodeCreateMessage({ messages: [], maxTokens: 1, metadata: "invalid" }))
25 })
26
27 // SEP-1330: https://modelcontextprotocol.io/seps/1330-elicitation-enum-schema-improvements-and-standards
28 // Conformance: elicitation-sep1330-enums
29 it("should preserve every November elicitation enum form when decoding a form request", () => {
30 const decoded = Schema.decodeUnknownSync(McpSchema.ElicitRequestFormParams)({
31 mode: "form",
32 message: "Choose values",
33 requestedSchema: {
34 type: "object",
35 properties: {
36 untitled: { type: "string", enum: ["one", "two"] },
37 titled: { type: "string", oneOf: [{ const: "one", title: "One" }] },
38 legacy: { type: "string", enum: ["one"], enumNames: ["One"] }
39 }
40 }
41 })
42
43 assert.deepStrictEqual(JSON.parse(JSON.stringify(decoded.requestedSchema.properties)), {
44 untitled: { type: "string", enum: ["one", "two"] },
45 titled: { type: "string", oneOf: [{ const: "one", title: "One" }] },
46 legacy: { type: "string", enum: ["one"], enumNames: ["One"] }
47 })
48 })
49
50 it("round-trips an implementation with icons", () => {
51 const implementation = { name: "server", version: "1.0.0", icons: [{ src: "https://example.com/icon.png" }] }
52 assert.deepStrictEqual(
53 Schema.encodeSync(McpSchema.Implementation)(Schema.decodeUnknownSync(McpSchema.Implementation)(implementation)),
54 implementation
55 )
56 })
57})