175 lines
No EOL
5.4 KiB
Swift
175 lines
No EOL
5.4 KiB
Swift
import Foundation
|
|
|
|
/// Tool metadata
|
|
public struct Tool: Codable {
|
|
public let name: String
|
|
public let description: String?
|
|
public let inputSchema: [String: Any]?
|
|
|
|
enum CodingKeys: String, CodingKey {
|
|
case name
|
|
case description
|
|
case inputSchema
|
|
}
|
|
|
|
public init(name: String, description: String? = nil, inputSchema: [String: Any]? = nil) {
|
|
self.name = name
|
|
self.description = description
|
|
self.inputSchema = inputSchema
|
|
}
|
|
|
|
public init(from decoder: Decoder) throws {
|
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
|
name = try container.decode(String.self, forKey: .name)
|
|
description = try container.decodeIfPresent(String.self, forKey: .description)
|
|
inputSchema = try container.decodeIfPresent([String: Any].self, forKey: .inputSchema)
|
|
}
|
|
|
|
public func encode(to encoder: Encoder) throws {
|
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
|
try container.encode(name, forKey: .name)
|
|
try container.encodeIfPresent(description, forKey: .description)
|
|
if let schema = inputSchema {
|
|
try container.encode(schema, forKey: .inputSchema)
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Tool request types
|
|
public struct ListToolsRequest: MCPRequest {
|
|
public let jsonrpc: String = "2.0"
|
|
public let id: String
|
|
public let method: String = "tools/list"
|
|
|
|
public init(id: String = UUID().uuidString) {
|
|
self.id = id
|
|
}
|
|
}
|
|
|
|
public struct CallToolRequest: MCPRequest {
|
|
public let jsonrpc: String = "2.0"
|
|
public let id: String
|
|
public let method: String = "tools/call"
|
|
public let params: CallToolParams
|
|
|
|
public struct CallToolParams: Codable {
|
|
public let name: String
|
|
public let arguments: [String: Any]?
|
|
|
|
enum CodingKeys: String, CodingKey {
|
|
case name
|
|
case arguments
|
|
}
|
|
|
|
public init(name: String, arguments: [String: Any]? = nil) {
|
|
self.name = name
|
|
self.arguments = arguments
|
|
}
|
|
|
|
public init(from decoder: Decoder) throws {
|
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
|
name = try container.decode(String.self, forKey: .name)
|
|
arguments = try container.decodeIfPresent([String: Any].self, forKey: .arguments)
|
|
}
|
|
|
|
public func encode(to encoder: Encoder) throws {
|
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
|
try container.encode(name, forKey: .name)
|
|
if let args = arguments {
|
|
try container.encode(args, forKey: .arguments)
|
|
}
|
|
}
|
|
}
|
|
|
|
public init(id: String = UUID().uuidString, name: String, arguments: [String: Any]? = nil) {
|
|
self.id = id
|
|
self.params = CallToolParams(name: name, arguments: arguments)
|
|
}
|
|
}
|
|
|
|
/// Tool response types
|
|
public struct ListToolsResponse: MCPResponse {
|
|
public let jsonrpc: String = "2.0"
|
|
public let id: String
|
|
public let result: ListToolsResult
|
|
|
|
public struct ListToolsResult: Codable {
|
|
public let tools: [Tool]
|
|
}
|
|
}
|
|
|
|
public struct CallToolResponse: MCPResponse {
|
|
public let jsonrpc: String = "2.0"
|
|
public let id: String
|
|
public let result: CallToolResult
|
|
|
|
public struct CallToolResult: Codable {
|
|
public let content: [ToolContent]
|
|
public let isError: Bool?
|
|
|
|
public init(content: [ToolContent], isError: Bool? = nil) {
|
|
self.content = content
|
|
self.isError = isError
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Tool content types
|
|
public enum ToolContent: Codable {
|
|
case text(String)
|
|
case image(ImageContent)
|
|
|
|
private enum CodingKeys: String, CodingKey {
|
|
case type
|
|
case text
|
|
case image
|
|
}
|
|
|
|
public init(from decoder: Decoder) throws {
|
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
|
let type = try container.decode(String.self, forKey: .type)
|
|
|
|
switch type {
|
|
case "text":
|
|
let text = try container.decode(String.self, forKey: .text)
|
|
self = .text(text)
|
|
case "image":
|
|
let image = try container.decode(ImageContent.self, forKey: .image)
|
|
self = .image(image)
|
|
default:
|
|
throw DecodingError.dataCorruptedError(forKey: .type, in: container, debugDescription: "Unknown tool content type")
|
|
}
|
|
}
|
|
|
|
public func encode(to encoder: Encoder) throws {
|
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
|
|
|
switch self {
|
|
case .text(let text):
|
|
try container.encode("text", forKey: .type)
|
|
try container.encode(text, forKey: .text)
|
|
case .image(let image):
|
|
try container.encode("image", forKey: .type)
|
|
try container.encode(image, forKey: .image)
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Image content type
|
|
public struct ImageContent: Codable {
|
|
public let data: String
|
|
public let mimeType: String
|
|
public let metadata: [String: String]?
|
|
|
|
public init(data: String, mimeType: String, metadata: [String: String]? = nil) {
|
|
self.data = data
|
|
self.mimeType = mimeType
|
|
self.metadata = metadata
|
|
}
|
|
}
|
|
|
|
/// Tool notification types
|
|
public struct ToolListChangedNotification: MCPNotification {
|
|
public let jsonrpc: String = "2.0"
|
|
public let method: String = "notifications/tools/list_changed"
|
|
} |