techne_mcp/
lib.rs

1pub mod client;
2pub mod server;
3
4mod schema;
5
6pub use client::Client;
7pub use schema::Schema;
8pub use server::Server;
9
10pub use bytes::Bytes;
11pub use serde::de::IgnoredAny as Ignored;
12pub use serde_json::{Map, Value, json};
13
14use serde::de::DeserializeOwned;
15use serde::{Deserialize, Serialize};
16
17use std::io;
18
19pub const VERSION: &str = "2025-06-18";
20pub const JSONRPC: &str = "2.0";
21
22#[derive(Debug, Clone, Serialize, Deserialize)]
23#[serde(untagged)]
24pub enum Message<R, N, T = Value> {
25    Request(Request<R>),
26    Notification(Notification<N>),
27    Response(Response<T>),
28    Error(Error),
29}
30
31impl<R, N, T> Message<R, N, T> {
32    pub fn request(id: Id, payload: R) -> Self {
33        Self::Request(Request::new(id, payload))
34    }
35
36    pub fn notification(payload: N) -> Self {
37        Self::Notification(Notification::new(payload))
38    }
39
40    pub fn response(id: Id, result: T) -> Self {
41        Self::Response(Response::new(id, result))
42    }
43
44    pub fn error(id: Option<Id>, payload: ErrorKind) -> Self {
45        Self::Error(Error::new(id, payload))
46    }
47
48    pub fn deserialize(json: &[u8]) -> Result<Self, Error>
49    where
50        R: DeserializeOwned,
51        N: DeserializeOwned,
52        T: DeserializeOwned,
53    {
54        #[derive(Deserialize)]
55        #[serde(untagged)]
56        enum JsonRpc<R, N, T> {
57            Message(Message<R, N, T>),
58            Other { method: String },
59        }
60
61        match serde_json::from_slice(json) {
62            Ok(JsonRpc::Message(message)) => Ok(message),
63            Ok(JsonRpc::Other { method }) => Err(Error::method_not_found(method)),
64            Err(error) => Err(Error::invalid_json(error.to_string())),
65        }
66    }
67}
68
69impl<R, N> Message<R, N> {
70    pub fn decode<A: DeserializeOwned>(self) -> serde_json::Result<Message<R, N, A>> {
71        Ok(match self {
72            Self::Request(message) => Message::Request(message),
73            Self::Notification(notification) => Message::Notification(notification),
74            Self::Response(response) => Message::Response(Response::new(
75                response.id,
76                serde_json::from_value(response.result)?,
77            )),
78            Self::Error(error) => Message::Error(error),
79        })
80    }
81}
82
83#[derive(Debug, Clone, Serialize, Deserialize)]
84pub struct Request<T> {
85    jsonrpc: String,
86    pub id: Id,
87    #[serde(flatten)]
88    pub payload: T,
89}
90
91impl<T> Request<T> {
92    pub fn new(id: Id, payload: T) -> Self {
93        Self {
94            jsonrpc: JSONRPC.to_owned(),
95            id,
96            payload,
97        }
98    }
99
100    pub fn serialize(&self) -> serde_json::Result<Bytes>
101    where
102        T: Serialize,
103    {
104        serde_json::to_vec(self).map(Bytes::from_owner)
105    }
106}
107
108#[derive(Debug, Clone, Serialize, Deserialize)]
109pub struct Response<T = serde_json::Value> {
110    jsonrpc: String,
111    pub id: Id,
112    pub result: T,
113}
114
115impl<T> Response<T> {
116    pub fn new(id: Id, result: T) -> Self {
117        Self {
118            jsonrpc: JSONRPC.to_owned(),
119            id,
120            result,
121        }
122    }
123
124    pub fn serialize(&self) -> serde_json::Result<Bytes>
125    where
126        T: Serialize,
127    {
128        serde_json::to_vec(self).map(Bytes::from_owner)
129    }
130}
131
132#[derive(Debug, Clone, Serialize, Deserialize)]
133pub struct Notification<T> {
134    jsonrpc: String,
135    #[serde(flatten)]
136    pub payload: T,
137}
138
139impl<T> Notification<T> {
140    pub fn new(payload: T) -> Self {
141        Self {
142            jsonrpc: JSONRPC.to_owned(),
143            payload,
144        }
145    }
146
147    pub fn serialize(&self) -> serde_json::Result<Bytes>
148    where
149        T: Serialize,
150    {
151        serde_json::to_vec(self).map(Bytes::from_owner)
152    }
153}
154
155#[derive(Debug, Clone, Serialize, Deserialize)]
156pub struct Error {
157    jsonrpc: String,
158    #[serde(default, skip_serializing_if = "Option::is_none")]
159    id: Option<Id>,
160    #[serde(rename = "error")]
161    payload: ErrorKind,
162}
163
164impl Error {
165    pub fn new(id: Option<Id>, payload: ErrorKind) -> Self {
166        Self {
167            jsonrpc: JSONRPC.to_owned(),
168            id,
169            payload,
170        }
171    }
172
173    pub fn method_not_found(method: String) -> Self {
174        Self::new(
175            None,
176            ErrorKind::new(-32601, format!("Unknown method: {method}")),
177        )
178    }
179
180    pub fn invalid_json(message: String) -> Self {
181        Self::new(None, ErrorKind::new(-32700, message))
182    }
183
184    pub fn serialize(&self) -> serde_json::Result<Bytes> {
185        serde_json::to_vec(self).map(Bytes::from_owner)
186    }
187}
188
189#[derive(Debug, Clone, Serialize, Deserialize)]
190pub struct ErrorKind {
191    code: i64,
192    message: String,
193}
194
195impl ErrorKind {
196    fn new(code: i64, message: String) -> Self {
197        Self { code, message }
198    }
199
200    pub fn invalid_params(message: String) -> Self {
201        Self::new(-32602, message)
202    }
203}
204
205impl std::fmt::Display for Error {
206    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
207        self.payload.fmt(f)
208    }
209}
210
211impl std::fmt::Display for ErrorKind {
212    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
213        write!(
214            f,
215            "{message} ({code})",
216            message = self.message,
217            code = self.code
218        )
219    }
220}
221
222#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default, Serialize, Deserialize)]
223pub struct Id(u64);
224
225impl Id {
226    pub fn increment(&mut self) -> Self {
227        let current = *self;
228        self.0 += 1;
229        current
230    }
231}
232
233pub fn from_value<T: DeserializeOwned>(value: Value) -> io::Result<T> {
234    Ok(serde_json::from_value(value)?)
235}