* Rename Error to MCPError * Conform MCPError to Swift.Error * Use unqualified Error instead of Swift.Error * Use unqualified MCPError instead of MCP.MCPError * Rename file back to Error.swift * Introduce top-level MCP namespace with nested Error typealias to provide deprecation notice for existing usage of MCP.Error * Fix markup for MCP enum warning
143 lines
4.5 KiB
Swift
143 lines
4.5 KiB
Swift
import Foundation
|
|
import Testing
|
|
|
|
@testable import MCP
|
|
|
|
@Suite("Server Tests")
|
|
struct ServerTests {
|
|
@Test("Start and stop server")
|
|
func testServerStartAndStop() async throws {
|
|
let transport = MockTransport()
|
|
let server = Server(name: "TestServer", version: "1.0")
|
|
|
|
#expect(await transport.isConnected == false)
|
|
try await server.start(transport: transport)
|
|
#expect(await transport.isConnected == true)
|
|
await server.stop()
|
|
#expect(await transport.isConnected == false)
|
|
}
|
|
|
|
@Test("Initialize request handling")
|
|
func testServerHandleInitialize() async throws {
|
|
let transport = MockTransport()
|
|
|
|
// Queue an initialize request
|
|
try await transport.queue(
|
|
request: Initialize.request(
|
|
.init(
|
|
protocolVersion: Version.latest,
|
|
capabilities: .init(),
|
|
clientInfo: .init(name: "TestClient", version: "1.0")
|
|
)
|
|
))
|
|
|
|
// Start the server
|
|
let server: Server = Server(
|
|
name: "TestServer",
|
|
version: "1.0"
|
|
)
|
|
try await server.start(transport: transport)
|
|
|
|
// Wait for message processing and response
|
|
try await Task.sleep(nanoseconds: 10_000_000) // 10ms
|
|
|
|
#expect(await transport.sentMessages.count == 1)
|
|
|
|
let messages = await transport.sentMessages
|
|
if let response = messages.first {
|
|
#expect(response.contains("serverInfo"))
|
|
}
|
|
|
|
// Clean up
|
|
await server.stop()
|
|
await transport.disconnect()
|
|
}
|
|
|
|
@Test("Initialize hook - successful")
|
|
func testInitializeHookSuccess() async throws {
|
|
let transport = MockTransport()
|
|
|
|
actor TestState {
|
|
var hookCalled = false
|
|
func setHookCalled() { hookCalled = true }
|
|
func wasHookCalled() -> Bool { hookCalled }
|
|
}
|
|
|
|
let state = TestState()
|
|
let server = Server(name: "TestServer", version: "1.0")
|
|
|
|
// Start with the hook directly
|
|
try await server.start(transport: transport) { clientInfo, capabilities in
|
|
#expect(clientInfo.name == "TestClient")
|
|
#expect(clientInfo.version == "1.0")
|
|
await state.setHookCalled()
|
|
}
|
|
|
|
// Wait for server to initialize
|
|
try await Task.sleep(for: .milliseconds(10))
|
|
|
|
// Queue an initialize request
|
|
try await transport.queue(
|
|
request: Initialize.request(
|
|
.init(
|
|
protocolVersion: Version.latest,
|
|
capabilities: .init(),
|
|
clientInfo: .init(name: "TestClient", version: "1.0")
|
|
)
|
|
))
|
|
|
|
// Wait for message processing and hook execution
|
|
try await Task.sleep(for: .milliseconds(500))
|
|
|
|
#expect(await state.wasHookCalled() == true)
|
|
#expect(await transport.sentMessages.count >= 1)
|
|
|
|
let messages = await transport.sentMessages
|
|
if let response = messages.first {
|
|
#expect(response.contains("serverInfo"))
|
|
}
|
|
|
|
await server.stop()
|
|
await transport.disconnect()
|
|
}
|
|
|
|
@Test("Initialize hook - rejection")
|
|
func testInitializeHookRejection() async throws {
|
|
let transport = MockTransport()
|
|
|
|
let server = Server(name: "TestServer", version: "1.0")
|
|
|
|
try await server.start(transport: transport) { clientInfo, _ in
|
|
if clientInfo.name == "BlockedClient" {
|
|
throw MCPError.invalidRequest("Client not allowed")
|
|
}
|
|
}
|
|
|
|
// Wait for server to initialize
|
|
try await Task.sleep(nanoseconds: 10_000_000) // 10ms
|
|
|
|
// Queue an initialize request from blocked client
|
|
try await transport.queue(
|
|
request: Initialize.request(
|
|
.init(
|
|
protocolVersion: Version.latest,
|
|
capabilities: .init(),
|
|
clientInfo: .init(name: "BlockedClient", version: "1.0")
|
|
)
|
|
))
|
|
|
|
// Wait for message processing
|
|
try await Task.sleep(nanoseconds: 200_000_000) // 200ms
|
|
|
|
#expect(await transport.sentMessages.count >= 1)
|
|
|
|
let messages = await transport.sentMessages
|
|
if let response = messages.first {
|
|
#expect(response.contains("error"))
|
|
#expect(response.contains("Client not allowed"))
|
|
}
|
|
|
|
await server.stop()
|
|
await transport.disconnect()
|
|
}
|
|
}
|