///|
pub(open) trait Transport {
fn receive(Self) -> String? raise @types.TransportError
fn send(Self, String) -> Unit raise @types.TransportError
fn send_notification(Self, @types.Notification) -> Unit raise @types.TransportError
fn close(Self) -> Unit
}
///|
pub(all) enum AnyTransport {
Stdio(StdioTransport)
StdioClient(StdioClientTransport)
Http(HttpTransport)
HttpClient(HttpClientTransport)
}
///|
pub async fn AnyTransport::receive(self : AnyTransport) -> String? {
match self {
Stdio(t) => t.receive()
StdioClient(t) => t.receive()
Http(t) => t.receive()
HttpClient(t) => t.receive()
}
}
///|
pub async fn AnyTransport::send(self : AnyTransport, message : String) -> Unit {
match self {
Stdio(t) => t.send(message)
StdioClient(t) => t.send(message)
Http(t) => t.send(message)
HttpClient(t) => t.send(message)
}
}
///|
pub async fn AnyTransport::send_notification(
self : AnyTransport,
notification : @types.Notification,
) -> Unit {
match self {
Stdio(t) => t.send_notification(notification)
StdioClient(t) => t.send_notification(notification)
Http(t) => t.send_notification(notification)
HttpClient(t) => t.send_notification(notification)
}
}
///|
pub fn AnyTransport::close(self : AnyTransport) -> Unit {
match self {
Stdio(t) => t.close()
StdioClient(t) => t.close()
Http(t) => t.close()
HttpClient(t) => t.close()
}
}
///|
pub fn validate_jsonrpc_message(message : String) -> Unit raise @types.MCPError {
let json = @json.parse(message) catch {
_ => raise @types.ParseError("Invalid JSON")
}
if json is Object(obj) {
match obj.get("jsonrpc") {
Some(String("2.0")) => ()
_ => raise @types.InvalidRequest("Missing or invalid 'jsonrpc' field")
}
let has_method = obj.get("method") is Some(_)
let has_result = obj.get("result") is Some(_)
let has_error = obj.get("error") is Some(_)
if !(has_method || has_result || has_error) {
raise @types.InvalidRequest(
"Must have 'method', 'result', or 'error' field",
)
}
()
} else {
raise @types.InvalidRequest("JSON-RPC message must be an object")
}
}