Skip to main content

agent_client_protocol/schema/
mod.rs

1//! ACP protocol schema types and message implementations.
2//!
3//! This module contains all the types from the Agent-Client Protocol schema,
4//! including requests, responses, notifications, and supporting types.
5//! All types are re-exported flatly from this module.
6
7// ---------------------------------------------------------------------------
8// Macros for implementing JsonRpc traits on schema types
9// ---------------------------------------------------------------------------
10
11/// Implement `JsonRpcMessage`, `JsonRpcRequest`, and `JsonRpcResponse` for a
12/// request/response pair from the schema crate.
13///
14/// ```ignore
15/// impl_jsonrpc_request!(PromptRequest, PromptResponse, "session/prompt");
16/// ```
17macro_rules! impl_jsonrpc_request {
18    ($req:ty, $resp:ty, $method:literal) => {
19        impl $crate::JsonRpcMessage for $req {
20            fn matches_method(method: &str) -> bool {
21                method == $method
22            }
23
24            fn method(&self) -> &str {
25                $method
26            }
27
28            fn to_untyped_message(&self) -> Result<$crate::UntypedMessage, $crate::Error> {
29                $crate::UntypedMessage::new($method, self)
30            }
31
32            fn parse_message(
33                method: &str,
34                params: &impl serde::Serialize,
35            ) -> Result<Self, $crate::Error> {
36                if method != $method {
37                    return Err($crate::Error::method_not_found());
38                }
39                $crate::util::json_cast_params(params)
40            }
41        }
42
43        impl $crate::JsonRpcRequest for $req {
44            type Response = $resp;
45        }
46
47        impl $crate::JsonRpcResponse for $resp {
48            fn into_json(self, _method: &str) -> Result<serde_json::Value, $crate::Error> {
49                serde_json::to_value(self).map_err($crate::Error::into_internal_error)
50            }
51
52            fn from_value(_method: &str, value: serde_json::Value) -> Result<Self, $crate::Error> {
53                $crate::util::json_cast(&value)
54            }
55        }
56    };
57}
58
59/// Implement `JsonRpcMessage` and `JsonRpcNotification` for a notification type
60/// from the schema crate.
61///
62/// ```ignore
63/// impl_jsonrpc_notification!(CancelNotification, "session/cancel");
64/// ```
65macro_rules! impl_jsonrpc_notification {
66    ($notif:ty, $method:literal) => {
67        impl $crate::JsonRpcMessage for $notif {
68            fn matches_method(method: &str) -> bool {
69                method == $method
70            }
71
72            fn method(&self) -> &str {
73                $method
74            }
75
76            fn to_untyped_message(&self) -> Result<$crate::UntypedMessage, $crate::Error> {
77                $crate::UntypedMessage::new($method, self)
78            }
79
80            fn parse_message(
81                method: &str,
82                params: &impl serde::Serialize,
83            ) -> Result<Self, $crate::Error> {
84                if method != $method {
85                    return Err($crate::Error::method_not_found());
86                }
87                $crate::util::json_cast_params(params)
88            }
89        }
90
91        impl $crate::JsonRpcNotification for $notif {}
92    };
93}
94
95/// Implement `JsonRpcMessage` and `JsonRpcRequest` for an enum that dispatches
96/// across multiple request types, with an extension method fallback.
97///
98/// Variants can optionally have `#[cfg(...)]` attributes for conditional compilation.
99///
100/// ```ignore
101/// impl_jsonrpc_request_enum!(ClientRequest {
102///     InitializeRequest => "initialize",
103///     PromptRequest => "session/prompt",
104///     #[cfg(feature = "unstable_session_model")]
105///     SetSessionModelRequest => "session/set_model",
106///     [ext] ExtMethodRequest,
107/// });
108/// ```
109macro_rules! impl_jsonrpc_request_enum {
110    ($enum:ty {
111        $( $(#[$meta:meta])* $variant:ident => $method:literal, )*
112        [ext] $ext_variant:ident,
113    }) => {
114        impl $crate::JsonRpcMessage for $enum {
115            fn matches_method(_method: &str) -> bool {
116                true
117            }
118
119            fn method(&self) -> &str {
120                match self {
121                    $( $(#[$meta])* Self::$variant(_) => $method, )*
122                    Self::$ext_variant(ext) => &ext.method,
123                    _ => "_unknown",
124                }
125            }
126
127            fn to_untyped_message(&self) -> Result<$crate::UntypedMessage, $crate::Error> {
128                $crate::UntypedMessage::new(self.method(), self)
129            }
130
131            fn parse_message(
132                method: &str,
133                params: &impl serde::Serialize,
134            ) -> Result<Self, $crate::Error> {
135                match method {
136                    $( $(#[$meta])* $method => $crate::util::json_cast_params(params).map(Self::$variant), )*
137                    _ => {
138                        if let Some(custom_method) = method.strip_prefix('_') {
139                            $crate::util::json_cast_params(params).map(
140                                |ext_req: $crate::schema::ExtRequest| {
141                                    Self::$ext_variant($crate::schema::ExtRequest::new(
142                                        custom_method.to_string(),
143                                        ext_req.params,
144                                    ))
145                                },
146                            )
147                        } else {
148                            Err($crate::Error::method_not_found())
149                        }
150                    }
151                }
152            }
153        }
154
155        impl $crate::JsonRpcRequest for $enum {
156            type Response = serde_json::Value;
157        }
158    };
159}
160
161/// Implement `JsonRpcMessage` and `JsonRpcNotification` for an enum that
162/// dispatches across multiple notification types, with an extension fallback.
163///
164/// Variants can optionally have `#[cfg(...)]` attributes for conditional compilation.
165///
166/// ```ignore
167/// impl_jsonrpc_notification_enum!(AgentNotification {
168///     SessionNotification => "session/update",
169///     [ext] ExtNotification,
170/// });
171/// ```
172macro_rules! impl_jsonrpc_notification_enum {
173    ($enum:ty {
174        $( $(#[$meta:meta])* $variant:ident => $method:literal, )*
175        [ext] $ext_variant:ident,
176    }) => {
177        impl $crate::JsonRpcMessage for $enum {
178            fn matches_method(_method: &str) -> bool {
179                true
180            }
181
182            fn method(&self) -> &str {
183                match self {
184                    $( $(#[$meta])* Self::$variant(_) => $method, )*
185                    Self::$ext_variant(ext) => &ext.method,
186                    _ => "_unknown",
187                }
188            }
189
190            fn to_untyped_message(&self) -> Result<$crate::UntypedMessage, $crate::Error> {
191                $crate::UntypedMessage::new(self.method(), self)
192            }
193
194            fn parse_message(
195                method: &str,
196                params: &impl serde::Serialize,
197            ) -> Result<Self, $crate::Error> {
198                match method {
199                    $( $(#[$meta])* $method => $crate::util::json_cast_params(params).map(Self::$variant), )*
200                    _ => {
201                        if let Some(custom_method) = method.strip_prefix('_') {
202                            $crate::util::json_cast_params(params).map(
203                                |ext_notif: $crate::schema::ExtNotification| {
204                                    Self::$ext_variant($crate::schema::ExtNotification::new(
205                                        custom_method.to_string(),
206                                        ext_notif.params,
207                                    ))
208                                },
209                            )
210                        } else {
211                            Err($crate::Error::method_not_found())
212                        }
213                    }
214                }
215            }
216        }
217
218        impl $crate::JsonRpcNotification for $enum {}
219    };
220}
221
222// Internal organization
223mod agent_to_client;
224mod client_to_agent;
225mod enum_impls;
226mod proxy_protocol;
227
228// Re-export everything from agent_client_protocol_schema
229pub use agent_client_protocol_schema::*;
230
231// Re-export proxy/MCP protocol types
232pub use proxy_protocol::*;