use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::collections::HashMap;
use thiserror::Error;
#[derive(Error, Debug)]
pub enum SimpleMcpError {
#[error("Transport error: {0}")]
Transport(String),
#[error("Protocol error: {0}")]
Protocol(String),
#[error("Tool error: {0}")]
Tool(String),
#[error("Serialization error: {0}")]
Serialization(#[from] serde_json::Error),
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
}
pub type SimpleMcpResult<T> = Result<T, SimpleMcpError>;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SimpleTool {
pub name: String,
pub description: Option<String>,
pub input_schema: Value,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SimpleToolCall {
pub name: String,
pub arguments: Option<HashMap<String, Value>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SimpleToolResult {
pub content: Vec<SimpleContent>,
pub is_error: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type")]
pub enum SimpleContent {
#[serde(rename = "text")]
Text { text: String },
#[serde(rename = "image")]
Image { data: String, mime_type: String },
#[serde(rename = "resource")]
Resource { resource: SimpleResource },
}
impl SimpleContent {
pub fn text(text: impl Into<String>) -> Self {
Self::Text { text: text.into() }
}
pub fn image(data: impl Into<String>, mime_type: impl Into<String>) -> Self {
Self::Image {
data: data.into(),
mime_type: mime_type.into()
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SimpleResource {
pub uri: String,
pub name: Option<String>,
pub description: Option<String>,
pub mime_type: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SimpleServerCapabilities {
pub tools: Option<SimpleToolsCapability>,
pub resources: Option<SimpleResourcesCapability>,
pub prompts: Option<SimplePromptsCapability>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SimpleToolsCapability {
pub list_changed: Option<bool>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SimpleResourcesCapability {
pub subscribe: Option<bool>,
pub list_changed: Option<bool>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SimplePromptsCapability {
pub list_changed: Option<bool>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SimpleClientCapabilities {
pub experimental: Option<HashMap<String, Value>>,
pub roots: Option<SimpleRootsCapability>,
pub sampling: Option<SimpleSamplingCapability>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SimpleRootsCapability {
pub list_changed: Option<bool>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SimpleSamplingCapability {}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SimpleServerInfo {
pub name: String,
pub version: String,
pub protocol_version: String,
pub capabilities: SimpleServerCapabilities,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SimpleClientInfo {
pub name: String,
pub version: String,
pub protocol_version: String,
pub capabilities: SimpleClientCapabilities,
}
impl Default for SimpleClientInfo {
fn default() -> Self {
Self {
name: "coderlib".to_string(),
version: "0.1.0".to_string(),
protocol_version: "2025-03-26".to_string(),
capabilities: SimpleClientCapabilities {
experimental: None,
roots: None,
sampling: None,
},
}
}
}
impl SimpleToolResult {
pub fn success(content: Vec<SimpleContent>) -> Self {
Self {
content,
is_error: false,
}
}
pub fn error(message: impl Into<String>) -> Self {
Self {
content: vec![SimpleContent::text(message.into())],
is_error: true,
}
}
}
pub trait SimpleTransport: Send + Sync {
fn send(&mut self, message: Value) -> SimpleMcpResult<()>;
fn receive(&mut self) -> SimpleMcpResult<Option<Value>>;
fn close(&mut self) -> SimpleMcpResult<()>;
}
pub trait SimpleToolHandler: Send + Sync {
fn name(&self) -> &str;
fn description(&self) -> Option<&str>;
fn input_schema(&self) -> Value;
fn call(&self, arguments: Option<HashMap<String, Value>>) -> SimpleMcpResult<SimpleToolResult>;
}
pub trait SimpleMcpServer: Send + Sync {
fn info(&self) -> SimpleServerInfo;
fn list_tools(&self) -> SimpleMcpResult<Vec<SimpleTool>>;
fn call_tool(&self, request: SimpleToolCall) -> SimpleMcpResult<SimpleToolResult>;
fn list_resources(&self) -> SimpleMcpResult<Vec<SimpleResource>>;
fn read_resource(&self, uri: &str) -> SimpleMcpResult<Vec<SimpleContent>>;
}
pub trait SimpleMcpClient: Send + Sync {
fn connect(&mut self) -> SimpleMcpResult<SimpleServerInfo>;
fn list_tools(&mut self) -> SimpleMcpResult<Vec<SimpleTool>>;
fn call_tool(&mut self, request: SimpleToolCall) -> SimpleMcpResult<SimpleToolResult>;
fn list_resources(&mut self) -> SimpleMcpResult<Vec<SimpleResource>>;
fn read_resource(&mut self, uri: &str) -> SimpleMcpResult<Vec<SimpleContent>>;
fn disconnect(&mut self) -> SimpleMcpResult<()>;
}