agent_client_protocol_schema/
agent.rs

1//! Methods and notifications the agent handles/receives.
2//!
3//! This module defines the Agent trait and all associated types for implementing
4//! an AI coding agent that follows the Agent Client Protocol (ACP).
5
6use std::{path::PathBuf, sync::Arc};
7
8use derive_more::{Display, From};
9use schemars::JsonSchema;
10use serde::{Deserialize, Serialize};
11use serde_json::value::RawValue;
12
13use crate::ext::ExtRequest;
14use crate::{ClientCapabilities, ContentBlock, ExtNotification, ProtocolVersion, SessionId};
15
16// Initialize
17
18/// Request parameters for the initialize method.
19///
20/// Sent by the client to establish connection and negotiate capabilities.
21///
22/// See protocol docs: [Initialization](https://agentclientprotocol.com/protocol/initialization)
23#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
24#[schemars(extend("x-side" = "agent", "x-method" = INITIALIZE_METHOD_NAME))]
25#[serde(rename_all = "camelCase")]
26pub struct InitializeRequest {
27    /// The latest protocol version supported by the client.
28    pub protocol_version: ProtocolVersion,
29    /// Capabilities supported by the client.
30    #[serde(default)]
31    pub client_capabilities: ClientCapabilities,
32    /// Extension point for implementations
33    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
34    pub meta: Option<serde_json::Value>,
35}
36
37/// Response from the initialize method.
38///
39/// Contains the negotiated protocol version and agent capabilities.
40///
41/// See protocol docs: [Initialization](https://agentclientprotocol.com/protocol/initialization)
42#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
43#[schemars(extend("x-side" = "agent", "x-method" = INITIALIZE_METHOD_NAME))]
44#[serde(rename_all = "camelCase")]
45pub struct InitializeResponse {
46    /// The protocol version the client specified if supported by the agent,
47    /// or the latest protocol version supported by the agent.
48    ///
49    /// The client should disconnect, if it doesn't support this version.
50    pub protocol_version: ProtocolVersion,
51    /// Capabilities supported by the agent.
52    #[serde(default)]
53    pub agent_capabilities: AgentCapabilities,
54    /// Authentication methods supported by the agent.
55    #[serde(default)]
56    pub auth_methods: Vec<AuthMethod>,
57    /// Extension point for implementations
58    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
59    pub meta: Option<serde_json::Value>,
60}
61
62// Authentication
63
64/// Request parameters for the authenticate method.
65///
66/// Specifies which authentication method to use.
67#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
68#[schemars(extend("x-side" = "agent", "x-method" = AUTHENTICATE_METHOD_NAME))]
69#[serde(rename_all = "camelCase")]
70pub struct AuthenticateRequest {
71    /// The ID of the authentication method to use.
72    /// Must be one of the methods advertised in the initialize response.
73    pub method_id: AuthMethodId,
74    /// Extension point for implementations
75    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
76    pub meta: Option<serde_json::Value>,
77}
78
79/// Response to authenticate method
80#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
81#[serde(rename_all = "camelCase")]
82#[schemars(extend("x-side" = "agent", "x-method" = AUTHENTICATE_METHOD_NAME))]
83pub struct AuthenticateResponse {
84    /// Extension point for implementations
85    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
86    pub meta: Option<serde_json::Value>,
87}
88
89/// Unique identifier for an authentication method.
90#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, Display, From)]
91#[serde(transparent)]
92#[from(Arc<str>, String, &'static str)]
93pub struct AuthMethodId(pub Arc<str>);
94
95/// Describes an available authentication method.
96#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
97#[serde(rename_all = "camelCase")]
98pub struct AuthMethod {
99    /// Unique identifier for this authentication method.
100    pub id: AuthMethodId,
101    /// Human-readable name of the authentication method.
102    pub name: String,
103    /// Optional description providing more details about this authentication method.
104    pub description: Option<String>,
105    /// Extension point for implementations
106    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
107    pub meta: Option<serde_json::Value>,
108}
109
110// New session
111
112/// Request parameters for creating a new session.
113///
114/// See protocol docs: [Creating a Session](https://agentclientprotocol.com/protocol/session-setup#creating-a-session)
115#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
116#[schemars(extend("x-side" = "agent", "x-method" = SESSION_NEW_METHOD_NAME))]
117#[serde(rename_all = "camelCase")]
118pub struct NewSessionRequest {
119    /// The working directory for this session. Must be an absolute path.
120    pub cwd: PathBuf,
121    /// List of MCP (Model Context Protocol) servers the agent should connect to.
122    pub mcp_servers: Vec<McpServer>,
123    /// Extension point for implementations
124    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
125    pub meta: Option<serde_json::Value>,
126}
127
128/// Response from creating a new session.
129///
130/// See protocol docs: [Creating a Session](https://agentclientprotocol.com/protocol/session-setup#creating-a-session)
131#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
132#[schemars(extend("x-side" = "agent", "x-method" = SESSION_NEW_METHOD_NAME))]
133#[serde(rename_all = "camelCase")]
134pub struct NewSessionResponse {
135    /// Unique identifier for the created session.
136    ///
137    /// Used in all subsequent requests for this conversation.
138    pub session_id: SessionId,
139    /// Initial mode state if supported by the Agent
140    ///
141    /// See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
142    #[serde(default, skip_serializing_if = "Option::is_none")]
143    pub modes: Option<SessionModeState>,
144    /// **UNSTABLE**
145    ///
146    /// This capability is not part of the spec yet, and may be removed or changed at any point.
147    ///
148    /// Initial model state if supported by the Agent
149    #[cfg(feature = "unstable")]
150    #[serde(default, skip_serializing_if = "Option::is_none")]
151    pub models: Option<SessionModelState>,
152    /// Extension point for implementations
153    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
154    pub meta: Option<serde_json::Value>,
155}
156
157// Load session
158
159/// Request parameters for loading an existing session.
160///
161/// Only available if the Agent supports the `loadSession` capability.
162///
163/// See protocol docs: [Loading Sessions](https://agentclientprotocol.com/protocol/session-setup#loading-sessions)
164#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
165#[schemars(extend("x-side" = "agent", "x-method" = SESSION_LOAD_METHOD_NAME))]
166#[serde(rename_all = "camelCase")]
167pub struct LoadSessionRequest {
168    /// List of MCP servers to connect to for this session.
169    pub mcp_servers: Vec<McpServer>,
170    /// The working directory for this session.
171    pub cwd: PathBuf,
172    /// The ID of the session to load.
173    pub session_id: SessionId,
174    /// Extension point for implementations
175    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
176    pub meta: Option<serde_json::Value>,
177}
178
179/// Response from loading an existing session.
180#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
181#[schemars(extend("x-side" = "agent", "x-method" = SESSION_LOAD_METHOD_NAME))]
182#[serde(rename_all = "camelCase")]
183pub struct LoadSessionResponse {
184    /// Initial mode state if supported by the Agent
185    ///
186    /// See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
187    #[serde(default, skip_serializing_if = "Option::is_none")]
188    pub modes: Option<SessionModeState>,
189    /// **UNSTABLE**
190    ///
191    /// This capability is not part of the spec yet, and may be removed or changed at any point.
192    ///
193    /// Initial model state if supported by the Agent
194    #[cfg(feature = "unstable")]
195    #[serde(default, skip_serializing_if = "Option::is_none")]
196    pub models: Option<SessionModelState>,
197    /// Extension point for implementations
198    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
199    pub meta: Option<serde_json::Value>,
200}
201
202// Session modes
203
204/// The set of modes and the one currently active.
205#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
206#[serde(rename_all = "camelCase")]
207pub struct SessionModeState {
208    /// The current mode the Agent is in.
209    pub current_mode_id: SessionModeId,
210    /// The set of modes that the Agent can operate in
211    pub available_modes: Vec<SessionMode>,
212    /// Extension point for implementations
213    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
214    pub meta: Option<serde_json::Value>,
215}
216
217/// A mode the agent can operate in.
218///
219/// See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
220#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
221#[serde(rename_all = "camelCase")]
222pub struct SessionMode {
223    pub id: SessionModeId,
224    pub name: String,
225    #[serde(default, skip_serializing_if = "Option::is_none")]
226    pub description: Option<String>,
227    /// Extension point for implementations
228    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
229    pub meta: Option<serde_json::Value>,
230}
231
232/// Unique identifier for a Session Mode.
233#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash)]
234#[serde(transparent)]
235pub struct SessionModeId(pub Arc<str>);
236
237impl std::fmt::Display for SessionModeId {
238    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
239        write!(f, "{}", self.0)
240    }
241}
242
243/// Request parameters for setting a session mode.
244#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
245#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_MODE_METHOD_NAME))]
246#[serde(rename_all = "camelCase")]
247pub struct SetSessionModeRequest {
248    /// The ID of the session to set the mode for.
249    pub session_id: SessionId,
250    /// The ID of the mode to set.
251    pub mode_id: SessionModeId,
252    /// Extension point for implementations
253    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
254    pub meta: Option<serde_json::Value>,
255}
256
257/// Response to `session/set_mode` method.
258#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
259#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_MODE_METHOD_NAME))]
260#[serde(rename_all = "camelCase")]
261pub struct SetSessionModeResponse {
262    pub meta: Option<serde_json::Value>,
263}
264
265// MCP
266
267/// Configuration for connecting to an MCP (Model Context Protocol) server.
268///
269/// MCP servers provide tools and context that the agent can use when
270/// processing prompts.
271///
272/// See protocol docs: [MCP Servers](https://agentclientprotocol.com/protocol/session-setup#mcp-servers)
273#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
274#[serde(tag = "type", rename_all = "snake_case")]
275pub enum McpServer {
276    /// HTTP transport configuration
277    ///
278    /// Only available when the Agent capabilities indicate `mcp_capabilities.http` is `true`.
279    #[serde(rename_all = "camelCase")]
280    Http {
281        /// Human-readable name identifying this MCP server.
282        name: String,
283        /// URL to the MCP server.
284        url: String,
285        /// HTTP headers to set when making requests to the MCP server.
286        headers: Vec<HttpHeader>,
287    },
288    /// SSE transport configuration
289    ///
290    /// Only available when the Agent capabilities indicate `mcp_capabilities.sse` is `true`.
291    #[serde(rename_all = "camelCase")]
292    Sse {
293        /// Human-readable name identifying this MCP server.
294        name: String,
295        /// URL to the MCP server.
296        url: String,
297        /// HTTP headers to set when making requests to the MCP server.
298        headers: Vec<HttpHeader>,
299    },
300    /// Stdio transport configuration
301    ///
302    /// All Agents MUST support this transport.
303    #[serde(untagged, rename_all = "camelCase")]
304    Stdio {
305        /// Human-readable name identifying this MCP server.
306        name: String,
307        /// Path to the MCP server executable.
308        command: PathBuf,
309        /// Command-line arguments to pass to the MCP server.
310        args: Vec<String>,
311        /// Environment variables to set when launching the MCP server.
312        env: Vec<EnvVariable>,
313    },
314}
315
316/// An environment variable to set when launching an MCP server.
317#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
318#[serde(rename_all = "camelCase")]
319pub struct EnvVariable {
320    /// The name of the environment variable.
321    pub name: String,
322    /// The value to set for the environment variable.
323    pub value: String,
324    /// Extension point for implementations
325    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
326    pub meta: Option<serde_json::Value>,
327}
328
329/// An HTTP header to set when making requests to the MCP server.
330#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
331#[serde(rename_all = "camelCase")]
332pub struct HttpHeader {
333    /// The name of the HTTP header.
334    pub name: String,
335    /// The value to set for the HTTP header.
336    pub value: String,
337    /// Extension point for implementations
338    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
339    pub meta: Option<serde_json::Value>,
340}
341
342// Prompt
343
344/// Request parameters for sending a user prompt to the agent.
345///
346/// Contains the user's message and any additional context.
347///
348/// See protocol docs: [User Message](https://agentclientprotocol.com/protocol/prompt-turn#1-user-message)
349#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
350#[schemars(extend("x-side" = "agent", "x-method" = SESSION_PROMPT_METHOD_NAME))]
351#[serde(rename_all = "camelCase")]
352pub struct PromptRequest {
353    /// The ID of the session to send this user message to
354    pub session_id: SessionId,
355    /// The blocks of content that compose the user's message.
356    ///
357    /// As a baseline, the Agent MUST support [`ContentBlock::Text`] and [`ContentBlock::ResourceLink`],
358    /// while other variants are optionally enabled via [`PromptCapabilities`].
359    ///
360    /// The Client MUST adapt its interface according to [`PromptCapabilities`].
361    ///
362    /// The client MAY include referenced pieces of context as either
363    /// [`ContentBlock::Resource`] or [`ContentBlock::ResourceLink`].
364    ///
365    /// When available, [`ContentBlock::Resource`] is preferred
366    /// as it avoids extra round-trips and allows the message to include
367    /// pieces of context from sources the agent may not have access to.
368    pub prompt: Vec<ContentBlock>,
369    /// Extension point for implementations
370    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
371    pub meta: Option<serde_json::Value>,
372}
373
374/// Response from processing a user prompt.
375///
376/// See protocol docs: [Check for Completion](https://agentclientprotocol.com/protocol/prompt-turn#4-check-for-completion)
377#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
378#[schemars(extend("x-side" = "agent", "x-method" = SESSION_PROMPT_METHOD_NAME))]
379#[serde(rename_all = "camelCase")]
380pub struct PromptResponse {
381    /// Indicates why the agent stopped processing the turn.
382    pub stop_reason: StopReason,
383    /// Extension point for implementations
384    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
385    pub meta: Option<serde_json::Value>,
386}
387
388/// Reasons why an agent stops processing a prompt turn.
389///
390/// See protocol docs: [Stop Reasons](https://agentclientprotocol.com/protocol/prompt-turn#stop-reasons)
391#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
392#[serde(rename_all = "snake_case")]
393pub enum StopReason {
394    /// The turn ended successfully.
395    EndTurn,
396    /// The turn ended because the agent reached the maximum number of tokens.
397    MaxTokens,
398    /// The turn ended because the agent reached the maximum number of allowed
399    /// agent requests between user turns.
400    MaxTurnRequests,
401    /// The turn ended because the agent refused to continue. The user prompt
402    /// and everything that comes after it won't be included in the next
403    /// prompt, so this should be reflected in the UI.
404    Refusal,
405    /// The turn was cancelled by the client via `session/cancel`.
406    ///
407    /// This stop reason MUST be returned when the client sends a `session/cancel`
408    /// notification, even if the cancellation causes exceptions in underlying operations.
409    /// Agents should catch these exceptions and return this semantically meaningful
410    /// response to confirm successful cancellation.
411    Cancelled,
412}
413
414// Model
415
416/// **UNSTABLE**
417///
418/// This capability is not part of the spec yet, and may be removed or changed at any point.
419///
420/// The set of models and the one currently active.
421#[cfg(feature = "unstable")]
422#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
423#[serde(rename_all = "camelCase")]
424pub struct SessionModelState {
425    /// The current model the Agent is in.
426    pub current_model_id: ModelId,
427    /// The set of models that the Agent can use
428    pub available_models: Vec<ModelInfo>,
429    /// Extension point for implementations
430    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
431    pub meta: Option<serde_json::Value>,
432}
433
434/// **UNSTABLE**
435///
436/// This capability is not part of the spec yet, and may be removed or changed at any point.
437///
438/// A unique identifier for a model.
439#[cfg(feature = "unstable")]
440#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, Display, From)]
441#[serde(transparent)]
442#[from(Arc<str>, String, &'static str)]
443pub struct ModelId(pub Arc<str>);
444
445/// **UNSTABLE**
446///
447/// This capability is not part of the spec yet, and may be removed or changed at any point.
448///
449/// Information about a selectable model.
450#[cfg(feature = "unstable")]
451#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
452#[serde(rename_all = "camelCase")]
453pub struct ModelInfo {
454    /// Unique identifier for the model.
455    pub model_id: ModelId,
456    /// Human-readable name of the model.
457    pub name: String,
458    /// Optional description of the model.
459    #[serde(default, skip_serializing_if = "Option::is_none")]
460    pub description: Option<String>,
461    /// Extension point for implementations
462    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
463    pub meta: Option<serde_json::Value>,
464}
465
466/// **UNSTABLE**
467///
468/// This capability is not part of the spec yet, and may be removed or changed at any point.
469///
470/// Request parameters for setting a session model.
471#[cfg(feature = "unstable")]
472#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
473#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_MODEL_METHOD_NAME))]
474#[serde(rename_all = "camelCase")]
475pub struct SetSessionModelRequest {
476    /// The ID of the session to set the model for.
477    pub session_id: SessionId,
478    /// The ID of the model to set.
479    pub model_id: ModelId,
480    /// Extension point for implementations
481    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
482    pub meta: Option<serde_json::Value>,
483}
484
485/// **UNSTABLE**
486///
487/// This capability is not part of the spec yet, and may be removed or changed at any point.
488///
489/// Response to `session/set_model` method.
490#[cfg(feature = "unstable")]
491#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
492#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_MODEL_METHOD_NAME))]
493#[serde(rename_all = "camelCase")]
494pub struct SetSessionModelResponse {
495    /// Extension point for implementations
496    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
497    pub meta: Option<serde_json::Value>,
498}
499
500// Capabilities
501
502/// Capabilities supported by the agent.
503///
504/// Advertised during initialization to inform the client about
505/// available features and content types.
506///
507/// See protocol docs: [Agent Capabilities](https://agentclientprotocol.com/protocol/initialization#agent-capabilities)
508#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
509#[serde(rename_all = "camelCase")]
510pub struct AgentCapabilities {
511    /// Whether the agent supports `session/load`.
512    #[serde(default)]
513    pub load_session: bool,
514    /// Prompt capabilities supported by the agent.
515    #[serde(default)]
516    pub prompt_capabilities: PromptCapabilities,
517    /// MCP capabilities supported by the agent.
518    #[serde(default)]
519    pub mcp_capabilities: McpCapabilities,
520    /// Extension point for implementations
521    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
522    pub meta: Option<serde_json::Value>,
523}
524
525/// Prompt capabilities supported by the agent in `session/prompt` requests.
526///
527/// Baseline agent functionality requires support for [`ContentBlock::Text`]
528/// and [`ContentBlock::ResourceLink`] in prompt requests.
529///
530/// Other variants must be explicitly opted in to.
531/// Capabilities for different types of content in prompt requests.
532///
533/// Indicates which content types beyond the baseline (text and resource links)
534/// the agent can process.
535///
536/// See protocol docs: [Prompt Capabilities](https://agentclientprotocol.com/protocol/initialization#prompt-capabilities)
537#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
538#[serde(rename_all = "camelCase")]
539pub struct PromptCapabilities {
540    /// Agent supports [`ContentBlock::Image`].
541    #[serde(default)]
542    pub image: bool,
543    /// Agent supports [`ContentBlock::Audio`].
544    #[serde(default)]
545    pub audio: bool,
546    /// Agent supports embedded context in `session/prompt` requests.
547    ///
548    /// When enabled, the Client is allowed to include [`ContentBlock::Resource`]
549    /// in prompt requests for pieces of context that are referenced in the message.
550    #[serde(default)]
551    pub embedded_context: bool,
552    /// Extension point for implementations
553    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
554    pub meta: Option<serde_json::Value>,
555}
556
557/// MCP capabilities supported by the agent
558#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
559#[serde(rename_all = "camelCase")]
560pub struct McpCapabilities {
561    /// Agent supports [`McpServer::Http`].
562    #[serde(default)]
563    pub http: bool,
564    /// Agent supports [`McpServer::Sse`].
565    #[serde(default)]
566    pub sse: bool,
567    /// Extension point for implementations
568    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
569    pub meta: Option<serde_json::Value>,
570}
571
572// Method schema
573
574/// Names of all methods that agents handle.
575///
576/// Provides a centralized definition of method names used in the protocol.
577#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
578pub struct AgentMethodNames {
579    /// Method for initializing the connection.
580    pub initialize: &'static str,
581    /// Method for authenticating with the agent.
582    pub authenticate: &'static str,
583    /// Method for creating a new session.
584    pub session_new: &'static str,
585    /// Method for loading an existing session.
586    pub session_load: &'static str,
587    /// Method for setting the mode for a session.
588    pub session_set_mode: &'static str,
589    /// Method for sending a prompt to the agent.
590    pub session_prompt: &'static str,
591    /// Notification for cancelling operations.
592    pub session_cancel: &'static str,
593    /// Method for selecting a model for a given session.
594    #[cfg(feature = "unstable")]
595    pub session_set_model: &'static str,
596}
597
598/// Constant containing all agent method names.
599pub const AGENT_METHOD_NAMES: AgentMethodNames = AgentMethodNames {
600    initialize: INITIALIZE_METHOD_NAME,
601    authenticate: AUTHENTICATE_METHOD_NAME,
602    session_new: SESSION_NEW_METHOD_NAME,
603    session_load: SESSION_LOAD_METHOD_NAME,
604    session_set_mode: SESSION_SET_MODE_METHOD_NAME,
605    session_prompt: SESSION_PROMPT_METHOD_NAME,
606    session_cancel: SESSION_CANCEL_METHOD_NAME,
607    #[cfg(feature = "unstable")]
608    session_set_model: SESSION_SET_MODEL_METHOD_NAME,
609};
610
611/// Method name for the initialize request.
612pub(crate) const INITIALIZE_METHOD_NAME: &str = "initialize";
613/// Method name for the authenticate request.
614pub(crate) const AUTHENTICATE_METHOD_NAME: &str = "authenticate";
615/// Method name for creating a new session.
616pub(crate) const SESSION_NEW_METHOD_NAME: &str = "session/new";
617/// Method name for loading an existing session.
618pub(crate) const SESSION_LOAD_METHOD_NAME: &str = "session/load";
619/// Method name for setting the mode for a session.
620pub(crate) const SESSION_SET_MODE_METHOD_NAME: &str = "session/set_mode";
621/// Method name for sending a prompt.
622pub(crate) const SESSION_PROMPT_METHOD_NAME: &str = "session/prompt";
623/// Method name for the cancel notification.
624pub(crate) const SESSION_CANCEL_METHOD_NAME: &str = "session/cancel";
625/// Method name for selecting a model for a given session.
626#[cfg(feature = "unstable")]
627pub(crate) const SESSION_SET_MODEL_METHOD_NAME: &str = "session/set_model";
628
629/// All possible requests that a client can send to an agent.
630///
631/// This enum is used internally for routing RPC requests. You typically won't need
632/// to use this directly - instead, use the methods on the [`Agent`] trait.
633///
634/// This enum encompasses all method calls from client to agent.
635#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
636#[serde(untagged)]
637#[schemars(extend("x-docs-ignore" = true))]
638pub enum ClientRequest {
639    /// Establishes the connection with a client and negotiates protocol capabilities.
640    ///
641    /// This method is called once at the beginning of the connection to:
642    /// - Negotiate the protocol version to use
643    /// - Exchange capability information between client and agent
644    /// - Determine available authentication methods
645    ///
646    /// The agent should respond with its supported protocol version and capabilities.
647    ///
648    /// See protocol docs: [Initialization](https://agentclientprotocol.com/protocol/initialization)
649    InitializeRequest(InitializeRequest),
650    /// Authenticates the client using the specified authentication method.
651    ///
652    /// Called when the agent requires authentication before allowing session creation.
653    /// The client provides the authentication method ID that was advertised during initialization.
654    ///
655    /// After successful authentication, the client can proceed to create sessions with
656    /// `new_session` without receiving an `auth_required` error.
657    ///
658    /// See protocol docs: [Initialization](https://agentclientprotocol.com/protocol/initialization)
659    AuthenticateRequest(AuthenticateRequest),
660    /// Creates a new conversation session with the agent.
661    ///
662    /// Sessions represent independent conversation contexts with their own history and state.
663    ///
664    /// The agent should:
665    /// - Create a new session context
666    /// - Connect to any specified MCP servers
667    /// - Return a unique session ID for future requests
668    ///
669    /// May return an `auth_required` error if the agent requires authentication.
670    ///
671    /// See protocol docs: [Session Setup](https://agentclientprotocol.com/protocol/session-setup)
672    NewSessionRequest(NewSessionRequest),
673    /// Loads an existing session to resume a previous conversation.
674    ///
675    /// This method is only available if the agent advertises the `loadSession` capability.
676    ///
677    /// The agent should:
678    /// - Restore the session context and conversation history
679    /// - Connect to the specified MCP servers
680    /// - Stream the entire conversation history back to the client via notifications
681    ///
682    /// See protocol docs: [Loading Sessions](https://agentclientprotocol.com/protocol/session-setup#loading-sessions)
683    LoadSessionRequest(LoadSessionRequest),
684    /// Sets the current mode for a session.
685    ///
686    /// Allows switching between different agent modes (e.g., "ask", "architect", "code")
687    /// that affect system prompts, tool availability, and permission behaviors.
688    ///
689    /// The mode must be one of the modes advertised in `availableModes` during session
690    /// creation or loading. Agents may also change modes autonomously and notify the
691    /// client via `current_mode_update` notifications.
692    ///
693    /// This method can be called at any time during a session, whether the Agent is
694    /// idle or actively generating a response.
695    ///
696    /// See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
697    SetSessionModeRequest(SetSessionModeRequest),
698    /// Processes a user prompt within a session.
699    ///
700    /// This method handles the whole lifecycle of a prompt:
701    /// - Receives user messages with optional context (files, images, etc.)
702    /// - Processes the prompt using language models
703    /// - Reports language model content and tool calls to the Clients
704    /// - Requests permission to run tools
705    /// - Executes any requested tool calls
706    /// - Returns when the turn is complete with a stop reason
707    ///
708    /// See protocol docs: [Prompt Turn](https://agentclientprotocol.com/protocol/prompt-turn)
709    PromptRequest(PromptRequest),
710    #[cfg(feature = "unstable")]
711    /// **UNSTABLE**
712    ///
713    /// This capability is not part of the spec yet, and may be removed or changed at any point.
714    ///
715    /// Select a model for a given session.
716    SetSessionModelRequest(SetSessionModelRequest),
717    /// Handles extension method requests from the client.
718    ///
719    /// Extension methods provide a way to add custom functionality while maintaining
720    /// protocol compatibility.
721    ///
722    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
723    ExtMethodRequest(ExtRequest),
724}
725
726/// All possible responses that an agent can send to a client.
727///
728/// This enum is used internally for routing RPC responses. You typically won't need
729/// to use this directly - the responses are handled automatically by the connection.
730///
731/// These are responses to the corresponding `ClientRequest` variants.
732#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
733#[serde(untagged)]
734#[schemars(extend("x-docs-ignore" = true))]
735pub enum AgentResponse {
736    InitializeResponse(InitializeResponse),
737    AuthenticateResponse(#[serde(default)] AuthenticateResponse),
738    NewSessionResponse(NewSessionResponse),
739    LoadSessionResponse(#[serde(default)] LoadSessionResponse),
740    SetSessionModeResponse(#[serde(default)] SetSessionModeResponse),
741    PromptResponse(PromptResponse),
742    #[cfg(feature = "unstable")]
743    SetSessionModelResponse(SetSessionModelResponse),
744    ExtMethodResponse(#[schemars(with = "serde_json::Value")] Arc<RawValue>),
745}
746
747/// All possible notifications that a client can send to an agent.
748///
749/// This enum is used internally for routing RPC notifications. You typically won't need
750/// to use this directly - use the notification methods on the [`Agent`] trait instead.
751///
752/// Notifications do not expect a response.
753#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
754#[serde(untagged)]
755#[schemars(extend("x-docs-ignore" = true))]
756pub enum ClientNotification {
757    /// Cancels ongoing operations for a session.
758    ///
759    /// This is a notification sent by the client to cancel an ongoing prompt turn.
760    ///
761    /// Upon receiving this notification, the Agent SHOULD:
762    /// - Stop all language model requests as soon as possible
763    /// - Abort all tool call invocations in progress
764    /// - Send any pending `session/update` notifications
765    /// - Respond to the original `session/prompt` request with `StopReason::Cancelled`
766    ///
767    /// See protocol docs: [Cancellation](https://agentclientprotocol.com/protocol/prompt-turn#cancellation)
768    CancelNotification(CancelNotification),
769    /// Handles extension notifications from the client.
770    ///
771    /// Extension notifications provide a way to send one-way messages for custom functionality
772    /// while maintaining protocol compatibility.
773    ///
774    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
775    ExtNotification(ExtNotification),
776}
777
778/// Notification to cancel ongoing operations for a session.
779///
780/// See protocol docs: [Cancellation](https://agentclientprotocol.com/protocol/prompt-turn#cancellation)
781#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
782#[schemars(extend("x-side" = "agent", "x-method" = SESSION_CANCEL_METHOD_NAME))]
783#[serde(rename_all = "camelCase")]
784pub struct CancelNotification {
785    /// The ID of the session to cancel operations for.
786    pub session_id: SessionId,
787    /// Extension point for implementations
788    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
789    pub meta: Option<serde_json::Value>,
790}
791
792#[cfg(test)]
793mod test_serialization {
794    use super::*;
795    use serde_json::json;
796
797    #[test]
798    fn test_mcp_server_stdio_serialization() {
799        let server = McpServer::Stdio {
800            name: "test-server".to_string(),
801            command: PathBuf::from("/usr/bin/server"),
802            args: vec!["--port".to_string(), "3000".to_string()],
803            env: vec![EnvVariable {
804                name: "API_KEY".to_string(),
805                value: "secret123".to_string(),
806                meta: None,
807            }],
808        };
809
810        let json = serde_json::to_value(&server).unwrap();
811        assert_eq!(
812            json,
813            json!({
814                "name": "test-server",
815                "command": "/usr/bin/server",
816                "args": ["--port", "3000"],
817                "env": [
818                    {
819                        "name": "API_KEY",
820                        "value": "secret123"
821                    }
822                ]
823            })
824        );
825
826        let deserialized: McpServer = serde_json::from_value(json).unwrap();
827        match deserialized {
828            McpServer::Stdio {
829                name,
830                command,
831                args,
832                env,
833            } => {
834                assert_eq!(name, "test-server");
835                assert_eq!(command, PathBuf::from("/usr/bin/server"));
836                assert_eq!(args, vec!["--port", "3000"]);
837                assert_eq!(env.len(), 1);
838                assert_eq!(env[0].name, "API_KEY");
839                assert_eq!(env[0].value, "secret123");
840            }
841            _ => panic!("Expected Stdio variant"),
842        }
843    }
844
845    #[test]
846    fn test_mcp_server_http_serialization() {
847        let server = McpServer::Http {
848            name: "http-server".to_string(),
849            url: "https://api.example.com".to_string(),
850            headers: vec![
851                HttpHeader {
852                    name: "Authorization".to_string(),
853                    value: "Bearer token123".to_string(),
854                    meta: None,
855                },
856                HttpHeader {
857                    name: "Content-Type".to_string(),
858                    value: "application/json".to_string(),
859                    meta: None,
860                },
861            ],
862        };
863
864        let json = serde_json::to_value(&server).unwrap();
865        assert_eq!(
866            json,
867            json!({
868                "type": "http",
869                "name": "http-server",
870                "url": "https://api.example.com",
871                "headers": [
872                    {
873                        "name": "Authorization",
874                        "value": "Bearer token123"
875                    },
876                    {
877                        "name": "Content-Type",
878                        "value": "application/json"
879                    }
880                ]
881            })
882        );
883
884        let deserialized: McpServer = serde_json::from_value(json).unwrap();
885        match deserialized {
886            McpServer::Http { name, url, headers } => {
887                assert_eq!(name, "http-server");
888                assert_eq!(url, "https://api.example.com");
889                assert_eq!(headers.len(), 2);
890                assert_eq!(headers[0].name, "Authorization");
891                assert_eq!(headers[0].value, "Bearer token123");
892                assert_eq!(headers[1].name, "Content-Type");
893                assert_eq!(headers[1].value, "application/json");
894            }
895            _ => panic!("Expected Http variant"),
896        }
897    }
898
899    #[test]
900    fn test_mcp_server_sse_serialization() {
901        let server = McpServer::Sse {
902            name: "sse-server".to_string(),
903            url: "https://sse.example.com/events".to_string(),
904            headers: vec![HttpHeader {
905                name: "X-API-Key".to_string(),
906                value: "apikey456".to_string(),
907                meta: None,
908            }],
909        };
910
911        let json = serde_json::to_value(&server).unwrap();
912        assert_eq!(
913            json,
914            json!({
915                "type": "sse",
916                "name": "sse-server",
917                "url": "https://sse.example.com/events",
918                "headers": [
919                    {
920                        "name": "X-API-Key",
921                        "value": "apikey456"
922                    }
923                ]
924            })
925        );
926
927        let deserialized: McpServer = serde_json::from_value(json).unwrap();
928        match deserialized {
929            McpServer::Sse { name, url, headers } => {
930                assert_eq!(name, "sse-server");
931                assert_eq!(url, "https://sse.example.com/events");
932                assert_eq!(headers.len(), 1);
933                assert_eq!(headers[0].name, "X-API-Key");
934                assert_eq!(headers[0].value, "apikey456");
935            }
936            _ => panic!("Expected Sse variant"),
937        }
938    }
939}