Files
CxIDE/Agent/MCPTypes.swift
T
cx-git-agent c118996746 feat: CxIDE v1 — native macOS SwiftUI IDE with agentic AI assistant
- SwiftUI macOS app with C++17 code analysis engine (ObjC++ bridge)
- Agentic AI loop: LLM plans → tool calls → execution → feedback loop
- 15 agent tools: file ops, terminal, git, xcode build, code intel
- 7 persistent terminal tools with background session management
- Chat sidebar with agent step rendering and auto-apply
- NVIDIA NIM API integration (Llama 3.3 70B default)
- OpenAI tool_calls format with prompt-based fallback
- Code editor with syntax highlighting and multi-tab support
- File tree, console view, terminal view
- Git integration and workspace management
2026-04-21 16:05:52 -05:00

179 lines
5.3 KiB
Swift

// MCPTypes.swift
// CxSwiftAgent MCP Protocol Types
//
// JSON-RPC 2.0 + MCP 2025-03-26 data types.
// Zero external dependencies.
import Foundation
// MARK: - JSON-RPC 2.0
struct JsonRpcRequest: Codable, Sendable {
let jsonrpc: String
let method: String
let params: [String: AnyCodable]?
let id: AnyCodable?
var isNotification: Bool { id == nil }
}
struct JsonRpcResponse: Codable, Sendable {
let jsonrpc: String
let result: AnyCodable?
let error: JsonRpcError?
let id: AnyCodable?
static func success(id: AnyCodable?, result: Any) -> JsonRpcResponse {
JsonRpcResponse(jsonrpc: "2.0", result: AnyCodable(result), error: nil, id: id)
}
static func error(id: AnyCodable?, code: Int, message: String, data: Any? = nil) -> JsonRpcResponse {
let errData = data.map { AnyCodable($0) }
return JsonRpcResponse(jsonrpc: "2.0", result: nil,
error: JsonRpcError(code: code, message: message, data: errData), id: id)
}
}
struct JsonRpcError: Codable, Sendable {
let code: Int
let message: String
let data: AnyCodable?
}
// MARK: - MCP Protocol Types
struct MCPToolDefinition: Sendable {
let name: String
let description: String
nonisolated(unsafe) let inputSchema: [String: Any]
let annotations: ToolAnnotations
let handler: @Sendable ([String: Any]) async -> [[String: Any]]
}
struct ToolAnnotations: Codable, Sendable {
var readOnlyHint: Bool = false
var destructiveHint: Bool = false
var idempotentHint: Bool = false
var openWorldHint: Bool = false
}
struct MCPResourceDefinition: Sendable {
let uri: String
let name: String
let mimeType: String
let handler: @Sendable () async -> String
}
struct MCPPromptDefinition: Sendable {
let name: String
let description: String
let arguments: [[String: String]]
let handler: @Sendable ([String: String]) -> [[String: Any]]
}
struct MCPCapabilities: Codable, Sendable {
let tools: ToolsCap?
let resources: ResourcesCap?
let prompts: PromptsCap?
let logging: LoggingCap?
struct ToolsCap: Codable, Sendable { let listChanged: Bool? }
struct ResourcesCap: Codable, Sendable { let subscribe: Bool?; let listChanged: Bool? }
struct PromptsCap: Codable, Sendable { let listChanged: Bool? }
struct LoggingCap: Codable, Sendable {}
}
// MARK: - AnyCodable (JSON bridge)
struct AnyCodable: Codable, Sendable, CustomStringConvertible {
nonisolated(unsafe) let value: Any
init(_ value: Any) {
self.value = value
}
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if container.decodeNil() {
value = NSNull()
} else if let b = try? container.decode(Bool.self) {
value = b
} else if let i = try? container.decode(Int.self) {
value = i
} else if let d = try? container.decode(Double.self) {
value = d
} else if let s = try? container.decode(String.self) {
value = s
} else if let arr = try? container.decode([AnyCodable].self) {
value = arr.map(\.value)
} else if let dict = try? container.decode([String: AnyCodable].self) {
value = dict.mapValues(\.value)
} else {
value = NSNull()
}
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch value {
case is NSNull:
try container.encodeNil()
case let b as Bool:
try container.encode(b)
case let i as Int:
try container.encode(i)
case let d as Double:
try container.encode(d)
case let s as String:
try container.encode(s)
case let arr as [Any]:
try container.encode(arr.map { AnyCodable($0) })
case let dict as [String: Any]:
try container.encode(dict.mapValues { AnyCodable($0) })
default:
try container.encode("\(value)")
}
}
var description: String { "\(value)" }
}
// MARK: - JSON Serialization Helpers
enum JSON {
private static let encoder: JSONEncoder = {
let e = JSONEncoder()
e.outputFormatting = [.sortedKeys]
return e
}()
private static let prettyEncoder: JSONEncoder = {
let e = JSONEncoder()
e.outputFormatting = [.prettyPrinted, .sortedKeys]
return e
}()
static func serialize(_ value: Any, pretty: Bool = false) -> String {
let enc = pretty ? prettyEncoder : encoder
if let codable = value as? Encodable {
if let data = try? enc.encode(AnyCodable(codable)) {
return String(data: data, encoding: .utf8) ?? "{}"
}
}
// Fallback to JSONSerialization
if let data = try? JSONSerialization.data(withJSONObject: value, options: pretty ? .prettyPrinted : .sortedKeys) {
return String(data: data, encoding: .utf8) ?? "{}"
}
return "{}"
}
static func parse(_ string: String) -> Any? {
guard let data = string.data(using: .utf8) else { return nil }
return try? JSONSerialization.jsonObject(with: data)
}
static func parseDict(_ string: String) -> [String: Any]? {
parse(string) as? [String: Any]
}
}