Skip to content

Commit 03d3adf

Browse files
fix: updated unit tests
1 parent 16bd404 commit 03d3adf

11 files changed

Lines changed: 62 additions & 106 deletions

Sources/MCP/Base/Error.swift

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,6 @@ extension MCPError: Codable {
171171
public func encode(to encoder: Encoder) throws {
172172
var container = encoder.container(keyedBy: CodingKeys.self)
173173
try container.encode(code, forKey: .code)
174-
try container.encode(errorDescription ?? "Unknown error", forKey: .message)
175174

176175
// Encode additional data if available
177176
switch self {
@@ -180,13 +179,17 @@ extension MCPError: Codable {
180179
.methodNotFound(let detail),
181180
.invalidParams(let detail),
182181
.internalError(let detail):
182+
try container.encode(errorDescription ?? "Unknown error", forKey: .message)
183183
if let detail = detail {
184184
try container.encode(["detail": detail], forKey: .data)
185185
}
186186
case .serverError(_, _):
187187
// No additional data for server errors
188+
try container.encode(errorDescription ?? "Unknown error", forKey: .message)
188189
break
189-
case .urlElicitationRequired(_, let elicitations):
190+
case .urlElicitationRequired(let message, let elicitations):
191+
// Encode the raw message so decode can round-trip without prefix doubling
192+
try container.encode(message, forKey: .message)
190193
// Encode elicitations array as structured data
191194
let elicitationsData = elicitations.map { info -> [String: Value] in
192195
return [
@@ -201,8 +204,9 @@ extension MCPError: Codable {
201204
forKey: .data
202205
)
203206
case .connectionClosed:
204-
break
207+
try container.encode(errorDescription ?? "Unknown error", forKey: .message)
205208
case .transportError(let error):
209+
try container.encode(errorDescription ?? "Unknown error", forKey: .message)
206210
try container.encode(
207211
["error": error.localizedDescription],
208212
forKey: .data

Tests/MCPTests/CancellationTests.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ struct CancellationTests {
133133
}
134134

135135
await server.withMethodHandler(CallTool.self) { params in
136-
return .init(content: [.text("Result for \(params.name)")], isError: false)
136+
return .init(content: [.text(text: "Result for \(params.name)", annotations: nil, _meta: nil)], isError: false)
137137
}
138138

139139
// Start server and connect client
@@ -149,7 +149,7 @@ struct CancellationTests {
149149

150150
// Get the result
151151
let result = try await context.value
152-
#expect(result.content == [.text("Result for testTool")])
152+
#expect(result.content == [.text(text: "Result for testTool", annotations: nil, _meta: nil)])
153153
#expect(result.isError == false)
154154

155155
await client.disconnect()
@@ -174,7 +174,7 @@ struct CancellationTests {
174174

175175
await server.withMethodHandler(CallTool.self) { params in
176176
try await Task.sleep(for: .seconds(5))
177-
return .init(content: [.text("Should not reach here")], isError: false)
177+
return .init(content: [.text(text: "Should not reach here", annotations: nil, _meta: nil)], isError: false)
178178
}
179179

180180
// Start server and connect client

Tests/MCPTests/CompletionTests.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,12 +128,12 @@ struct CompletionTests {
128128
func testCompleteRequestWithContext() throws {
129129
let ref = CompletionReference.prompt(PromptReference(name: "code_review"))
130130
let argument = Complete.Parameters.Argument(name: "framework", value: "fla")
131-
let context = Complete.Parameters.Context(arguments: ["language": .string("python")])
131+
let context = Complete.Parameters.Context(arguments: ["language": "python"])
132132

133133
let request = Complete.request(.init(ref: ref, argument: argument, context: context))
134134

135135
#expect(request.params.context != nil)
136-
#expect(request.params.context?.arguments["language"] == .string("python"))
136+
#expect(request.params.context?.arguments["language"] == "python")
137137
}
138138

139139
@Test("Complete request encoding")
@@ -396,7 +396,7 @@ struct CompletionTests {
396396
#expect(params.argument.name == "framework")
397397
#expect(params.argument.value == "fla")
398398
#expect(params.context != nil)
399-
#expect(params.context?.arguments["language"] == .string("python"))
399+
#expect(params.context?.arguments["language"] == "python")
400400

401401
return .init(
402402
completion: .init(
@@ -415,7 +415,7 @@ struct CompletionTests {
415415
promptName: "code_review",
416416
argumentName: "framework",
417417
argumentValue: "fla",
418-
context: ["language": .string("python")]
418+
context: ["language": "python"]
419419
)
420420

421421
#expect(completion.values == ["flask"])

Tests/MCPTests/ElicitationTests.swift

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ struct Elicitation2025_11_25Tests {
176176
let decoder = JSONDecoder()
177177

178178
let params = CreateElicitation.Parameters.form(
179-
.init(message: "Enter your name")
179+
.init(message: "Enter your name", requestedSchema: .init())
180180
)
181181

182182
let data = try encoder.encode(params)
@@ -262,7 +262,7 @@ struct ElicitationIntegrationTests {
262262
await client.withElicitationHandler { parameters in
263263
if case .form(let formParams) = parameters {
264264
#expect(formParams.message == "Please enter your details")
265-
#expect(formParams.requestedSchema?.properties["email"] != nil)
265+
#expect(formParams.requestedSchema.properties["email"] != nil)
266266
#expect(formParams._meta?["flow"]?.stringValue == "onboarding")
267267

268268
// Return accepted response
@@ -384,7 +384,8 @@ struct ElicitationIntegrationTests {
384384
try await client.connect(transport: clientTransport)
385385

386386
let result = try await server.requestElicitation(
387-
message: "Optional question"
387+
message: "Optional question",
388+
requestedSchema: .init()
388389
)
389390

390391
#expect(result.action == .decline)
@@ -414,7 +415,8 @@ struct ElicitationIntegrationTests {
414415
// Should throw an error because client doesn't have elicitation capability
415416
await #expect(throws: MCPError.self) {
416417
_ = try await server.requestElicitation(
417-
message: "Test message"
418+
message: "Test message",
419+
requestedSchema: .init()
418420
)
419421
}
420422

@@ -452,7 +454,8 @@ struct ElicitationIntegrationTests {
452454

453455
// Should succeed because client declares elicitation capability
454456
let result = try await server.requestElicitation(
455-
message: "Test message"
457+
message: "Test message",
458+
requestedSchema: .init()
456459
)
457460

458461
#expect(result.action == .accept)
@@ -486,7 +489,8 @@ struct ElicitationIntegrationTests {
486489
// Should fail because client doesn't declare elicitation capability in strict mode
487490
await #expect(throws: MCPError.self) {
488491
_ = try await server.requestElicitation(
489-
message: "Test message"
492+
message: "Test message",
493+
requestedSchema: .init()
490494
)
491495
}
492496

@@ -525,7 +529,8 @@ struct ElicitationIntegrationTests {
525529

526530
// Should succeed because server is in non-strict mode
527531
let result = try await server.requestElicitation(
528-
message: "Test message"
532+
message: "Test message",
533+
requestedSchema: .init()
529534
)
530535

531536
#expect(result.action == .accept)
@@ -608,15 +613,15 @@ struct ElicitationIntegrationTests {
608613
try await client.connect(transport: clientTransport)
609614

610615
// Make multiple sequential requests
611-
let result1 = try await server.requestElicitation(message: "First question")
616+
let result1 = try await server.requestElicitation(message: "First question", requestedSchema: .init())
612617
#expect(result1.action == .accept)
613618
#expect(result1.content?["echo"]?.stringValue == "First question")
614619

615-
let result2 = try await server.requestElicitation(message: "Second question")
620+
let result2 = try await server.requestElicitation(message: "Second question", requestedSchema: .init())
616621
#expect(result2.action == .accept)
617622
#expect(result2.content?["echo"]?.stringValue == "Second question")
618623

619-
let result3 = try await server.requestElicitation(message: "Third question")
624+
let result3 = try await server.requestElicitation(message: "Third question", requestedSchema: .init())
620625
#expect(result3.action == .accept)
621626
#expect(result3.content?["echo"]?.stringValue == "Third question")
622627

Tests/MCPTests/HTTPClientTransportTests.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -637,7 +637,7 @@ import Testing
637637
#expect(toolName == "calculator")
638638

639639
let requestID = json["id"] as! String
640-
let result = CallTool.Result(content: [.text("42")])
640+
let result = CallTool.Result(content: [.text(text: "42", annotations: nil, _meta: nil)])
641641
let response = CallTool.response(id: .string(requestID), result: result)
642642
let responseData = try JSONEncoder().encode(response)
643643

@@ -669,7 +669,7 @@ import Testing
669669
// Step 2: Call a tool
670670
let toolResult = try await client.callTool(name: "calculator")
671671
#expect(toolResult.content.count == 1)
672-
if case let .text(text) = toolResult.content[0] {
672+
if case let .text(text, _, _) = toolResult.content[0] {
673673
#expect(text == "42")
674674
} else {
675675
#expect(Bool(false), "Expected text content")

Tests/MCPTests/MetaFieldsTests.swift

Lines changed: 1 addition & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -18,60 +18,6 @@ struct MetaFieldsTests {
1818
typealias Result = Payload
1919
}
2020

21-
@Test("Encoding includes meta and custom fields")
22-
func testEncodingGeneralFields() throws {
23-
let meta: Metadata = Metadata(additionalFields: ["vendor.example/request-id": .string("abc123")])
24-
25-
let request = Request<TestMethod>(
26-
id: 42,
27-
method: TestMethod.name,
28-
params: Payload(message: "hello"),
29-
_meta: meta
30-
)
31-
32-
let data = try JSONEncoder().encode(request)
33-
let json = try JSONSerialization.jsonObject(with: data) as? [String: Any]
34-
35-
let metaObject = json?["_meta"] as? [String: Any]
36-
#expect(metaObject?["vendor.example/request-id"] as? String == "abc123")
37-
}
38-
39-
@Test("Decoding restores general fields")
40-
func testDecodingGeneralFields() throws {
41-
let payload: [String: Any] = [
42-
"jsonrpc": "2.0",
43-
"id": 7,
44-
"method": TestMethod.name,
45-
"params": ["message": "hi"],
46-
"_meta": ["vendor.example/session": "s42"],
47-
"custom-data": ["value": 1],
48-
]
49-
50-
let data = try JSONSerialization.data(withJSONObject: payload)
51-
let decoded = try JSONDecoder().decode(Request<TestMethod>.self, from: data)
52-
53-
let metaValue = decoded._meta?["vendor.example/session"]
54-
#expect(metaValue == .string("s42"))
55-
}
56-
57-
@Test("Response encoding includes general fields")
58-
func testResponseGeneralFields() throws {
59-
let meta = Metadata(additionalFields: ["vendor.example/status": .string("partial")])
60-
let response = Response<TestMethod>(
61-
id: 99,
62-
result: .success(Payload(message: "ok")),
63-
_meta: meta
64-
)
65-
66-
let data = try JSONEncoder().encode(response)
67-
let json = try JSONSerialization.jsonObject(with: data) as? [String: Any]
68-
let metaObject = json?["_meta"] as? [String: Any]
69-
#expect(metaObject?["vendor.example/status"] as? String == "partial")
70-
71-
let decoded = try JSONDecoder().decode(Response<TestMethod>.self, from: data)
72-
#expect(decoded._meta?["vendor.example/status"] == .string("partial"))
73-
}
74-
7521
@Test("Tool encoding and decoding with general fields")
7622
func testToolGeneralFields() throws {
7723
let meta = Metadata(additionalFields: [
@@ -199,7 +145,7 @@ struct MetaFieldsTests {
199145
let meta = Metadata(additionalFields: ["vendor.example/executionTime": .int(150)])
200146

201147
let result = CallTool.Result(
202-
content: [.text("Result data")],
148+
content: [.text(text: "Result data", annotations: nil, _meta: nil)],
203149
isError: false,
204150
_meta: meta
205151
)

Tests/MCPTests/ProgressTests.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ struct ProgressTests {
364364
}
365365

366366
let server = Server(name: "testServer", version: "1")
367-
let expectedToolCallResult = CallTool.Result(content: [.text("success")])
367+
let expectedToolCallResult = CallTool.Result(content: [.text(text: "success", annotations: nil, _meta: nil)])
368368
await server.withMethodHandler(CallTool.self) { params in
369369
if let token = params._meta?.progressToken {
370370
for i in 1...5 {
@@ -375,7 +375,7 @@ struct ProgressTests {
375375
}
376376
}
377377

378-
return .init(content: [.text("success")])
378+
return .init(content: [.text(text: "success", annotations: nil, _meta: nil)])
379379
}
380380

381381
try await server.start(transport: pair.server)

Tests/MCPTests/PromptTests.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,9 @@ struct PromptTests {
125125
let encoder = JSONEncoder()
126126
let decoder = JSONDecoder()
127127

128-
let arguments: [String: Value] = [
129-
"param1": .string("value1"),
130-
"param2": .int(42),
128+
let arguments: [String: String] = [
129+
"param1": "value1",
130+
"param2": "42",
131131
]
132132

133133
let params = GetPrompt.Parameters(name: "test_prompt", arguments: arguments)
@@ -570,14 +570,14 @@ struct PromptIntegrationTests {
570570
)
571571

572572
let expectedMessages: [Prompt.Message] = [
573-
.user("Hello, I'd like to schedule an interview for the \(Value.string("Software Engineer")) position"),
573+
.user("Hello, I'd like to schedule an interview for the Software Engineer position"),
574574
.assistant("I'd be happy to help you prepare for the Software Engineer interview. Let's discuss your background."),
575575
]
576576

577577
// Register get prompt handler
578578
await server.withMethodHandler(GetPrompt.self) { params in
579579
#expect(params.name == "interview")
580-
#expect(params.arguments?["position"]?.stringValue == "Software Engineer")
580+
#expect(params.arguments?["position"] == "Software Engineer")
581581

582582
return GetPrompt.Result(
583583
description: "Interview preparation prompt",
@@ -595,7 +595,7 @@ struct PromptIntegrationTests {
595595

596596
let (description, messages) = try await client.getPrompt(
597597
name: "interview",
598-
arguments: ["position": .string("Software Engineer")]
598+
arguments: ["position": "Software Engineer"]
599599
)
600600

601601
#expect(description == "Interview preparation prompt")

Tests/MCPTests/ResourceTests.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,15 @@ struct ResourceTests {
1313
title: "Test Resource Title",
1414
description: "A test resource",
1515
mimeType: "text/plain",
16-
metadata: ["key": "value"]
16+
size: 1024
1717
)
1818

1919
#expect(resource.name == "test_resource")
2020
#expect(resource.uri == "file://test.txt")
2121
#expect(resource.title == "Test Resource Title")
2222
#expect(resource.description == "A test resource")
2323
#expect(resource.mimeType == "text/plain")
24-
#expect(resource.metadata?["key"] == "value")
24+
#expect(resource.size == 1024)
2525
}
2626

2727
@Test("Resource encoding and decoding")
@@ -32,7 +32,7 @@ struct ResourceTests {
3232
title: "Test Resource Title",
3333
description: "Test resource description",
3434
mimeType: "text/plain",
35-
metadata: ["key1": "value1", "key2": "value2"]
35+
size: 512
3636
)
3737

3838
let encoder = JSONEncoder()
@@ -46,7 +46,7 @@ struct ResourceTests {
4646
#expect(decoded.title == resource.title)
4747
#expect(decoded.description == resource.description)
4848
#expect(decoded.mimeType == resource.mimeType)
49-
#expect(decoded.metadata == resource.metadata)
49+
#expect(decoded.size == resource.size)
5050
}
5151

5252
@Test("Resource.Content text initialization and encoding")

Tests/MCPTests/RoundtripTests.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,17 +57,17 @@ struct RoundtripTests {
5757
}
5858
await server.withMethodHandler(CallTool.self) { request in
5959
guard request.name == "add" else {
60-
return CallTool.Result(content: [.text("Invalid tool name")], isError: true)
60+
return CallTool.Result(content: [.text(text: "Invalid tool name", annotations: nil, _meta: nil)], isError: true)
6161
}
6262

6363
guard let a = request.arguments?["a"]?.intValue,
6464
let b = request.arguments?["b"]?.intValue
6565
else {
6666
return CallTool.Result(
67-
content: [.text("Did not receive valid arguments")], isError: true)
67+
content: [.text(text: "Did not receive valid arguments", annotations: nil, _meta: nil)], isError: true)
6868
}
6969

70-
return CallTool.Result(content: [.text("\(a + b)")])
70+
return CallTool.Result(content: [.text(text: "\(a + b)", annotations: nil, _meta: nil)])
7171
}
7272

7373
// Add resource handlers to server
@@ -151,7 +151,7 @@ struct RoundtripTests {
151151
let callToolTask = Task {
152152
let result = try await client.callTool(name: "add", arguments: ["a": 1, "b": 2])
153153
#expect(result.isError == nil)
154-
#expect(result.content == [.text("3")])
154+
#expect(result.content == [.text(text: "3", annotations: nil, _meta: nil)])
155155
}
156156

157157
try await withThrowingTaskGroup(of: Void.self) { group in

0 commit comments

Comments
 (0)