use serde_json::Value;
#[derive(Debug, Clone, PartialEq)]
pub enum Protocol {
Mcp,
OpenAI,
A2A,
Generic,
}
impl std::fmt::Display for Protocol {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Protocol::Mcp => write!(f, "MCP"),
Protocol::OpenAI => write!(f, "OpenAI"),
Protocol::A2A => write!(f, "A2A"),
Protocol::Generic => write!(f, "Generic"),
}
}
}
pub fn detect_protocol(body: &[u8]) -> Protocol {
match serde_json::from_slice::<Value>(body) {
Ok(json) => detect_protocol_value(&json),
Err(_) => Protocol::Generic,
}
}
pub fn detect_protocol_value(json: &Value) -> Protocol {
if json.get("jsonrpc").is_some() {
if let Some(method) = json.get("method").and_then(|m| m.as_str()) {
if method.starts_with("tasks/") || method.starts_with("agent/") {
return Protocol::A2A;
}
}
return Protocol::Mcp;
}
if json.get("task").is_some() || json.get("agent_card").is_some() {
return Protocol::A2A;
}
if json.get("model").is_some() && json.get("messages").is_some() {
return Protocol::OpenAI;
}
Protocol::Generic
}
#[derive(Debug, Clone, PartialEq, serde::Serialize)]
pub enum A2ATaskState {
Submitted,
Working,
InputRequired,
Completed,
Canceled,
Failed,
}
pub fn extract_a2a_method(body: &[u8]) -> Option<String> {
let json: Value = serde_json::from_slice(body).ok()?;
json.get("method")
.and_then(|m| m.as_str())
.map(String::from)
}
pub fn validate_agent_card(body: &[u8]) -> bool {
let Ok(json) = serde_json::from_slice::<Value>(body) else {
return false;
};
json.get("name").is_some() && json.get("capabilities").is_some()
}