///|
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 send_event(Self, event_type~ : String, data~ : String) -> Unit
fn supports_streaming(Self) -> Bool
fn close(Self) -> Unit
}
///|
pub(all) enum AnyTransport {
Stdio(StdioTransport)
StdioClient(StdioClientTransport)
Http(HttpTransport)
HttpClient(HttpClientTransport)
}
///|
pub async fn AnyTransport::receive(
self : AnyTransport,
) -> String? raise @types.TransportError {
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 raise @types.TransportError {
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 raise @types.TransportError {
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::send_event(
self : AnyTransport,
event_type~ : String,
data~ : String,
) -> Unit {
match self {
Stdio(t) => t.send_event(event_type~, data~)
StdioClient(t) => t.send_event(event_type~, data~)
Http(t) => t.send_event(event_type~, data~)
HttpClient(t) => t.send_event(event_type~, data~)
}
}
///|
pub fn AnyTransport::supports_streaming(self : AnyTransport) -> Bool {
match self {
Stdio(t) => t.supports_streaming()
StdioClient(t) => t.supports_streaming()
Http(t) => t.supports_streaming()
HttpClient(t) => t.supports_streaming()
}
}
///|
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,
) -> Result[Unit, @types.MCPError] {
let json = @json.parse(message) catch {
_ => return Err(@types.ParseError("Invalid JSON"))
}
if json is Object(obj) {
match obj.get("jsonrpc") {
Some(String("2.0")) => ()
_ =>
return Err(@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) {
return Err(
@types.InvalidRequest("Must have 'method', 'result', or 'error' field"),
)
}
Ok(())
} else {
Err(@types.InvalidRequest("JSON-RPC message must be an object"))
}
}