diff --git a/Sources/MCP/Base/Messages.swift b/Sources/MCP/Base/Messages.swift index 8214a702..25c8167e 100644 --- a/Sources/MCP/Base/Messages.swift +++ b/Sources/MCP/Base/Messages.swift @@ -104,6 +104,12 @@ public struct Request: Hashable, Identifiable, Codable, Sendable { // If params field is missing, use Empty params = Empty() as! M.Parameters } + } else if M.Parameters.self == Value.self { + // allow missing parameter for Value parameters. This is important for AnyRequest to be able to + // decode a message that does have an `id` but does not have a `params` object. Otherwise the + // incoming message would fail to decode and would instead decode as an AnyNotification, despite + // the `id` parameter. + params = try container.decodeIfPresent(M.Parameters.self, forKey: .params) ?? (Value.null as! M.Parameters) } else { params = try container.decode(M.Parameters.self, forKey: .params) } diff --git a/Sources/MCP/Base/Utilities/Ping.swift b/Sources/MCP/Base/Utilities/Ping.swift index e526ad4e..e64f0440 100644 --- a/Sources/MCP/Base/Utilities/Ping.swift +++ b/Sources/MCP/Base/Utilities/Ping.swift @@ -1,5 +1,7 @@ /// The Model Context Protocol includes an optional ping mechanism that allows either party to verify that their counterpart is still responsive and the connection is alive. /// - SeeAlso: https://spec.modelcontextprotocol.io/specification/2024-11-05/basic/utilities/ping public enum Ping: Method { + public typealias Parameters = Empty + public typealias Result = Value public static let name: String = "ping" } diff --git a/Sources/MCP/Server/Server.swift b/Sources/MCP/Server/Server.swift index 495d7680..efbcbdb4 100644 --- a/Sources/MCP/Server/Server.swift +++ b/Sources/MCP/Server/Server.swift @@ -401,8 +401,11 @@ public actor Server { return result } - // Ping - withMethodHandler(Ping.self) { _ in return Empty() } + // Ping. Specification shows empty dictionary as the response: + // https://spec.modelcontextprotocol.io/specification/2024-11-05/basic/utilities/ping/ + withMethodHandler(Ping.self) { params in + return .object([:]) + } } private func setInitialState( diff --git a/Sources/MCP/Server/Tools.swift b/Sources/MCP/Server/Tools.swift index aacb282b..5bb89a5b 100644 --- a/Sources/MCP/Server/Tools.swift +++ b/Sources/MCP/Server/Tools.swift @@ -118,7 +118,11 @@ public struct Tool: Hashable, Codable, Sendable { public enum ListTools: Method { public static let name = "tools/list" - public struct Parameters: Hashable, Codable, Sendable { + // Specification allows optional cursor parameter: + // https://spec.modelcontextprotocol.io/specification/2024-11-05/server/tools/ + public typealias Parameters = Cursor? + + public struct Cursor: Hashable, Codable, Sendable { public let cursor: String? public init(cursor: String? = nil) {