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