use serde::Serialize;
use serde_json::Value;
pub const PROTOCOL_VERSION: &str = "2026-07-28";
pub mod method {
pub const INITIALIZE: &str = "initialize";
pub const PING: &str = "ping";
pub const TOOLS_CALL: &str = "tools/call";
pub const TOOLS_LIST: &str = "tools/list";
}
#[derive(Debug, Clone, Serialize)]
pub struct Tool {
pub name: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(rename = "inputSchema", skip_serializing_if = "Option::is_none")]
pub input_schema: Option<Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub annotations: Option<ToolAnnotations>,
}
#[derive(Debug, Clone, Default, Serialize)]
pub struct ToolAnnotations {
#[serde(skip_serializing_if = "Option::is_none")]
pub title: Option<String>,
#[serde(rename = "readOnlyHint", skip_serializing_if = "Option::is_none")]
pub read_only_hint: Option<bool>,
#[serde(rename = "destructiveHint", skip_serializing_if = "Option::is_none")]
pub destructive_hint: Option<bool>,
#[serde(rename = "idempotentHint", skip_serializing_if = "Option::is_none")]
pub idempotent_hint: Option<bool>,
#[serde(rename = "openWorldHint", skip_serializing_if = "Option::is_none")]
pub open_world_hint: Option<bool>,
}
impl ToolAnnotations {
pub fn new() -> Self {
Self::default()
}
pub fn title(mut self, title: &str) -> Self {
self.title = Some(title.to_string());
self
}
pub fn read_only(mut self, hint: bool) -> Self {
self.read_only_hint = Some(hint);
self
}
pub fn destructive(mut self, hint: bool) -> Self {
self.destructive_hint = Some(hint);
self
}
pub fn idempotent(mut self, hint: bool) -> Self {
self.idempotent_hint = Some(hint);
self
}
pub fn open_world(mut self, hint: bool) -> Self {
self.open_world_hint = Some(hint);
self
}
}
#[derive(Debug, Serialize)]
pub struct ToolsListResult {
pub tools: Vec<Tool>,
}
#[derive(Debug, Serialize)]
pub struct TextContent {
#[serde(rename = "type")]
pub kind: &'static str,
pub text: String,
}
#[derive(Debug, Serialize)]
pub struct CallToolResult {
pub content: Vec<TextContent>,
#[serde(rename = "isError", skip_serializing_if = "Option::is_none")]
pub is_error: Option<bool>,
#[serde(rename = "structuredContent", skip_serializing_if = "Option::is_none")]
pub structured_content: Option<Value>,
}
impl From<Result<Value, String>> for CallToolResult {
fn from(result: Result<Value, String>) -> Self {
match result {
Ok(value) => Self {
content: vec![TextContent {
kind: "text",
text: value.to_string(),
}],
is_error: None,
structured_content: Some(value),
},
Err(message) => Self {
content: vec![TextContent {
kind: "text",
text: message,
}],
is_error: Some(true),
structured_content: None,
},
}
}
}
#[derive(Debug, Serialize)]
pub struct ServerInfo {
pub name: String,
pub version: String,
}