Skip to main content

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};
11
12use crate::{
13    ClientCapabilities, ContentBlock, ExtNotification, ExtRequest, ExtResponse, IntoOption, Meta,
14    ProtocolVersion, SessionId,
15};
16
17// Initialize
18
19/// Request parameters for the initialize method.
20///
21/// Sent by the client to establish connection and negotiate capabilities.
22///
23/// See protocol docs: [Initialization](https://agentclientprotocol.com/protocol/initialization)
24#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
25#[schemars(extend("x-side" = "agent", "x-method" = INITIALIZE_METHOD_NAME))]
26#[serde(rename_all = "camelCase")]
27#[non_exhaustive]
28pub struct InitializeRequest {
29    /// The latest protocol version supported by the client.
30    pub protocol_version: ProtocolVersion,
31    /// Capabilities supported by the client.
32    #[serde(default)]
33    pub client_capabilities: ClientCapabilities,
34    /// Information about the Client name and version sent to the Agent.
35    ///
36    /// Note: in future versions of the protocol, this will be required.
37    #[serde(skip_serializing_if = "Option::is_none")]
38    pub client_info: Option<Implementation>,
39    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
40    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
41    /// these keys.
42    ///
43    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
44    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
45    pub meta: Option<Meta>,
46}
47
48impl InitializeRequest {
49    #[must_use]
50    pub fn new(protocol_version: ProtocolVersion) -> Self {
51        Self {
52            protocol_version,
53            client_capabilities: ClientCapabilities::default(),
54            client_info: None,
55            meta: None,
56        }
57    }
58
59    /// Capabilities supported by the client.
60    #[must_use]
61    pub fn client_capabilities(mut self, client_capabilities: ClientCapabilities) -> Self {
62        self.client_capabilities = client_capabilities;
63        self
64    }
65
66    /// Information about the Client name and version sent to the Agent.
67    #[must_use]
68    pub fn client_info(mut self, client_info: impl IntoOption<Implementation>) -> Self {
69        self.client_info = client_info.into_option();
70        self
71    }
72
73    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
74    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
75    /// these keys.
76    ///
77    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
78    #[must_use]
79    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
80        self.meta = meta.into_option();
81        self
82    }
83}
84
85/// Response to the `initialize` method.
86///
87/// Contains the negotiated protocol version and agent capabilities.
88///
89/// See protocol docs: [Initialization](https://agentclientprotocol.com/protocol/initialization)
90#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
91#[schemars(extend("x-side" = "agent", "x-method" = INITIALIZE_METHOD_NAME))]
92#[serde(rename_all = "camelCase")]
93#[non_exhaustive]
94pub struct InitializeResponse {
95    /// The protocol version the client specified if supported by the agent,
96    /// or the latest protocol version supported by the agent.
97    ///
98    /// The client should disconnect, if it doesn't support this version.
99    pub protocol_version: ProtocolVersion,
100    /// Capabilities supported by the agent.
101    #[serde(default)]
102    pub agent_capabilities: AgentCapabilities,
103    /// Authentication methods supported by the agent.
104    #[serde(default)]
105    pub auth_methods: Vec<AuthMethod>,
106    /// Information about the Agent name and version sent to the Client.
107    ///
108    /// Note: in future versions of the protocol, this will be required.
109    #[serde(skip_serializing_if = "Option::is_none")]
110    pub agent_info: Option<Implementation>,
111    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
112    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
113    /// these keys.
114    ///
115    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
116    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
117    pub meta: Option<Meta>,
118}
119
120impl InitializeResponse {
121    #[must_use]
122    pub fn new(protocol_version: ProtocolVersion) -> Self {
123        Self {
124            protocol_version,
125            agent_capabilities: AgentCapabilities::default(),
126            auth_methods: vec![],
127            agent_info: None,
128            meta: None,
129        }
130    }
131
132    /// Capabilities supported by the agent.
133    #[must_use]
134    pub fn agent_capabilities(mut self, agent_capabilities: AgentCapabilities) -> Self {
135        self.agent_capabilities = agent_capabilities;
136        self
137    }
138
139    /// Authentication methods supported by the agent.
140    #[must_use]
141    pub fn auth_methods(mut self, auth_methods: Vec<AuthMethod>) -> Self {
142        self.auth_methods = auth_methods;
143        self
144    }
145
146    /// Information about the Agent name and version sent to the Client.
147    #[must_use]
148    pub fn agent_info(mut self, agent_info: impl IntoOption<Implementation>) -> Self {
149        self.agent_info = agent_info.into_option();
150        self
151    }
152
153    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
154    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
155    /// these keys.
156    ///
157    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
158    #[must_use]
159    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
160        self.meta = meta.into_option();
161        self
162    }
163}
164
165/// Metadata about the implementation of the client or agent.
166/// Describes the name and version of an MCP implementation, with an optional
167/// title for UI representation.
168#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
169#[serde(rename_all = "camelCase")]
170#[non_exhaustive]
171pub struct Implementation {
172    /// Intended for programmatic or logical use, but can be used as a display
173    /// name fallback if title isn’t present.
174    pub name: String,
175    /// Intended for UI and end-user contexts — optimized to be human-readable
176    /// and easily understood.
177    ///
178    /// If not provided, the name should be used for display.
179    pub title: Option<String>,
180    /// Version of the implementation. Can be displayed to the user or used
181    /// for debugging or metrics purposes. (e.g. "1.0.0").
182    pub version: String,
183    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
184    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
185    /// these keys.
186    ///
187    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
188    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
189    pub meta: Option<Meta>,
190}
191
192impl Implementation {
193    pub fn new(name: impl Into<String>, version: impl Into<String>) -> Self {
194        Self {
195            name: name.into(),
196            title: None,
197            version: version.into(),
198            meta: None,
199        }
200    }
201
202    /// Intended for UI and end-user contexts — optimized to be human-readable
203    /// and easily understood.
204    ///
205    /// If not provided, the name should be used for display.
206    #[must_use]
207    pub fn title(mut self, title: impl IntoOption<String>) -> Self {
208        self.title = title.into_option();
209        self
210    }
211
212    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
213    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
214    /// these keys.
215    ///
216    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
217    #[must_use]
218    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
219        self.meta = meta.into_option();
220        self
221    }
222}
223
224// Authentication
225
226/// Request parameters for the authenticate method.
227///
228/// Specifies which authentication method to use.
229#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
230#[schemars(extend("x-side" = "agent", "x-method" = AUTHENTICATE_METHOD_NAME))]
231#[serde(rename_all = "camelCase")]
232#[non_exhaustive]
233pub struct AuthenticateRequest {
234    /// The ID of the authentication method to use.
235    /// Must be one of the methods advertised in the initialize response.
236    pub method_id: AuthMethodId,
237    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
238    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
239    /// these keys.
240    ///
241    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
242    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
243    pub meta: Option<Meta>,
244}
245
246impl AuthenticateRequest {
247    #[must_use]
248    pub fn new(method_id: impl Into<AuthMethodId>) -> Self {
249        Self {
250            method_id: method_id.into(),
251            meta: None,
252        }
253    }
254
255    #[must_use]
256    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
257        self.meta = meta.into_option();
258        self
259    }
260}
261
262/// Response to the `authenticate` method.
263#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
264#[serde(rename_all = "camelCase")]
265#[schemars(extend("x-side" = "agent", "x-method" = AUTHENTICATE_METHOD_NAME))]
266#[non_exhaustive]
267pub struct AuthenticateResponse {
268    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
269    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
270    /// these keys.
271    ///
272    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
273    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
274    pub meta: Option<Meta>,
275}
276
277impl AuthenticateResponse {
278    #[must_use]
279    pub fn new() -> Self {
280        Self::default()
281    }
282
283    #[must_use]
284    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
285        self.meta = meta.into_option();
286        self
287    }
288}
289
290#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, Display, From)]
291#[serde(transparent)]
292#[from(Arc<str>, String, &'static str)]
293#[non_exhaustive]
294pub struct AuthMethodId(pub Arc<str>);
295
296impl AuthMethodId {
297    pub fn new(id: impl Into<Arc<str>>) -> Self {
298        Self(id.into())
299    }
300}
301
302/// Describes an available authentication method.
303#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
304#[serde(rename_all = "camelCase")]
305#[non_exhaustive]
306pub struct AuthMethod {
307    /// Unique identifier for this authentication method.
308    pub id: AuthMethodId,
309    /// Human-readable name of the authentication method.
310    pub name: String,
311    /// Optional description providing more details about this authentication method.
312    pub description: Option<String>,
313    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
314    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
315    /// these keys.
316    ///
317    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
318    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
319    pub meta: Option<Meta>,
320}
321
322impl AuthMethod {
323    pub fn new(id: impl Into<AuthMethodId>, name: impl Into<String>) -> Self {
324        Self {
325            id: id.into(),
326            name: name.into(),
327            description: None,
328            meta: None,
329        }
330    }
331
332    /// Optional description providing more details about this authentication method.
333    #[must_use]
334    pub fn description(mut self, description: impl IntoOption<String>) -> Self {
335        self.description = description.into_option();
336        self
337    }
338
339    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
340    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
341    /// these keys.
342    ///
343    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
344    #[must_use]
345    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
346        self.meta = meta.into_option();
347        self
348    }
349}
350
351// New session
352
353/// Request parameters for creating a new session.
354///
355/// See protocol docs: [Creating a Session](https://agentclientprotocol.com/protocol/session-setup#creating-a-session)
356#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
357#[schemars(extend("x-side" = "agent", "x-method" = SESSION_NEW_METHOD_NAME))]
358#[serde(rename_all = "camelCase")]
359#[non_exhaustive]
360pub struct NewSessionRequest {
361    /// The working directory for this session. Must be an absolute path.
362    pub cwd: PathBuf,
363    /// List of MCP (Model Context Protocol) servers the agent should connect to.
364    pub mcp_servers: Vec<McpServer>,
365    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
366    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
367    /// these keys.
368    ///
369    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
370    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
371    pub meta: Option<Meta>,
372}
373
374impl NewSessionRequest {
375    pub fn new(cwd: impl Into<PathBuf>) -> Self {
376        Self {
377            cwd: cwd.into(),
378            mcp_servers: vec![],
379            meta: None,
380        }
381    }
382
383    /// List of MCP (Model Context Protocol) servers the agent should connect to.
384    #[must_use]
385    pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
386        self.mcp_servers = mcp_servers;
387        self
388    }
389
390    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
391    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
392    /// these keys.
393    ///
394    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
395    #[must_use]
396    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
397        self.meta = meta.into_option();
398        self
399    }
400}
401
402/// Response from creating a new session.
403///
404/// See protocol docs: [Creating a Session](https://agentclientprotocol.com/protocol/session-setup#creating-a-session)
405#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
406#[schemars(extend("x-side" = "agent", "x-method" = SESSION_NEW_METHOD_NAME))]
407#[serde(rename_all = "camelCase")]
408#[non_exhaustive]
409pub struct NewSessionResponse {
410    /// Unique identifier for the created session.
411    ///
412    /// Used in all subsequent requests for this conversation.
413    pub session_id: SessionId,
414    /// Initial mode state if supported by the Agent
415    ///
416    /// See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
417    #[serde(skip_serializing_if = "Option::is_none")]
418    pub modes: Option<SessionModeState>,
419    /// **UNSTABLE**
420    ///
421    /// This capability is not part of the spec yet, and may be removed or changed at any point.
422    ///
423    /// Initial model state if supported by the Agent
424    #[cfg(feature = "unstable_session_model")]
425    #[serde(skip_serializing_if = "Option::is_none")]
426    pub models: Option<SessionModelState>,
427    /// Initial session configuration options if supported by the Agent.
428    #[serde(skip_serializing_if = "Option::is_none")]
429    pub config_options: Option<Vec<SessionConfigOption>>,
430    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
431    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
432    /// these keys.
433    ///
434    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
435    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
436    pub meta: Option<Meta>,
437}
438
439impl NewSessionResponse {
440    #[must_use]
441    pub fn new(session_id: impl Into<SessionId>) -> Self {
442        Self {
443            session_id: session_id.into(),
444            modes: None,
445            #[cfg(feature = "unstable_session_model")]
446            models: None,
447            config_options: None,
448            meta: None,
449        }
450    }
451
452    /// Initial mode state if supported by the Agent
453    ///
454    /// See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
455    #[must_use]
456    pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
457        self.modes = modes.into_option();
458        self
459    }
460
461    /// **UNSTABLE**
462    ///
463    /// This capability is not part of the spec yet, and may be removed or changed at any point.
464    ///
465    /// Initial model state if supported by the Agent
466    #[cfg(feature = "unstable_session_model")]
467    #[must_use]
468    pub fn models(mut self, models: impl IntoOption<SessionModelState>) -> Self {
469        self.models = models.into_option();
470        self
471    }
472
473    /// Initial session configuration options if supported by the Agent.
474    #[must_use]
475    pub fn config_options(
476        mut self,
477        config_options: impl IntoOption<Vec<SessionConfigOption>>,
478    ) -> Self {
479        self.config_options = config_options.into_option();
480        self
481    }
482
483    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
484    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
485    /// these keys.
486    ///
487    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
488    #[must_use]
489    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
490        self.meta = meta.into_option();
491        self
492    }
493}
494
495// Load session
496
497/// Request parameters for loading an existing session.
498///
499/// Only available if the Agent supports the `loadSession` capability.
500///
501/// See protocol docs: [Loading Sessions](https://agentclientprotocol.com/protocol/session-setup#loading-sessions)
502#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
503#[schemars(extend("x-side" = "agent", "x-method" = SESSION_LOAD_METHOD_NAME))]
504#[serde(rename_all = "camelCase")]
505#[non_exhaustive]
506pub struct LoadSessionRequest {
507    /// List of MCP servers to connect to for this session.
508    pub mcp_servers: Vec<McpServer>,
509    /// The working directory for this session.
510    pub cwd: PathBuf,
511    /// The ID of the session to load.
512    pub session_id: SessionId,
513    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
514    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
515    /// these keys.
516    ///
517    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
518    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
519    pub meta: Option<Meta>,
520}
521
522impl LoadSessionRequest {
523    pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
524        Self {
525            mcp_servers: vec![],
526            cwd: cwd.into(),
527            session_id: session_id.into(),
528            meta: None,
529        }
530    }
531
532    /// List of MCP servers to connect to for this session.
533    #[must_use]
534    pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
535        self.mcp_servers = mcp_servers;
536        self
537    }
538
539    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
540    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
541    /// these keys.
542    ///
543    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
544    #[must_use]
545    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
546        self.meta = meta.into_option();
547        self
548    }
549}
550
551/// Response from loading an existing session.
552#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
553#[schemars(extend("x-side" = "agent", "x-method" = SESSION_LOAD_METHOD_NAME))]
554#[serde(rename_all = "camelCase")]
555#[non_exhaustive]
556pub struct LoadSessionResponse {
557    /// Initial mode state if supported by the Agent
558    ///
559    /// See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
560    #[serde(default, skip_serializing_if = "Option::is_none")]
561    pub modes: Option<SessionModeState>,
562    /// **UNSTABLE**
563    ///
564    /// This capability is not part of the spec yet, and may be removed or changed at any point.
565    ///
566    /// Initial model state if supported by the Agent
567    #[cfg(feature = "unstable_session_model")]
568    #[serde(default, skip_serializing_if = "Option::is_none")]
569    pub models: Option<SessionModelState>,
570    /// Initial session configuration options if supported by the Agent.
571    #[serde(default, skip_serializing_if = "Option::is_none")]
572    pub config_options: Option<Vec<SessionConfigOption>>,
573    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
574    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
575    /// these keys.
576    ///
577    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
578    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
579    pub meta: Option<Meta>,
580}
581
582impl LoadSessionResponse {
583    #[must_use]
584    pub fn new() -> Self {
585        Self::default()
586    }
587
588    /// Initial mode state if supported by the Agent
589    ///
590    /// See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
591    #[must_use]
592    pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
593        self.modes = modes.into_option();
594        self
595    }
596
597    /// **UNSTABLE**
598    ///
599    /// This capability is not part of the spec yet, and may be removed or changed at any point.
600    ///
601    /// Initial model state if supported by the Agent
602    #[cfg(feature = "unstable_session_model")]
603    #[must_use]
604    pub fn models(mut self, models: impl IntoOption<SessionModelState>) -> Self {
605        self.models = models.into_option();
606        self
607    }
608
609    /// Initial session configuration options if supported by the Agent.
610    #[must_use]
611    pub fn config_options(
612        mut self,
613        config_options: impl IntoOption<Vec<SessionConfigOption>>,
614    ) -> Self {
615        self.config_options = config_options.into_option();
616        self
617    }
618
619    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
620    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
621    /// these keys.
622    ///
623    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
624    #[must_use]
625    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
626        self.meta = meta.into_option();
627        self
628    }
629}
630
631// Fork session
632
633/// **UNSTABLE**
634///
635/// This capability is not part of the spec yet, and may be removed or changed at any point.
636///
637/// Request parameters for forking an existing session.
638///
639/// Creates a new session based on the context of an existing one, allowing
640/// operations like generating summaries without affecting the original session's history.
641///
642/// Only available if the Agent supports the `session.fork` capability.
643#[cfg(feature = "unstable_session_fork")]
644#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
645#[schemars(extend("x-side" = "agent", "x-method" = SESSION_FORK_METHOD_NAME))]
646#[serde(rename_all = "camelCase")]
647#[non_exhaustive]
648pub struct ForkSessionRequest {
649    /// The ID of the session to fork.
650    pub session_id: SessionId,
651    /// The working directory for this session.
652    pub cwd: PathBuf,
653    /// List of MCP servers to connect to for this session.
654    #[serde(default, skip_serializing_if = "Vec::is_empty")]
655    pub mcp_servers: Vec<McpServer>,
656    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
657    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
658    /// these keys.
659    ///
660    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
661    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
662    pub meta: Option<Meta>,
663}
664
665#[cfg(feature = "unstable_session_fork")]
666impl ForkSessionRequest {
667    pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
668        Self {
669            session_id: session_id.into(),
670            cwd: cwd.into(),
671            mcp_servers: vec![],
672            meta: None,
673        }
674    }
675
676    /// List of MCP servers to connect to for this session.
677    #[must_use]
678    pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
679        self.mcp_servers = mcp_servers;
680        self
681    }
682
683    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
684    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
685    /// these keys.
686    ///
687    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
688    #[must_use]
689    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
690        self.meta = meta.into_option();
691        self
692    }
693}
694
695/// **UNSTABLE**
696///
697/// This capability is not part of the spec yet, and may be removed or changed at any point.
698///
699/// Response from forking an existing session.
700#[cfg(feature = "unstable_session_fork")]
701#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
702#[schemars(extend("x-side" = "agent", "x-method" = SESSION_FORK_METHOD_NAME))]
703#[serde(rename_all = "camelCase")]
704#[non_exhaustive]
705pub struct ForkSessionResponse {
706    /// Unique identifier for the newly created forked session.
707    pub session_id: SessionId,
708    /// Initial mode state if supported by the Agent
709    ///
710    /// See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
711    #[serde(skip_serializing_if = "Option::is_none")]
712    pub modes: Option<SessionModeState>,
713    /// **UNSTABLE**
714    ///
715    /// This capability is not part of the spec yet, and may be removed or changed at any point.
716    ///
717    /// Initial model state if supported by the Agent
718    #[cfg(feature = "unstable_session_model")]
719    #[serde(skip_serializing_if = "Option::is_none")]
720    pub models: Option<SessionModelState>,
721    /// Initial session configuration options if supported by the Agent.
722    #[serde(skip_serializing_if = "Option::is_none")]
723    pub config_options: Option<Vec<SessionConfigOption>>,
724    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
725    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
726    /// these keys.
727    ///
728    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
729    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
730    pub meta: Option<Meta>,
731}
732
733#[cfg(feature = "unstable_session_fork")]
734impl ForkSessionResponse {
735    #[must_use]
736    pub fn new(session_id: impl Into<SessionId>) -> Self {
737        Self {
738            session_id: session_id.into(),
739            modes: None,
740            #[cfg(feature = "unstable_session_model")]
741            models: None,
742            config_options: None,
743            meta: None,
744        }
745    }
746
747    /// Initial mode state if supported by the Agent
748    ///
749    /// See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
750    #[must_use]
751    pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
752        self.modes = modes.into_option();
753        self
754    }
755
756    /// **UNSTABLE**
757    ///
758    /// This capability is not part of the spec yet, and may be removed or changed at any point.
759    ///
760    /// Initial model state if supported by the Agent
761    #[cfg(feature = "unstable_session_model")]
762    #[must_use]
763    pub fn models(mut self, models: impl IntoOption<SessionModelState>) -> Self {
764        self.models = models.into_option();
765        self
766    }
767
768    /// Initial session configuration options if supported by the Agent.
769    #[must_use]
770    pub fn config_options(
771        mut self,
772        config_options: impl IntoOption<Vec<SessionConfigOption>>,
773    ) -> Self {
774        self.config_options = config_options.into_option();
775        self
776    }
777
778    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
779    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
780    /// these keys.
781    ///
782    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
783    #[must_use]
784    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
785        self.meta = meta.into_option();
786        self
787    }
788}
789
790// Resume session
791
792/// **UNSTABLE**
793///
794/// This capability is not part of the spec yet, and may be removed or changed at any point.
795///
796/// Request parameters for resuming an existing session.
797///
798/// Resumes an existing session without returning previous messages (unlike `session/load`).
799/// This is useful for agents that can resume sessions but don't implement full session loading.
800///
801/// Only available if the Agent supports the `session.resume` capability.
802#[cfg(feature = "unstable_session_resume")]
803#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
804#[schemars(extend("x-side" = "agent", "x-method" = SESSION_RESUME_METHOD_NAME))]
805#[serde(rename_all = "camelCase")]
806#[non_exhaustive]
807pub struct ResumeSessionRequest {
808    /// The ID of the session to resume.
809    pub session_id: SessionId,
810    /// The working directory for this session.
811    pub cwd: PathBuf,
812    /// List of MCP servers to connect to for this session.
813    #[serde(default, skip_serializing_if = "Vec::is_empty")]
814    pub mcp_servers: Vec<McpServer>,
815    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
816    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
817    /// these keys.
818    ///
819    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
820    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
821    pub meta: Option<Meta>,
822}
823
824#[cfg(feature = "unstable_session_resume")]
825impl ResumeSessionRequest {
826    pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
827        Self {
828            session_id: session_id.into(),
829            cwd: cwd.into(),
830            mcp_servers: vec![],
831            meta: None,
832        }
833    }
834
835    /// List of MCP servers to connect to for this session.
836    #[must_use]
837    pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
838        self.mcp_servers = mcp_servers;
839        self
840    }
841
842    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
843    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
844    /// these keys.
845    ///
846    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
847    #[must_use]
848    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
849        self.meta = meta.into_option();
850        self
851    }
852}
853
854/// **UNSTABLE**
855///
856/// This capability is not part of the spec yet, and may be removed or changed at any point.
857///
858/// Response from resuming an existing session.
859#[cfg(feature = "unstable_session_resume")]
860#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
861#[schemars(extend("x-side" = "agent", "x-method" = SESSION_RESUME_METHOD_NAME))]
862#[serde(rename_all = "camelCase")]
863#[non_exhaustive]
864pub struct ResumeSessionResponse {
865    /// Initial mode state if supported by the Agent
866    ///
867    /// See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
868    #[serde(default, skip_serializing_if = "Option::is_none")]
869    pub modes: Option<SessionModeState>,
870    /// **UNSTABLE**
871    ///
872    /// This capability is not part of the spec yet, and may be removed or changed at any point.
873    ///
874    /// Initial model state if supported by the Agent
875    #[cfg(feature = "unstable_session_model")]
876    #[serde(default, skip_serializing_if = "Option::is_none")]
877    pub models: Option<SessionModelState>,
878    /// Initial session configuration options if supported by the Agent.
879    #[serde(default, skip_serializing_if = "Option::is_none")]
880    pub config_options: Option<Vec<SessionConfigOption>>,
881    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
882    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
883    /// these keys.
884    ///
885    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
886    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
887    pub meta: Option<Meta>,
888}
889
890#[cfg(feature = "unstable_session_resume")]
891impl ResumeSessionResponse {
892    #[must_use]
893    pub fn new() -> Self {
894        Self::default()
895    }
896
897    /// Initial mode state if supported by the Agent
898    ///
899    /// See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
900    #[must_use]
901    pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
902        self.modes = modes.into_option();
903        self
904    }
905
906    /// **UNSTABLE**
907    ///
908    /// This capability is not part of the spec yet, and may be removed or changed at any point.
909    ///
910    /// Initial model state if supported by the Agent
911    #[cfg(feature = "unstable_session_model")]
912    #[must_use]
913    pub fn models(mut self, models: impl IntoOption<SessionModelState>) -> Self {
914        self.models = models.into_option();
915        self
916    }
917
918    /// Initial session configuration options if supported by the Agent.
919    #[must_use]
920    pub fn config_options(
921        mut self,
922        config_options: impl IntoOption<Vec<SessionConfigOption>>,
923    ) -> Self {
924        self.config_options = config_options.into_option();
925        self
926    }
927
928    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
929    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
930    /// these keys.
931    ///
932    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
933    #[must_use]
934    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
935        self.meta = meta.into_option();
936        self
937    }
938}
939
940// List sessions
941
942/// **UNSTABLE**
943///
944/// This capability is not part of the spec yet, and may be removed or changed at any point.
945///
946/// Request parameters for listing existing sessions.
947///
948/// Only available if the Agent supports the `listSessions` capability.
949#[cfg(feature = "unstable_session_list")]
950#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
951#[schemars(extend("x-side" = "agent", "x-method" = SESSION_LIST_METHOD_NAME))]
952#[serde(rename_all = "camelCase")]
953#[non_exhaustive]
954pub struct ListSessionsRequest {
955    /// Filter sessions by working directory. Must be an absolute path.
956    #[serde(skip_serializing_if = "Option::is_none")]
957    pub cwd: Option<PathBuf>,
958    /// Opaque cursor token from a previous response's nextCursor field for cursor-based pagination
959    #[serde(skip_serializing_if = "Option::is_none")]
960    pub cursor: Option<String>,
961    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
962    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
963    /// these keys.
964    ///
965    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
966    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
967    pub meta: Option<Meta>,
968}
969
970#[cfg(feature = "unstable_session_list")]
971impl ListSessionsRequest {
972    #[must_use]
973    pub fn new() -> Self {
974        Self::default()
975    }
976
977    /// Filter sessions by working directory. Must be an absolute path.
978    #[must_use]
979    pub fn cwd(mut self, cwd: impl IntoOption<PathBuf>) -> Self {
980        self.cwd = cwd.into_option();
981        self
982    }
983
984    /// Opaque cursor token from a previous response's nextCursor field for cursor-based pagination
985    #[must_use]
986    pub fn cursor(mut self, cursor: impl IntoOption<String>) -> Self {
987        self.cursor = cursor.into_option();
988        self
989    }
990
991    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
992    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
993    /// these keys.
994    ///
995    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
996    #[must_use]
997    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
998        self.meta = meta.into_option();
999        self
1000    }
1001}
1002
1003/// **UNSTABLE**
1004///
1005/// This capability is not part of the spec yet, and may be removed or changed at any point.
1006///
1007/// Response from listing sessions.
1008#[cfg(feature = "unstable_session_list")]
1009#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1010#[schemars(extend("x-side" = "agent", "x-method" = SESSION_LIST_METHOD_NAME))]
1011#[serde(rename_all = "camelCase")]
1012#[non_exhaustive]
1013pub struct ListSessionsResponse {
1014    /// Array of session information objects
1015    pub sessions: Vec<SessionInfo>,
1016    /// Opaque cursor token. If present, pass this in the next request's cursor parameter
1017    /// to fetch the next page. If absent, there are no more results.
1018    #[serde(skip_serializing_if = "Option::is_none")]
1019    pub next_cursor: Option<String>,
1020    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1021    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1022    /// these keys.
1023    ///
1024    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1025    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1026    pub meta: Option<Meta>,
1027}
1028
1029#[cfg(feature = "unstable_session_list")]
1030impl ListSessionsResponse {
1031    #[must_use]
1032    pub fn new(sessions: Vec<SessionInfo>) -> Self {
1033        Self {
1034            sessions,
1035            next_cursor: None,
1036            meta: None,
1037        }
1038    }
1039
1040    #[must_use]
1041    pub fn next_cursor(mut self, next_cursor: impl IntoOption<String>) -> Self {
1042        self.next_cursor = next_cursor.into_option();
1043        self
1044    }
1045
1046    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1047    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1048    /// these keys.
1049    ///
1050    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1051    #[must_use]
1052    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1053        self.meta = meta.into_option();
1054        self
1055    }
1056}
1057
1058/// **UNSTABLE**
1059///
1060/// This capability is not part of the spec yet, and may be removed or changed at any point.
1061///
1062/// Information about a session returned by session/list
1063#[cfg(feature = "unstable_session_list")]
1064#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1065#[serde(rename_all = "camelCase")]
1066#[non_exhaustive]
1067pub struct SessionInfo {
1068    /// Unique identifier for the session
1069    pub session_id: SessionId,
1070    /// The working directory for this session. Must be an absolute path.
1071    pub cwd: PathBuf,
1072    /// Human-readable title for the session
1073    #[serde(skip_serializing_if = "Option::is_none")]
1074    pub title: Option<String>,
1075    /// ISO 8601 timestamp of last activity
1076    #[serde(skip_serializing_if = "Option::is_none")]
1077    pub updated_at: Option<String>,
1078    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1079    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1080    /// these keys.
1081    ///
1082    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1083    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1084    pub meta: Option<Meta>,
1085}
1086
1087#[cfg(feature = "unstable_session_list")]
1088impl SessionInfo {
1089    pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1090        Self {
1091            session_id: session_id.into(),
1092            cwd: cwd.into(),
1093            title: None,
1094            updated_at: None,
1095            meta: None,
1096        }
1097    }
1098
1099    /// Human-readable title for the session
1100    #[must_use]
1101    pub fn title(mut self, title: impl IntoOption<String>) -> Self {
1102        self.title = title.into_option();
1103        self
1104    }
1105
1106    /// ISO 8601 timestamp of last activity
1107    #[must_use]
1108    pub fn updated_at(mut self, updated_at: impl IntoOption<String>) -> Self {
1109        self.updated_at = updated_at.into_option();
1110        self
1111    }
1112
1113    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1114    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1115    /// these keys.
1116    ///
1117    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1118    #[must_use]
1119    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1120        self.meta = meta.into_option();
1121        self
1122    }
1123}
1124
1125// Session modes
1126
1127/// The set of modes and the one currently active.
1128#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1129#[serde(rename_all = "camelCase")]
1130#[non_exhaustive]
1131pub struct SessionModeState {
1132    /// The current mode the Agent is in.
1133    pub current_mode_id: SessionModeId,
1134    /// The set of modes that the Agent can operate in
1135    pub available_modes: Vec<SessionMode>,
1136    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1137    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1138    /// these keys.
1139    ///
1140    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1141    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1142    pub meta: Option<Meta>,
1143}
1144
1145impl SessionModeState {
1146    #[must_use]
1147    pub fn new(
1148        current_mode_id: impl Into<SessionModeId>,
1149        available_modes: Vec<SessionMode>,
1150    ) -> Self {
1151        Self {
1152            current_mode_id: current_mode_id.into(),
1153            available_modes,
1154            meta: None,
1155        }
1156    }
1157
1158    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1159    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1160    /// these keys.
1161    ///
1162    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1163    #[must_use]
1164    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1165        self.meta = meta.into_option();
1166        self
1167    }
1168}
1169
1170/// A mode the agent can operate in.
1171///
1172/// See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
1173#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1174#[serde(rename_all = "camelCase")]
1175#[non_exhaustive]
1176pub struct SessionMode {
1177    pub id: SessionModeId,
1178    pub name: String,
1179    #[serde(default, skip_serializing_if = "Option::is_none")]
1180    pub description: Option<String>,
1181    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1182    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1183    /// these keys.
1184    ///
1185    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1186    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1187    pub meta: Option<Meta>,
1188}
1189
1190impl SessionMode {
1191    pub fn new(id: impl Into<SessionModeId>, name: impl Into<String>) -> Self {
1192        Self {
1193            id: id.into(),
1194            name: name.into(),
1195            description: None,
1196            meta: None,
1197        }
1198    }
1199
1200    #[must_use]
1201    pub fn description(mut self, description: impl IntoOption<String>) -> Self {
1202        self.description = description.into_option();
1203        self
1204    }
1205
1206    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1207    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1208    /// these keys.
1209    ///
1210    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1211    #[must_use]
1212    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1213        self.meta = meta.into_option();
1214        self
1215    }
1216}
1217
1218/// Unique identifier for a Session Mode.
1219#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, From, Display)]
1220#[serde(transparent)]
1221#[from(Arc<str>, String, &'static str)]
1222#[non_exhaustive]
1223pub struct SessionModeId(pub Arc<str>);
1224
1225impl SessionModeId {
1226    pub fn new(id: impl Into<Arc<str>>) -> Self {
1227        Self(id.into())
1228    }
1229}
1230
1231/// Request parameters for setting a session mode.
1232#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1233#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_MODE_METHOD_NAME))]
1234#[serde(rename_all = "camelCase")]
1235#[non_exhaustive]
1236pub struct SetSessionModeRequest {
1237    /// The ID of the session to set the mode for.
1238    pub session_id: SessionId,
1239    /// The ID of the mode to set.
1240    pub mode_id: SessionModeId,
1241    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1242    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1243    /// these keys.
1244    ///
1245    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1246    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1247    pub meta: Option<Meta>,
1248}
1249
1250impl SetSessionModeRequest {
1251    #[must_use]
1252    pub fn new(session_id: impl Into<SessionId>, mode_id: impl Into<SessionModeId>) -> Self {
1253        Self {
1254            session_id: session_id.into(),
1255            mode_id: mode_id.into(),
1256            meta: None,
1257        }
1258    }
1259
1260    #[must_use]
1261    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1262        self.meta = meta.into_option();
1263        self
1264    }
1265}
1266
1267/// Response to `session/set_mode` method.
1268#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1269#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_MODE_METHOD_NAME))]
1270#[serde(rename_all = "camelCase")]
1271#[non_exhaustive]
1272pub struct SetSessionModeResponse {
1273    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1274    pub meta: Option<Meta>,
1275}
1276
1277impl SetSessionModeResponse {
1278    #[must_use]
1279    pub fn new() -> Self {
1280        Self::default()
1281    }
1282
1283    #[must_use]
1284    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1285        self.meta = meta.into_option();
1286        self
1287    }
1288}
1289
1290// Session config options
1291
1292/// Unique identifier for a session configuration option.
1293#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, From, Display)]
1294#[serde(transparent)]
1295#[from(Arc<str>, String, &'static str)]
1296#[non_exhaustive]
1297pub struct SessionConfigId(pub Arc<str>);
1298
1299impl SessionConfigId {
1300    pub fn new(id: impl Into<Arc<str>>) -> Self {
1301        Self(id.into())
1302    }
1303}
1304
1305/// Unique identifier for a session configuration option value.
1306#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, From, Display)]
1307#[serde(transparent)]
1308#[from(Arc<str>, String, &'static str)]
1309#[non_exhaustive]
1310pub struct SessionConfigValueId(pub Arc<str>);
1311
1312impl SessionConfigValueId {
1313    pub fn new(id: impl Into<Arc<str>>) -> Self {
1314        Self(id.into())
1315    }
1316}
1317
1318/// Unique identifier for a session configuration option value group.
1319#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, From, Display)]
1320#[serde(transparent)]
1321#[from(Arc<str>, String, &'static str)]
1322#[non_exhaustive]
1323pub struct SessionConfigGroupId(pub Arc<str>);
1324
1325impl SessionConfigGroupId {
1326    pub fn new(id: impl Into<Arc<str>>) -> Self {
1327        Self(id.into())
1328    }
1329}
1330
1331/// A possible value for a session configuration option.
1332#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1333#[serde(rename_all = "camelCase")]
1334#[non_exhaustive]
1335pub struct SessionConfigSelectOption {
1336    /// Unique identifier for this option value.
1337    pub value: SessionConfigValueId,
1338    /// Human-readable label for this option value.
1339    pub name: String,
1340    /// Optional description for this option value.
1341    #[serde(default, skip_serializing_if = "Option::is_none")]
1342    pub description: Option<String>,
1343    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1344    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1345    /// these keys.
1346    ///
1347    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1348    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1349    pub meta: Option<Meta>,
1350}
1351
1352impl SessionConfigSelectOption {
1353    #[must_use]
1354    pub fn new(value: impl Into<SessionConfigValueId>, name: impl Into<String>) -> Self {
1355        Self {
1356            value: value.into(),
1357            name: name.into(),
1358            description: None,
1359            meta: None,
1360        }
1361    }
1362
1363    #[must_use]
1364    pub fn description(mut self, description: impl IntoOption<String>) -> Self {
1365        self.description = description.into_option();
1366        self
1367    }
1368
1369    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1370    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1371    /// these keys.
1372    ///
1373    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1374    #[must_use]
1375    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1376        self.meta = meta.into_option();
1377        self
1378    }
1379}
1380
1381/// A group of possible values for a session configuration option.
1382#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1383#[serde(rename_all = "camelCase")]
1384#[non_exhaustive]
1385pub struct SessionConfigSelectGroup {
1386    /// Unique identifier for this group.
1387    pub group: SessionConfigGroupId,
1388    /// Human-readable label for this group.
1389    pub name: String,
1390    /// The set of option values in this group.
1391    pub options: Vec<SessionConfigSelectOption>,
1392    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1393    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1394    /// these keys.
1395    ///
1396    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1397    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1398    pub meta: Option<Meta>,
1399}
1400
1401impl SessionConfigSelectGroup {
1402    #[must_use]
1403    pub fn new(
1404        group: impl Into<SessionConfigGroupId>,
1405        name: impl Into<String>,
1406        options: Vec<SessionConfigSelectOption>,
1407    ) -> Self {
1408        Self {
1409            group: group.into(),
1410            name: name.into(),
1411            options,
1412            meta: None,
1413        }
1414    }
1415
1416    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1417    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1418    /// these keys.
1419    ///
1420    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1421    #[must_use]
1422    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1423        self.meta = meta.into_option();
1424        self
1425    }
1426}
1427
1428/// Possible values for a session configuration option.
1429#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1430#[serde(untagged)]
1431#[non_exhaustive]
1432pub enum SessionConfigSelectOptions {
1433    /// A flat list of options with no grouping.
1434    Ungrouped(Vec<SessionConfigSelectOption>),
1435    /// A list of options grouped under headers.
1436    Grouped(Vec<SessionConfigSelectGroup>),
1437}
1438
1439impl From<Vec<SessionConfigSelectOption>> for SessionConfigSelectOptions {
1440    fn from(options: Vec<SessionConfigSelectOption>) -> Self {
1441        SessionConfigSelectOptions::Ungrouped(options)
1442    }
1443}
1444
1445impl From<Vec<SessionConfigSelectGroup>> for SessionConfigSelectOptions {
1446    fn from(groups: Vec<SessionConfigSelectGroup>) -> Self {
1447        SessionConfigSelectOptions::Grouped(groups)
1448    }
1449}
1450
1451/// A single-value selector (dropdown) session configuration option payload.
1452#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1453#[serde(rename_all = "camelCase")]
1454#[non_exhaustive]
1455pub struct SessionConfigSelect {
1456    /// The currently selected value.
1457    pub current_value: SessionConfigValueId,
1458    /// The set of selectable options.
1459    pub options: SessionConfigSelectOptions,
1460}
1461
1462impl SessionConfigSelect {
1463    #[must_use]
1464    pub fn new(
1465        current_value: impl Into<SessionConfigValueId>,
1466        options: impl Into<SessionConfigSelectOptions>,
1467    ) -> Self {
1468        Self {
1469            current_value: current_value.into(),
1470            options: options.into(),
1471        }
1472    }
1473}
1474
1475/// Semantic category for a session configuration option.
1476///
1477/// This is intended to help Clients distinguish broadly common selectors (e.g. model selector vs
1478/// session mode selector vs thought/reasoning level) for UX purposes (keyboard shortcuts, icons,
1479/// placement). It MUST NOT be required for correctness. Clients MUST handle missing or unknown
1480/// categories gracefully.
1481///
1482/// Category names beginning with `_` are free for custom use, like other ACP extension methods.
1483/// Category names that do not begin with `_` are reserved for the ACP spec.
1484#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1485#[serde(rename_all = "snake_case")]
1486#[non_exhaustive]
1487pub enum SessionConfigOptionCategory {
1488    /// Session mode selector.
1489    Mode,
1490    /// Model selector.
1491    Model,
1492    /// Thought/reasoning level selector.
1493    ThoughtLevel,
1494    /// Unknown / uncategorized selector.
1495    #[serde(untagged)]
1496    Other(String),
1497}
1498
1499/// Type-specific session configuration option payload.
1500#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1501#[serde(tag = "type", rename_all = "snake_case")]
1502#[schemars(extend("discriminator" = {"propertyName": "type"}))]
1503#[non_exhaustive]
1504pub enum SessionConfigKind {
1505    /// Single-value selector (dropdown).
1506    Select(SessionConfigSelect),
1507}
1508
1509/// A session configuration option selector and its current state.
1510#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1511#[serde(rename_all = "camelCase")]
1512#[non_exhaustive]
1513pub struct SessionConfigOption {
1514    /// Unique identifier for the configuration option.
1515    pub id: SessionConfigId,
1516    /// Human-readable label for the option.
1517    pub name: String,
1518    /// Optional description for the Client to display to the user.
1519    #[serde(default, skip_serializing_if = "Option::is_none")]
1520    pub description: Option<String>,
1521    /// Optional semantic category for this option (UX only).
1522    #[serde(default, skip_serializing_if = "Option::is_none")]
1523    pub category: Option<SessionConfigOptionCategory>,
1524    /// Type-specific fields for this configuration option.
1525    #[serde(flatten)]
1526    pub kind: SessionConfigKind,
1527    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1528    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1529    /// these keys.
1530    ///
1531    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1532    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1533    pub meta: Option<Meta>,
1534}
1535
1536impl SessionConfigOption {
1537    #[must_use]
1538    pub fn new(
1539        id: impl Into<SessionConfigId>,
1540        name: impl Into<String>,
1541        kind: SessionConfigKind,
1542    ) -> Self {
1543        Self {
1544            id: id.into(),
1545            name: name.into(),
1546            description: None,
1547            category: None,
1548            kind,
1549            meta: None,
1550        }
1551    }
1552
1553    #[must_use]
1554    pub fn select(
1555        id: impl Into<SessionConfigId>,
1556        name: impl Into<String>,
1557        current_value: impl Into<SessionConfigValueId>,
1558        options: impl Into<SessionConfigSelectOptions>,
1559    ) -> Self {
1560        Self::new(
1561            id,
1562            name,
1563            SessionConfigKind::Select(SessionConfigSelect::new(current_value, options)),
1564        )
1565    }
1566
1567    #[must_use]
1568    pub fn description(mut self, description: impl IntoOption<String>) -> Self {
1569        self.description = description.into_option();
1570        self
1571    }
1572
1573    #[must_use]
1574    pub fn category(mut self, category: impl IntoOption<SessionConfigOptionCategory>) -> Self {
1575        self.category = category.into_option();
1576        self
1577    }
1578
1579    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1580    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1581    /// these keys.
1582    ///
1583    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1584    #[must_use]
1585    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1586        self.meta = meta.into_option();
1587        self
1588    }
1589}
1590
1591/// Request parameters for setting a session configuration option.
1592#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1593#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_CONFIG_OPTION_METHOD_NAME))]
1594#[serde(rename_all = "camelCase")]
1595#[non_exhaustive]
1596pub struct SetSessionConfigOptionRequest {
1597    /// The ID of the session to set the configuration option for.
1598    pub session_id: SessionId,
1599    /// The ID of the configuration option to set.
1600    pub config_id: SessionConfigId,
1601    /// The ID of the configuration option value to set.
1602    pub value: SessionConfigValueId,
1603    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1604    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1605    /// these keys.
1606    ///
1607    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1608    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1609    pub meta: Option<Meta>,
1610}
1611
1612impl SetSessionConfigOptionRequest {
1613    #[must_use]
1614    pub fn new(
1615        session_id: impl Into<SessionId>,
1616        config_id: impl Into<SessionConfigId>,
1617        value: impl Into<SessionConfigValueId>,
1618    ) -> Self {
1619        Self {
1620            session_id: session_id.into(),
1621            config_id: config_id.into(),
1622            value: value.into(),
1623            meta: None,
1624        }
1625    }
1626
1627    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1628    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1629    /// these keys.
1630    ///
1631    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1632    #[must_use]
1633    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1634        self.meta = meta.into_option();
1635        self
1636    }
1637}
1638
1639/// Response to `session/set_config_option` method.
1640#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1641#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_CONFIG_OPTION_METHOD_NAME))]
1642#[serde(rename_all = "camelCase")]
1643#[non_exhaustive]
1644pub struct SetSessionConfigOptionResponse {
1645    /// The full set of configuration options and their current values.
1646    pub config_options: Vec<SessionConfigOption>,
1647    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1648    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1649    /// these keys.
1650    ///
1651    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1652    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1653    pub meta: Option<Meta>,
1654}
1655
1656impl SetSessionConfigOptionResponse {
1657    #[must_use]
1658    pub fn new(config_options: Vec<SessionConfigOption>) -> Self {
1659        Self {
1660            config_options,
1661            meta: None,
1662        }
1663    }
1664
1665    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1666    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1667    /// these keys.
1668    ///
1669    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1670    #[must_use]
1671    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1672        self.meta = meta.into_option();
1673        self
1674    }
1675}
1676
1677// MCP
1678
1679/// Configuration for connecting to an MCP (Model Context Protocol) server.
1680///
1681/// MCP servers provide tools and context that the agent can use when
1682/// processing prompts.
1683///
1684/// See protocol docs: [MCP Servers](https://agentclientprotocol.com/protocol/session-setup#mcp-servers)
1685#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1686#[serde(tag = "type", rename_all = "snake_case")]
1687#[non_exhaustive]
1688pub enum McpServer {
1689    /// HTTP transport configuration
1690    ///
1691    /// Only available when the Agent capabilities indicate `mcp_capabilities.http` is `true`.
1692    Http(McpServerHttp),
1693    /// SSE transport configuration
1694    ///
1695    /// Only available when the Agent capabilities indicate `mcp_capabilities.sse` is `true`.
1696    Sse(McpServerSse),
1697    /// Stdio transport configuration
1698    ///
1699    /// All Agents MUST support this transport.
1700    #[serde(untagged)]
1701    Stdio(McpServerStdio),
1702}
1703
1704/// HTTP transport configuration for MCP.
1705#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1706#[serde(rename_all = "camelCase")]
1707#[non_exhaustive]
1708pub struct McpServerHttp {
1709    /// Human-readable name identifying this MCP server.
1710    pub name: String,
1711    /// URL to the MCP server.
1712    pub url: String,
1713    /// HTTP headers to set when making requests to the MCP server.
1714    pub headers: Vec<HttpHeader>,
1715    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1716    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1717    /// these keys.
1718    ///
1719    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1720    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1721    pub meta: Option<Meta>,
1722}
1723
1724impl McpServerHttp {
1725    pub fn new(name: impl Into<String>, url: impl Into<String>) -> Self {
1726        Self {
1727            name: name.into(),
1728            url: url.into(),
1729            headers: Vec::new(),
1730            meta: None,
1731        }
1732    }
1733
1734    /// HTTP headers to set when making requests to the MCP server.
1735    #[must_use]
1736    pub fn headers(mut self, headers: Vec<HttpHeader>) -> Self {
1737        self.headers = headers;
1738        self
1739    }
1740
1741    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1742    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1743    /// these keys.
1744    ///
1745    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1746    #[must_use]
1747    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1748        self.meta = meta.into_option();
1749        self
1750    }
1751}
1752
1753/// SSE transport configuration for MCP.
1754#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1755#[serde(rename_all = "camelCase")]
1756#[non_exhaustive]
1757pub struct McpServerSse {
1758    /// Human-readable name identifying this MCP server.
1759    pub name: String,
1760    /// URL to the MCP server.
1761    pub url: String,
1762    /// HTTP headers to set when making requests to the MCP server.
1763    pub headers: Vec<HttpHeader>,
1764    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1765    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1766    /// these keys.
1767    ///
1768    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1769    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1770    pub meta: Option<Meta>,
1771}
1772
1773impl McpServerSse {
1774    pub fn new(name: impl Into<String>, url: impl Into<String>) -> Self {
1775        Self {
1776            name: name.into(),
1777            url: url.into(),
1778            headers: Vec::new(),
1779            meta: None,
1780        }
1781    }
1782
1783    /// HTTP headers to set when making requests to the MCP server.
1784    #[must_use]
1785    pub fn headers(mut self, headers: Vec<HttpHeader>) -> Self {
1786        self.headers = headers;
1787        self
1788    }
1789
1790    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1791    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1792    /// these keys.
1793    ///
1794    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1795    #[must_use]
1796    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1797        self.meta = meta.into_option();
1798        self
1799    }
1800}
1801
1802/// Stdio transport configuration for MCP.
1803#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1804#[serde(rename_all = "camelCase")]
1805#[non_exhaustive]
1806pub struct McpServerStdio {
1807    /// Human-readable name identifying this MCP server.
1808    pub name: String,
1809    /// Path to the MCP server executable.
1810    pub command: PathBuf,
1811    /// Command-line arguments to pass to the MCP server.
1812    pub args: Vec<String>,
1813    /// Environment variables to set when launching the MCP server.
1814    pub env: Vec<EnvVariable>,
1815    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1816    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1817    /// these keys.
1818    ///
1819    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1820    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1821    pub meta: Option<Meta>,
1822}
1823
1824impl McpServerStdio {
1825    pub fn new(name: impl Into<String>, command: impl Into<PathBuf>) -> Self {
1826        Self {
1827            name: name.into(),
1828            command: command.into(),
1829            args: Vec::new(),
1830            env: Vec::new(),
1831            meta: None,
1832        }
1833    }
1834
1835    /// Command-line arguments to pass to the MCP server.
1836    #[must_use]
1837    pub fn args(mut self, args: Vec<String>) -> Self {
1838        self.args = args;
1839        self
1840    }
1841
1842    /// Environment variables to set when launching the MCP server.
1843    #[must_use]
1844    pub fn env(mut self, env: Vec<EnvVariable>) -> Self {
1845        self.env = env;
1846        self
1847    }
1848
1849    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1850    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1851    /// these keys.
1852    ///
1853    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1854    #[must_use]
1855    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1856        self.meta = meta.into_option();
1857        self
1858    }
1859}
1860
1861/// An environment variable to set when launching an MCP server.
1862#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1863#[serde(rename_all = "camelCase")]
1864#[non_exhaustive]
1865pub struct EnvVariable {
1866    /// The name of the environment variable.
1867    pub name: String,
1868    /// The value to set for the environment variable.
1869    pub value: String,
1870    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1871    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1872    /// these keys.
1873    ///
1874    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1875    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1876    pub meta: Option<Meta>,
1877}
1878
1879impl EnvVariable {
1880    pub fn new(name: impl Into<String>, value: impl Into<String>) -> Self {
1881        Self {
1882            name: name.into(),
1883            value: value.into(),
1884            meta: None,
1885        }
1886    }
1887
1888    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1889    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1890    /// these keys.
1891    ///
1892    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1893    #[must_use]
1894    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1895        self.meta = meta.into_option();
1896        self
1897    }
1898}
1899
1900/// An HTTP header to set when making requests to the MCP server.
1901#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1902#[serde(rename_all = "camelCase")]
1903#[non_exhaustive]
1904pub struct HttpHeader {
1905    /// The name of the HTTP header.
1906    pub name: String,
1907    /// The value to set for the HTTP header.
1908    pub value: String,
1909    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1910    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1911    /// these keys.
1912    ///
1913    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1914    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1915    pub meta: Option<Meta>,
1916}
1917
1918impl HttpHeader {
1919    pub fn new(name: impl Into<String>, value: impl Into<String>) -> Self {
1920        Self {
1921            name: name.into(),
1922            value: value.into(),
1923            meta: None,
1924        }
1925    }
1926
1927    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1928    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1929    /// these keys.
1930    ///
1931    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1932    #[must_use]
1933    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1934        self.meta = meta.into_option();
1935        self
1936    }
1937}
1938
1939// Prompt
1940
1941/// Request parameters for sending a user prompt to the agent.
1942///
1943/// Contains the user's message and any additional context.
1944///
1945/// See protocol docs: [User Message](https://agentclientprotocol.com/protocol/prompt-turn#1-user-message)
1946#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
1947#[schemars(extend("x-side" = "agent", "x-method" = SESSION_PROMPT_METHOD_NAME))]
1948#[serde(rename_all = "camelCase")]
1949#[non_exhaustive]
1950pub struct PromptRequest {
1951    /// The ID of the session to send this user message to
1952    pub session_id: SessionId,
1953    /// The blocks of content that compose the user's message.
1954    ///
1955    /// As a baseline, the Agent MUST support [`ContentBlock::Text`] and [`ContentBlock::ResourceLink`],
1956    /// while other variants are optionally enabled via [`PromptCapabilities`].
1957    ///
1958    /// The Client MUST adapt its interface according to [`PromptCapabilities`].
1959    ///
1960    /// The client MAY include referenced pieces of context as either
1961    /// [`ContentBlock::Resource`] or [`ContentBlock::ResourceLink`].
1962    ///
1963    /// When available, [`ContentBlock::Resource`] is preferred
1964    /// as it avoids extra round-trips and allows the message to include
1965    /// pieces of context from sources the agent may not have access to.
1966    pub prompt: Vec<ContentBlock>,
1967    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1968    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1969    /// these keys.
1970    ///
1971    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1972    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1973    pub meta: Option<Meta>,
1974}
1975
1976impl PromptRequest {
1977    #[must_use]
1978    pub fn new(session_id: impl Into<SessionId>, prompt: Vec<ContentBlock>) -> Self {
1979        Self {
1980            session_id: session_id.into(),
1981            prompt,
1982            meta: None,
1983        }
1984    }
1985
1986    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1987    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1988    /// these keys.
1989    ///
1990    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1991    #[must_use]
1992    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1993        self.meta = meta.into_option();
1994        self
1995    }
1996}
1997
1998/// Response from processing a user prompt.
1999///
2000/// See protocol docs: [Check for Completion](https://agentclientprotocol.com/protocol/prompt-turn#4-check-for-completion)
2001#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2002#[schemars(extend("x-side" = "agent", "x-method" = SESSION_PROMPT_METHOD_NAME))]
2003#[serde(rename_all = "camelCase")]
2004#[non_exhaustive]
2005pub struct PromptResponse {
2006    /// Indicates why the agent stopped processing the turn.
2007    pub stop_reason: StopReason,
2008    /// **UNSTABLE**
2009    ///
2010    /// This capability is not part of the spec yet, and may be removed or changed at any point.
2011    ///
2012    /// Token usage for this turn (optional).
2013    #[cfg(feature = "unstable_session_usage")]
2014    #[serde(skip_serializing_if = "Option::is_none")]
2015    pub usage: Option<Usage>,
2016    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2017    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2018    /// these keys.
2019    ///
2020    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2021    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
2022    pub meta: Option<Meta>,
2023}
2024
2025impl PromptResponse {
2026    #[must_use]
2027    pub fn new(stop_reason: StopReason) -> Self {
2028        Self {
2029            stop_reason,
2030            #[cfg(feature = "unstable_session_usage")]
2031            usage: None,
2032            meta: None,
2033        }
2034    }
2035
2036    /// **UNSTABLE**
2037    ///
2038    /// This capability is not part of the spec yet, and may be removed or changed at any point.
2039    ///
2040    /// Token usage for this turn.
2041    #[cfg(feature = "unstable_session_usage")]
2042    #[must_use]
2043    pub fn usage(mut self, usage: impl IntoOption<Usage>) -> Self {
2044        self.usage = usage.into_option();
2045        self
2046    }
2047
2048    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2049    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2050    /// these keys.
2051    ///
2052    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2053    #[must_use]
2054    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2055        self.meta = meta.into_option();
2056        self
2057    }
2058}
2059
2060/// Reasons why an agent stops processing a prompt turn.
2061///
2062/// See protocol docs: [Stop Reasons](https://agentclientprotocol.com/protocol/prompt-turn#stop-reasons)
2063#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
2064#[serde(rename_all = "snake_case")]
2065#[non_exhaustive]
2066pub enum StopReason {
2067    /// The turn ended successfully.
2068    EndTurn,
2069    /// The turn ended because the agent reached the maximum number of tokens.
2070    MaxTokens,
2071    /// The turn ended because the agent reached the maximum number of allowed
2072    /// agent requests between user turns.
2073    MaxTurnRequests,
2074    /// The turn ended because the agent refused to continue. The user prompt
2075    /// and everything that comes after it won't be included in the next
2076    /// prompt, so this should be reflected in the UI.
2077    Refusal,
2078    /// The turn was cancelled by the client via `session/cancel`.
2079    ///
2080    /// This stop reason MUST be returned when the client sends a `session/cancel`
2081    /// notification, even if the cancellation causes exceptions in underlying operations.
2082    /// Agents should catch these exceptions and return this semantically meaningful
2083    /// response to confirm successful cancellation.
2084    Cancelled,
2085}
2086
2087/// **UNSTABLE**
2088///
2089/// This capability is not part of the spec yet, and may be removed or changed at any point.
2090///
2091/// Token usage information for a prompt turn.
2092#[cfg(feature = "unstable_session_usage")]
2093#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2094#[serde(rename_all = "camelCase")]
2095#[non_exhaustive]
2096pub struct Usage {
2097    /// Sum of all token types across session.
2098    pub total_tokens: u64,
2099    /// Total input tokens across all turns.
2100    pub input_tokens: u64,
2101    /// Total output tokens across all turns.
2102    pub output_tokens: u64,
2103    /// Total thought/reasoning tokens
2104    #[serde(skip_serializing_if = "Option::is_none")]
2105    pub thought_tokens: Option<u64>,
2106    /// Total cache read tokens.
2107    #[serde(skip_serializing_if = "Option::is_none")]
2108    pub cached_read_tokens: Option<u64>,
2109    /// Total cache write tokens.
2110    #[serde(skip_serializing_if = "Option::is_none")]
2111    pub cached_write_tokens: Option<u64>,
2112}
2113
2114#[cfg(feature = "unstable_session_usage")]
2115impl Usage {
2116    #[must_use]
2117    pub fn new(total_tokens: u64, input_tokens: u64, output_tokens: u64) -> Self {
2118        Self {
2119            total_tokens,
2120            input_tokens,
2121            output_tokens,
2122            thought_tokens: None,
2123            cached_read_tokens: None,
2124            cached_write_tokens: None,
2125        }
2126    }
2127
2128    /// Total thought/reasoning tokens
2129    #[must_use]
2130    pub fn thought_tokens(mut self, thought_tokens: impl IntoOption<u64>) -> Self {
2131        self.thought_tokens = thought_tokens.into_option();
2132        self
2133    }
2134
2135    /// Total cache read tokens.
2136    #[must_use]
2137    pub fn cached_read_tokens(mut self, cached_read_tokens: impl IntoOption<u64>) -> Self {
2138        self.cached_read_tokens = cached_read_tokens.into_option();
2139        self
2140    }
2141
2142    /// Total cache write tokens.
2143    #[must_use]
2144    pub fn cached_write_tokens(mut self, cached_write_tokens: impl IntoOption<u64>) -> Self {
2145        self.cached_write_tokens = cached_write_tokens.into_option();
2146        self
2147    }
2148}
2149
2150// Model
2151
2152/// **UNSTABLE**
2153///
2154/// This capability is not part of the spec yet, and may be removed or changed at any point.
2155///
2156/// The set of models and the one currently active.
2157#[cfg(feature = "unstable_session_model")]
2158#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2159#[serde(rename_all = "camelCase")]
2160#[non_exhaustive]
2161pub struct SessionModelState {
2162    /// The current model the Agent is in.
2163    pub current_model_id: ModelId,
2164    /// The set of models that the Agent can use
2165    pub available_models: Vec<ModelInfo>,
2166    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2167    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2168    /// these keys.
2169    ///
2170    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2171    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
2172    pub meta: Option<Meta>,
2173}
2174
2175#[cfg(feature = "unstable_session_model")]
2176impl SessionModelState {
2177    #[must_use]
2178    pub fn new(current_model_id: impl Into<ModelId>, available_models: Vec<ModelInfo>) -> Self {
2179        Self {
2180            current_model_id: current_model_id.into(),
2181            available_models,
2182            meta: None,
2183        }
2184    }
2185
2186    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2187    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2188    /// these keys.
2189    ///
2190    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2191    #[must_use]
2192    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2193        self.meta = meta.into_option();
2194        self
2195    }
2196}
2197
2198/// **UNSTABLE**
2199///
2200/// This capability is not part of the spec yet, and may be removed or changed at any point.
2201///
2202/// A unique identifier for a model.
2203#[cfg(feature = "unstable_session_model")]
2204#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, Display, From)]
2205#[serde(transparent)]
2206#[from(Arc<str>, String, &'static str)]
2207#[non_exhaustive]
2208pub struct ModelId(pub Arc<str>);
2209
2210#[cfg(feature = "unstable_session_model")]
2211impl ModelId {
2212    pub fn new(id: impl Into<Arc<str>>) -> Self {
2213        Self(id.into())
2214    }
2215}
2216
2217/// **UNSTABLE**
2218///
2219/// This capability is not part of the spec yet, and may be removed or changed at any point.
2220///
2221/// Information about a selectable model.
2222#[cfg(feature = "unstable_session_model")]
2223#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2224#[serde(rename_all = "camelCase")]
2225#[non_exhaustive]
2226pub struct ModelInfo {
2227    /// Unique identifier for the model.
2228    pub model_id: ModelId,
2229    /// Human-readable name of the model.
2230    pub name: String,
2231    /// Optional description of the model.
2232    #[serde(default, skip_serializing_if = "Option::is_none")]
2233    pub description: Option<String>,
2234    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2235    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2236    /// these keys.
2237    ///
2238    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2239    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
2240    pub meta: Option<Meta>,
2241}
2242
2243#[cfg(feature = "unstable_session_model")]
2244impl ModelInfo {
2245    pub fn new(model_id: impl Into<ModelId>, name: impl Into<String>) -> Self {
2246        Self {
2247            model_id: model_id.into(),
2248            name: name.into(),
2249            description: None,
2250            meta: None,
2251        }
2252    }
2253
2254    /// Optional description of the model.
2255    #[must_use]
2256    pub fn description(mut self, description: impl IntoOption<String>) -> Self {
2257        self.description = description.into_option();
2258        self
2259    }
2260
2261    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2262    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2263    /// these keys.
2264    ///
2265    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2266    #[must_use]
2267    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2268        self.meta = meta.into_option();
2269        self
2270    }
2271}
2272
2273/// **UNSTABLE**
2274///
2275/// This capability is not part of the spec yet, and may be removed or changed at any point.
2276///
2277/// Request parameters for setting a session model.
2278#[cfg(feature = "unstable_session_model")]
2279#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2280#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_MODEL_METHOD_NAME))]
2281#[serde(rename_all = "camelCase")]
2282#[non_exhaustive]
2283pub struct SetSessionModelRequest {
2284    /// The ID of the session to set the model for.
2285    pub session_id: SessionId,
2286    /// The ID of the model to set.
2287    pub model_id: ModelId,
2288    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2289    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2290    /// these keys.
2291    ///
2292    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2293    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
2294    pub meta: Option<Meta>,
2295}
2296
2297#[cfg(feature = "unstable_session_model")]
2298impl SetSessionModelRequest {
2299    #[must_use]
2300    pub fn new(session_id: impl Into<SessionId>, model_id: impl Into<ModelId>) -> Self {
2301        Self {
2302            session_id: session_id.into(),
2303            model_id: model_id.into(),
2304            meta: None,
2305        }
2306    }
2307
2308    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2309    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2310    /// these keys.
2311    ///
2312    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2313    #[must_use]
2314    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2315        self.meta = meta.into_option();
2316        self
2317    }
2318}
2319
2320/// **UNSTABLE**
2321///
2322/// This capability is not part of the spec yet, and may be removed or changed at any point.
2323///
2324/// Response to `session/set_model` method.
2325#[cfg(feature = "unstable_session_model")]
2326#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2327#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_MODEL_METHOD_NAME))]
2328#[serde(rename_all = "camelCase")]
2329#[non_exhaustive]
2330pub struct SetSessionModelResponse {
2331    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2332    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2333    /// these keys.
2334    ///
2335    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2336    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
2337    pub meta: Option<Meta>,
2338}
2339
2340#[cfg(feature = "unstable_session_model")]
2341impl SetSessionModelResponse {
2342    #[must_use]
2343    pub fn new() -> Self {
2344        Self::default()
2345    }
2346
2347    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2348    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2349    /// these keys.
2350    ///
2351    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2352    #[must_use]
2353    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2354        self.meta = meta.into_option();
2355        self
2356    }
2357}
2358
2359// Capabilities
2360
2361/// Capabilities supported by the agent.
2362///
2363/// Advertised during initialization to inform the client about
2364/// available features and content types.
2365///
2366/// See protocol docs: [Agent Capabilities](https://agentclientprotocol.com/protocol/initialization#agent-capabilities)
2367#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2368#[serde(rename_all = "camelCase")]
2369#[non_exhaustive]
2370pub struct AgentCapabilities {
2371    /// Whether the agent supports `session/load`.
2372    #[serde(default)]
2373    pub load_session: bool,
2374    /// Prompt capabilities supported by the agent.
2375    #[serde(default)]
2376    pub prompt_capabilities: PromptCapabilities,
2377    /// MCP capabilities supported by the agent.
2378    #[serde(default)]
2379    pub mcp_capabilities: McpCapabilities,
2380    #[serde(default)]
2381    pub session_capabilities: SessionCapabilities,
2382    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2383    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2384    /// these keys.
2385    ///
2386    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2387    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
2388    pub meta: Option<Meta>,
2389}
2390
2391impl AgentCapabilities {
2392    #[must_use]
2393    pub fn new() -> Self {
2394        Self::default()
2395    }
2396
2397    /// Whether the agent supports `session/load`.
2398    #[must_use]
2399    pub fn load_session(mut self, load_session: bool) -> Self {
2400        self.load_session = load_session;
2401        self
2402    }
2403
2404    /// Prompt capabilities supported by the agent.
2405    #[must_use]
2406    pub fn prompt_capabilities(mut self, prompt_capabilities: PromptCapabilities) -> Self {
2407        self.prompt_capabilities = prompt_capabilities;
2408        self
2409    }
2410
2411    /// MCP capabilities supported by the agent.
2412    #[must_use]
2413    pub fn mcp_capabilities(mut self, mcp_capabilities: McpCapabilities) -> Self {
2414        self.mcp_capabilities = mcp_capabilities;
2415        self
2416    }
2417
2418    /// Session capabilities supported by the agent.
2419    #[must_use]
2420    pub fn session_capabilities(mut self, session_capabilities: SessionCapabilities) -> Self {
2421        self.session_capabilities = session_capabilities;
2422        self
2423    }
2424
2425    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2426    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2427    /// these keys.
2428    ///
2429    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2430    #[must_use]
2431    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2432        self.meta = meta.into_option();
2433        self
2434    }
2435}
2436
2437/// Session capabilities supported by the agent.
2438///
2439/// As a baseline, all Agents **MUST** support `session/new`, `session/prompt`, `session/cancel`, and `session/update`.
2440///
2441/// Optionally, they **MAY** support other session methods and notifications by specifying additional capabilities.
2442///
2443/// Note: `session/load` is still handled by the top-level `load_session` capability. This will be unified in future versions of the protocol.
2444///
2445/// See protocol docs: [Session Capabilities](https://agentclientprotocol.com/protocol/initialization#session-capabilities)
2446#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2447#[non_exhaustive]
2448pub struct SessionCapabilities {
2449    /// **UNSTABLE**
2450    ///
2451    /// This capability is not part of the spec yet, and may be removed or changed at any point.
2452    ///
2453    /// Whether the agent supports `session/list`.
2454    #[cfg(feature = "unstable_session_list")]
2455    #[serde(skip_serializing_if = "Option::is_none")]
2456    pub list: Option<SessionListCapabilities>,
2457    /// **UNSTABLE**
2458    ///
2459    /// This capability is not part of the spec yet, and may be removed or changed at any point.
2460    ///
2461    /// Whether the agent supports `session/fork`.
2462    #[cfg(feature = "unstable_session_fork")]
2463    #[serde(skip_serializing_if = "Option::is_none")]
2464    pub fork: Option<SessionForkCapabilities>,
2465    /// **UNSTABLE**
2466    ///
2467    /// This capability is not part of the spec yet, and may be removed or changed at any point.
2468    ///
2469    /// Whether the agent supports `session/resume`.
2470    #[cfg(feature = "unstable_session_resume")]
2471    #[serde(skip_serializing_if = "Option::is_none")]
2472    pub resume: Option<SessionResumeCapabilities>,
2473    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2474    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2475    /// these keys.
2476    ///
2477    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2478    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
2479    pub meta: Option<Meta>,
2480}
2481
2482impl SessionCapabilities {
2483    #[must_use]
2484    pub fn new() -> Self {
2485        Self::default()
2486    }
2487
2488    #[cfg(feature = "unstable_session_list")]
2489    /// Whether the agent supports `session/list`.
2490    #[must_use]
2491    pub fn list(mut self, list: impl IntoOption<SessionListCapabilities>) -> Self {
2492        self.list = list.into_option();
2493        self
2494    }
2495
2496    #[cfg(feature = "unstable_session_fork")]
2497    /// Whether the agent supports `session/fork`.
2498    #[must_use]
2499    pub fn fork(mut self, fork: impl IntoOption<SessionForkCapabilities>) -> Self {
2500        self.fork = fork.into_option();
2501        self
2502    }
2503
2504    #[cfg(feature = "unstable_session_resume")]
2505    /// Whether the agent supports `session/resume`.
2506    #[must_use]
2507    pub fn resume(mut self, resume: impl IntoOption<SessionResumeCapabilities>) -> Self {
2508        self.resume = resume.into_option();
2509        self
2510    }
2511
2512    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2513    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2514    /// these keys.
2515    ///
2516    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2517    #[must_use]
2518    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2519        self.meta = meta.into_option();
2520        self
2521    }
2522}
2523
2524/// Capabilities for the `session/list` method.
2525///
2526/// By supplying `{}` it means that the agent supports listing of sessions.
2527///
2528/// Further capabilities can be added in the future for other means of filtering or searching the list.
2529#[cfg(feature = "unstable_session_list")]
2530#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2531#[non_exhaustive]
2532pub struct SessionListCapabilities {
2533    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2534    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2535    /// these keys.
2536    ///
2537    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2538    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
2539    pub meta: Option<Meta>,
2540}
2541
2542#[cfg(feature = "unstable_session_list")]
2543impl SessionListCapabilities {
2544    #[must_use]
2545    pub fn new() -> Self {
2546        Self::default()
2547    }
2548    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2549    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2550    /// these keys.
2551    ///
2552    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2553    #[must_use]
2554    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2555        self.meta = meta.into_option();
2556        self
2557    }
2558}
2559
2560/// **UNSTABLE**
2561///
2562/// This capability is not part of the spec yet, and may be removed or changed at any point.
2563///
2564/// Capabilities for the `session/fork` method.
2565///
2566/// By supplying `{}` it means that the agent supports forking of sessions.
2567#[cfg(feature = "unstable_session_fork")]
2568#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2569#[non_exhaustive]
2570pub struct SessionForkCapabilities {
2571    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2572    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2573    /// these keys.
2574    ///
2575    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2576    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
2577    pub meta: Option<Meta>,
2578}
2579
2580#[cfg(feature = "unstable_session_fork")]
2581impl SessionForkCapabilities {
2582    #[must_use]
2583    pub fn new() -> Self {
2584        Self::default()
2585    }
2586
2587    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2588    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2589    /// these keys.
2590    ///
2591    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2592    #[must_use]
2593    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2594        self.meta = meta.into_option();
2595        self
2596    }
2597}
2598
2599/// **UNSTABLE**
2600///
2601/// This capability is not part of the spec yet, and may be removed or changed at any point.
2602///
2603/// Capabilities for the `session/resume` method.
2604///
2605/// By supplying `{}` it means that the agent supports resuming of sessions.
2606#[cfg(feature = "unstable_session_resume")]
2607#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2608#[non_exhaustive]
2609pub struct SessionResumeCapabilities {
2610    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2611    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2612    /// these keys.
2613    ///
2614    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2615    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
2616    pub meta: Option<Meta>,
2617}
2618
2619#[cfg(feature = "unstable_session_resume")]
2620impl SessionResumeCapabilities {
2621    #[must_use]
2622    pub fn new() -> Self {
2623        Self::default()
2624    }
2625
2626    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2627    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2628    /// these keys.
2629    ///
2630    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2631    #[must_use]
2632    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2633        self.meta = meta.into_option();
2634        self
2635    }
2636}
2637
2638/// Prompt capabilities supported by the agent in `session/prompt` requests.
2639///
2640/// Baseline agent functionality requires support for [`ContentBlock::Text`]
2641/// and [`ContentBlock::ResourceLink`] in prompt requests.
2642///
2643/// Other variants must be explicitly opted in to.
2644/// Capabilities for different types of content in prompt requests.
2645///
2646/// Indicates which content types beyond the baseline (text and resource links)
2647/// the agent can process.
2648///
2649/// See protocol docs: [Prompt Capabilities](https://agentclientprotocol.com/protocol/initialization#prompt-capabilities)
2650#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2651#[serde(rename_all = "camelCase")]
2652#[non_exhaustive]
2653pub struct PromptCapabilities {
2654    /// Agent supports [`ContentBlock::Image`].
2655    #[serde(default)]
2656    pub image: bool,
2657    /// Agent supports [`ContentBlock::Audio`].
2658    #[serde(default)]
2659    pub audio: bool,
2660    /// Agent supports embedded context in `session/prompt` requests.
2661    ///
2662    /// When enabled, the Client is allowed to include [`ContentBlock::Resource`]
2663    /// in prompt requests for pieces of context that are referenced in the message.
2664    #[serde(default)]
2665    pub embedded_context: bool,
2666    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2667    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2668    /// these keys.
2669    ///
2670    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2671    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
2672    pub meta: Option<Meta>,
2673}
2674
2675impl PromptCapabilities {
2676    #[must_use]
2677    pub fn new() -> Self {
2678        Self::default()
2679    }
2680
2681    /// Agent supports [`ContentBlock::Image`].
2682    #[must_use]
2683    pub fn image(mut self, image: bool) -> Self {
2684        self.image = image;
2685        self
2686    }
2687
2688    /// Agent supports [`ContentBlock::Audio`].
2689    #[must_use]
2690    pub fn audio(mut self, audio: bool) -> Self {
2691        self.audio = audio;
2692        self
2693    }
2694
2695    /// Agent supports embedded context in `session/prompt` requests.
2696    ///
2697    /// When enabled, the Client is allowed to include [`ContentBlock::Resource`]
2698    /// in prompt requests for pieces of context that are referenced in the message.
2699    #[must_use]
2700    pub fn embedded_context(mut self, embedded_context: bool) -> Self {
2701        self.embedded_context = embedded_context;
2702        self
2703    }
2704
2705    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2706    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2707    /// these keys.
2708    ///
2709    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2710    #[must_use]
2711    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2712        self.meta = meta.into_option();
2713        self
2714    }
2715}
2716
2717/// MCP capabilities supported by the agent
2718#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2719#[serde(rename_all = "camelCase")]
2720#[non_exhaustive]
2721pub struct McpCapabilities {
2722    /// Agent supports [`McpServer::Http`].
2723    #[serde(default)]
2724    pub http: bool,
2725    /// Agent supports [`McpServer::Sse`].
2726    #[serde(default)]
2727    pub sse: bool,
2728    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2729    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2730    /// these keys.
2731    ///
2732    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2733    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
2734    pub meta: Option<Meta>,
2735}
2736
2737impl McpCapabilities {
2738    #[must_use]
2739    pub fn new() -> Self {
2740        Self::default()
2741    }
2742
2743    /// Agent supports [`McpServer::Http`].
2744    #[must_use]
2745    pub fn http(mut self, http: bool) -> Self {
2746        self.http = http;
2747        self
2748    }
2749
2750    /// Agent supports [`McpServer::Sse`].
2751    #[must_use]
2752    pub fn sse(mut self, sse: bool) -> Self {
2753        self.sse = sse;
2754        self
2755    }
2756
2757    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2758    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2759    /// these keys.
2760    ///
2761    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2762    #[must_use]
2763    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2764        self.meta = meta.into_option();
2765        self
2766    }
2767}
2768
2769// Method schema
2770
2771/// Names of all methods that agents handle.
2772///
2773/// Provides a centralized definition of method names used in the protocol.
2774#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2775#[non_exhaustive]
2776pub struct AgentMethodNames {
2777    /// Method for initializing the connection.
2778    pub initialize: &'static str,
2779    /// Method for authenticating with the agent.
2780    pub authenticate: &'static str,
2781    /// Method for creating a new session.
2782    pub session_new: &'static str,
2783    /// Method for loading an existing session.
2784    pub session_load: &'static str,
2785    /// Method for setting the mode for a session.
2786    pub session_set_mode: &'static str,
2787    /// Method for setting a configuration option for a session.
2788    pub session_set_config_option: &'static str,
2789    /// Method for sending a prompt to the agent.
2790    pub session_prompt: &'static str,
2791    /// Notification for cancelling operations.
2792    pub session_cancel: &'static str,
2793    /// Method for selecting a model for a given session.
2794    #[cfg(feature = "unstable_session_model")]
2795    pub session_set_model: &'static str,
2796    /// Method for listing existing sessions.
2797    #[cfg(feature = "unstable_session_list")]
2798    pub session_list: &'static str,
2799    /// Method for forking an existing session.
2800    #[cfg(feature = "unstable_session_fork")]
2801    pub session_fork: &'static str,
2802    /// Method for resuming an existing session.
2803    #[cfg(feature = "unstable_session_resume")]
2804    pub session_resume: &'static str,
2805}
2806
2807/// Constant containing all agent method names.
2808pub const AGENT_METHOD_NAMES: AgentMethodNames = AgentMethodNames {
2809    initialize: INITIALIZE_METHOD_NAME,
2810    authenticate: AUTHENTICATE_METHOD_NAME,
2811    session_new: SESSION_NEW_METHOD_NAME,
2812    session_load: SESSION_LOAD_METHOD_NAME,
2813    session_set_mode: SESSION_SET_MODE_METHOD_NAME,
2814    session_set_config_option: SESSION_SET_CONFIG_OPTION_METHOD_NAME,
2815    session_prompt: SESSION_PROMPT_METHOD_NAME,
2816    session_cancel: SESSION_CANCEL_METHOD_NAME,
2817    #[cfg(feature = "unstable_session_model")]
2818    session_set_model: SESSION_SET_MODEL_METHOD_NAME,
2819    #[cfg(feature = "unstable_session_list")]
2820    session_list: SESSION_LIST_METHOD_NAME,
2821    #[cfg(feature = "unstable_session_fork")]
2822    session_fork: SESSION_FORK_METHOD_NAME,
2823    #[cfg(feature = "unstable_session_resume")]
2824    session_resume: SESSION_RESUME_METHOD_NAME,
2825};
2826
2827/// Method name for the initialize request.
2828pub(crate) const INITIALIZE_METHOD_NAME: &str = "initialize";
2829/// Method name for the authenticate request.
2830pub(crate) const AUTHENTICATE_METHOD_NAME: &str = "authenticate";
2831/// Method name for creating a new session.
2832pub(crate) const SESSION_NEW_METHOD_NAME: &str = "session/new";
2833/// Method name for loading an existing session.
2834pub(crate) const SESSION_LOAD_METHOD_NAME: &str = "session/load";
2835/// Method name for setting the mode for a session.
2836pub(crate) const SESSION_SET_MODE_METHOD_NAME: &str = "session/set_mode";
2837/// Method name for setting a configuration option for a session.
2838pub(crate) const SESSION_SET_CONFIG_OPTION_METHOD_NAME: &str = "session/set_config_option";
2839/// Method name for sending a prompt.
2840pub(crate) const SESSION_PROMPT_METHOD_NAME: &str = "session/prompt";
2841/// Method name for the cancel notification.
2842pub(crate) const SESSION_CANCEL_METHOD_NAME: &str = "session/cancel";
2843/// Method name for selecting a model for a given session.
2844#[cfg(feature = "unstable_session_model")]
2845pub(crate) const SESSION_SET_MODEL_METHOD_NAME: &str = "session/set_model";
2846/// Method name for listing existing sessions.
2847#[cfg(feature = "unstable_session_list")]
2848pub(crate) const SESSION_LIST_METHOD_NAME: &str = "session/list";
2849/// Method name for forking an existing session.
2850#[cfg(feature = "unstable_session_fork")]
2851pub(crate) const SESSION_FORK_METHOD_NAME: &str = "session/fork";
2852/// Method name for resuming an existing session.
2853#[cfg(feature = "unstable_session_resume")]
2854pub(crate) const SESSION_RESUME_METHOD_NAME: &str = "session/resume";
2855
2856/// All possible requests that a client can send to an agent.
2857///
2858/// This enum is used internally for routing RPC requests. You typically won't need
2859/// to use this directly - instead, use the methods on the [`Agent`] trait.
2860///
2861/// This enum encompasses all method calls from client to agent.
2862#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
2863#[serde(untagged)]
2864#[schemars(inline)]
2865#[non_exhaustive]
2866pub enum ClientRequest {
2867    /// Establishes the connection with a client and negotiates protocol capabilities.
2868    ///
2869    /// This method is called once at the beginning of the connection to:
2870    /// - Negotiate the protocol version to use
2871    /// - Exchange capability information between client and agent
2872    /// - Determine available authentication methods
2873    ///
2874    /// The agent should respond with its supported protocol version and capabilities.
2875    ///
2876    /// See protocol docs: [Initialization](https://agentclientprotocol.com/protocol/initialization)
2877    InitializeRequest(InitializeRequest),
2878    /// Authenticates the client using the specified authentication method.
2879    ///
2880    /// Called when the agent requires authentication before allowing session creation.
2881    /// The client provides the authentication method ID that was advertised during initialization.
2882    ///
2883    /// After successful authentication, the client can proceed to create sessions with
2884    /// `new_session` without receiving an `auth_required` error.
2885    ///
2886    /// See protocol docs: [Initialization](https://agentclientprotocol.com/protocol/initialization)
2887    AuthenticateRequest(AuthenticateRequest),
2888    /// Creates a new conversation session with the agent.
2889    ///
2890    /// Sessions represent independent conversation contexts with their own history and state.
2891    ///
2892    /// The agent should:
2893    /// - Create a new session context
2894    /// - Connect to any specified MCP servers
2895    /// - Return a unique session ID for future requests
2896    ///
2897    /// May return an `auth_required` error if the agent requires authentication.
2898    ///
2899    /// See protocol docs: [Session Setup](https://agentclientprotocol.com/protocol/session-setup)
2900    NewSessionRequest(NewSessionRequest),
2901    /// Loads an existing session to resume a previous conversation.
2902    ///
2903    /// This method is only available if the agent advertises the `loadSession` capability.
2904    ///
2905    /// The agent should:
2906    /// - Restore the session context and conversation history
2907    /// - Connect to the specified MCP servers
2908    /// - Stream the entire conversation history back to the client via notifications
2909    ///
2910    /// See protocol docs: [Loading Sessions](https://agentclientprotocol.com/protocol/session-setup#loading-sessions)
2911    LoadSessionRequest(LoadSessionRequest),
2912    #[cfg(feature = "unstable_session_list")]
2913    /// **UNSTABLE**
2914    ///
2915    /// This capability is not part of the spec yet, and may be removed or changed at any point.
2916    ///
2917    /// Lists existing sessions known to the agent.
2918    ///
2919    /// This method is only available if the agent advertises the `listSessions` capability.
2920    ///
2921    /// The agent should return metadata about sessions with optional filtering and pagination support.
2922    ListSessionsRequest(ListSessionsRequest),
2923    #[cfg(feature = "unstable_session_fork")]
2924    /// **UNSTABLE**
2925    ///
2926    /// This capability is not part of the spec yet, and may be removed or changed at any point.
2927    ///
2928    /// Forks an existing session to create a new independent session.
2929    ///
2930    /// This method is only available if the agent advertises the `session.fork` capability.
2931    ///
2932    /// The agent should create a new session with the same conversation context as the
2933    /// original, allowing operations like generating summaries without affecting the
2934    /// original session's history.
2935    ForkSessionRequest(ForkSessionRequest),
2936    #[cfg(feature = "unstable_session_resume")]
2937    /// **UNSTABLE**
2938    ///
2939    /// This capability is not part of the spec yet, and may be removed or changed at any point.
2940    ///
2941    /// Resumes an existing session without returning previous messages.
2942    ///
2943    /// This method is only available if the agent advertises the `session.resume` capability.
2944    ///
2945    /// The agent should resume the session context, allowing the conversation to continue
2946    /// without replaying the message history (unlike `session/load`).
2947    ResumeSessionRequest(ResumeSessionRequest),
2948    /// Sets the current mode for a session.
2949    ///
2950    /// Allows switching between different agent modes (e.g., "ask", "architect", "code")
2951    /// that affect system prompts, tool availability, and permission behaviors.
2952    ///
2953    /// The mode must be one of the modes advertised in `availableModes` during session
2954    /// creation or loading. Agents may also change modes autonomously and notify the
2955    /// client via `current_mode_update` notifications.
2956    ///
2957    /// This method can be called at any time during a session, whether the Agent is
2958    /// idle or actively generating a response.
2959    ///
2960    /// See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
2961    SetSessionModeRequest(SetSessionModeRequest),
2962    /// Sets the current value for a session configuration option.
2963    SetSessionConfigOptionRequest(SetSessionConfigOptionRequest),
2964    /// Processes a user prompt within a session.
2965    ///
2966    /// This method handles the whole lifecycle of a prompt:
2967    /// - Receives user messages with optional context (files, images, etc.)
2968    /// - Processes the prompt using language models
2969    /// - Reports language model content and tool calls to the Clients
2970    /// - Requests permission to run tools
2971    /// - Executes any requested tool calls
2972    /// - Returns when the turn is complete with a stop reason
2973    ///
2974    /// See protocol docs: [Prompt Turn](https://agentclientprotocol.com/protocol/prompt-turn)
2975    PromptRequest(PromptRequest),
2976    #[cfg(feature = "unstable_session_model")]
2977    /// **UNSTABLE**
2978    ///
2979    /// This capability is not part of the spec yet, and may be removed or changed at any point.
2980    ///
2981    /// Select a model for a given session.
2982    SetSessionModelRequest(SetSessionModelRequest),
2983    /// Handles extension method requests from the client.
2984    ///
2985    /// Extension methods provide a way to add custom functionality while maintaining
2986    /// protocol compatibility.
2987    ///
2988    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2989    ExtMethodRequest(ExtRequest),
2990}
2991
2992impl ClientRequest {
2993    /// Returns the corresponding method name of the request.
2994    #[must_use]
2995    pub fn method(&self) -> &str {
2996        match self {
2997            Self::InitializeRequest(_) => AGENT_METHOD_NAMES.initialize,
2998            Self::AuthenticateRequest(_) => AGENT_METHOD_NAMES.authenticate,
2999            Self::NewSessionRequest(_) => AGENT_METHOD_NAMES.session_new,
3000            Self::LoadSessionRequest(_) => AGENT_METHOD_NAMES.session_load,
3001            #[cfg(feature = "unstable_session_list")]
3002            Self::ListSessionsRequest(_) => AGENT_METHOD_NAMES.session_list,
3003            #[cfg(feature = "unstable_session_fork")]
3004            Self::ForkSessionRequest(_) => AGENT_METHOD_NAMES.session_fork,
3005            #[cfg(feature = "unstable_session_resume")]
3006            Self::ResumeSessionRequest(_) => AGENT_METHOD_NAMES.session_resume,
3007            Self::SetSessionModeRequest(_) => AGENT_METHOD_NAMES.session_set_mode,
3008            Self::SetSessionConfigOptionRequest(_) => AGENT_METHOD_NAMES.session_set_config_option,
3009            Self::PromptRequest(_) => AGENT_METHOD_NAMES.session_prompt,
3010            #[cfg(feature = "unstable_session_model")]
3011            Self::SetSessionModelRequest(_) => AGENT_METHOD_NAMES.session_set_model,
3012            Self::ExtMethodRequest(ext_request) => &ext_request.method,
3013        }
3014    }
3015}
3016
3017/// All possible responses that an agent can send to a client.
3018///
3019/// This enum is used internally for routing RPC responses. You typically won't need
3020/// to use this directly - the responses are handled automatically by the connection.
3021///
3022/// These are responses to the corresponding `ClientRequest` variants.
3023#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
3024#[serde(untagged)]
3025#[schemars(inline)]
3026#[non_exhaustive]
3027pub enum AgentResponse {
3028    InitializeResponse(InitializeResponse),
3029    AuthenticateResponse(#[serde(default)] AuthenticateResponse),
3030    NewSessionResponse(NewSessionResponse),
3031    LoadSessionResponse(#[serde(default)] LoadSessionResponse),
3032    #[cfg(feature = "unstable_session_list")]
3033    ListSessionsResponse(ListSessionsResponse),
3034    #[cfg(feature = "unstable_session_fork")]
3035    ForkSessionResponse(ForkSessionResponse),
3036    #[cfg(feature = "unstable_session_resume")]
3037    ResumeSessionResponse(#[serde(default)] ResumeSessionResponse),
3038    SetSessionModeResponse(#[serde(default)] SetSessionModeResponse),
3039    SetSessionConfigOptionResponse(SetSessionConfigOptionResponse),
3040    PromptResponse(PromptResponse),
3041    #[cfg(feature = "unstable_session_model")]
3042    SetSessionModelResponse(SetSessionModelResponse),
3043    ExtMethodResponse(ExtResponse),
3044}
3045
3046/// All possible notifications that a client can send to an agent.
3047///
3048/// This enum is used internally for routing RPC notifications. You typically won't need
3049/// to use this directly - use the notification methods on the [`Agent`] trait instead.
3050///
3051/// Notifications do not expect a response.
3052#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
3053#[serde(untagged)]
3054#[schemars(inline)]
3055#[non_exhaustive]
3056pub enum ClientNotification {
3057    /// Cancels ongoing operations for a session.
3058    ///
3059    /// This is a notification sent by the client to cancel an ongoing prompt turn.
3060    ///
3061    /// Upon receiving this notification, the Agent SHOULD:
3062    /// - Stop all language model requests as soon as possible
3063    /// - Abort all tool call invocations in progress
3064    /// - Send any pending `session/update` notifications
3065    /// - Respond to the original `session/prompt` request with `StopReason::Cancelled`
3066    ///
3067    /// See protocol docs: [Cancellation](https://agentclientprotocol.com/protocol/prompt-turn#cancellation)
3068    CancelNotification(CancelNotification),
3069    /// Handles extension notifications from the client.
3070    ///
3071    /// Extension notifications provide a way to send one-way messages for custom functionality
3072    /// while maintaining protocol compatibility.
3073    ///
3074    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3075    ExtNotification(ExtNotification),
3076}
3077
3078impl ClientNotification {
3079    /// Returns the corresponding method name of the notification.
3080    #[must_use]
3081    pub fn method(&self) -> &str {
3082        match self {
3083            Self::CancelNotification(_) => AGENT_METHOD_NAMES.session_cancel,
3084            Self::ExtNotification(ext_notification) => &ext_notification.method,
3085        }
3086    }
3087}
3088
3089/// Notification to cancel ongoing operations for a session.
3090///
3091/// See protocol docs: [Cancellation](https://agentclientprotocol.com/protocol/prompt-turn#cancellation)
3092#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3093#[schemars(extend("x-side" = "agent", "x-method" = SESSION_CANCEL_METHOD_NAME))]
3094#[serde(rename_all = "camelCase")]
3095#[non_exhaustive]
3096pub struct CancelNotification {
3097    /// The ID of the session to cancel operations for.
3098    pub session_id: SessionId,
3099    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3100    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3101    /// these keys.
3102    ///
3103    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3104    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
3105    pub meta: Option<Meta>,
3106}
3107
3108impl CancelNotification {
3109    #[must_use]
3110    pub fn new(session_id: impl Into<SessionId>) -> Self {
3111        Self {
3112            session_id: session_id.into(),
3113            meta: None,
3114        }
3115    }
3116
3117    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3118    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3119    /// these keys.
3120    ///
3121    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3122    #[must_use]
3123    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3124        self.meta = meta.into_option();
3125        self
3126    }
3127}
3128
3129#[cfg(test)]
3130mod test_serialization {
3131    use super::*;
3132    use serde_json::json;
3133
3134    #[test]
3135    fn test_mcp_server_stdio_serialization() {
3136        let server = McpServer::Stdio(
3137            McpServerStdio::new("test-server", "/usr/bin/server")
3138                .args(vec!["--port".to_string(), "3000".to_string()])
3139                .env(vec![EnvVariable::new("API_KEY", "secret123")]),
3140        );
3141
3142        let json = serde_json::to_value(&server).unwrap();
3143        assert_eq!(
3144            json,
3145            json!({
3146                "name": "test-server",
3147                "command": "/usr/bin/server",
3148                "args": ["--port", "3000"],
3149                "env": [
3150                    {
3151                        "name": "API_KEY",
3152                        "value": "secret123"
3153                    }
3154                ]
3155            })
3156        );
3157
3158        let deserialized: McpServer = serde_json::from_value(json).unwrap();
3159        match deserialized {
3160            McpServer::Stdio(McpServerStdio {
3161                name,
3162                command,
3163                args,
3164                env,
3165                meta: _,
3166            }) => {
3167                assert_eq!(name, "test-server");
3168                assert_eq!(command, PathBuf::from("/usr/bin/server"));
3169                assert_eq!(args, vec!["--port", "3000"]);
3170                assert_eq!(env.len(), 1);
3171                assert_eq!(env[0].name, "API_KEY");
3172                assert_eq!(env[0].value, "secret123");
3173            }
3174            _ => panic!("Expected Stdio variant"),
3175        }
3176    }
3177
3178    #[test]
3179    fn test_mcp_server_http_serialization() {
3180        let server = McpServer::Http(
3181            McpServerHttp::new("http-server", "https://api.example.com").headers(vec![
3182                HttpHeader::new("Authorization", "Bearer token123"),
3183                HttpHeader::new("Content-Type", "application/json"),
3184            ]),
3185        );
3186
3187        let json = serde_json::to_value(&server).unwrap();
3188        assert_eq!(
3189            json,
3190            json!({
3191                "type": "http",
3192                "name": "http-server",
3193                "url": "https://api.example.com",
3194                "headers": [
3195                    {
3196                        "name": "Authorization",
3197                        "value": "Bearer token123"
3198                    },
3199                    {
3200                        "name": "Content-Type",
3201                        "value": "application/json"
3202                    }
3203                ]
3204            })
3205        );
3206
3207        let deserialized: McpServer = serde_json::from_value(json).unwrap();
3208        match deserialized {
3209            McpServer::Http(McpServerHttp {
3210                name,
3211                url,
3212                headers,
3213                meta: _,
3214            }) => {
3215                assert_eq!(name, "http-server");
3216                assert_eq!(url, "https://api.example.com");
3217                assert_eq!(headers.len(), 2);
3218                assert_eq!(headers[0].name, "Authorization");
3219                assert_eq!(headers[0].value, "Bearer token123");
3220                assert_eq!(headers[1].name, "Content-Type");
3221                assert_eq!(headers[1].value, "application/json");
3222            }
3223            _ => panic!("Expected Http variant"),
3224        }
3225    }
3226
3227    #[test]
3228    fn test_mcp_server_sse_serialization() {
3229        let server = McpServer::Sse(
3230            McpServerSse::new("sse-server", "https://sse.example.com/events")
3231                .headers(vec![HttpHeader::new("X-API-Key", "apikey456")]),
3232        );
3233
3234        let json = serde_json::to_value(&server).unwrap();
3235        assert_eq!(
3236            json,
3237            json!({
3238                "type": "sse",
3239                "name": "sse-server",
3240                "url": "https://sse.example.com/events",
3241                "headers": [
3242                    {
3243                        "name": "X-API-Key",
3244                        "value": "apikey456"
3245                    }
3246                ]
3247            })
3248        );
3249
3250        let deserialized: McpServer = serde_json::from_value(json).unwrap();
3251        match deserialized {
3252            McpServer::Sse(McpServerSse {
3253                name,
3254                url,
3255                headers,
3256                meta: _,
3257            }) => {
3258                assert_eq!(name, "sse-server");
3259                assert_eq!(url, "https://sse.example.com/events");
3260                assert_eq!(headers.len(), 1);
3261                assert_eq!(headers[0].name, "X-API-Key");
3262                assert_eq!(headers[0].value, "apikey456");
3263            }
3264            _ => panic!("Expected Sse variant"),
3265        }
3266    }
3267
3268    #[test]
3269    fn test_session_config_option_category_known_variants() {
3270        // Test serialization of known variants
3271        assert_eq!(
3272            serde_json::to_value(&SessionConfigOptionCategory::Mode).unwrap(),
3273            json!("mode")
3274        );
3275        assert_eq!(
3276            serde_json::to_value(&SessionConfigOptionCategory::Model).unwrap(),
3277            json!("model")
3278        );
3279        assert_eq!(
3280            serde_json::to_value(&SessionConfigOptionCategory::ThoughtLevel).unwrap(),
3281            json!("thought_level")
3282        );
3283
3284        // Test deserialization of known variants
3285        assert_eq!(
3286            serde_json::from_str::<SessionConfigOptionCategory>("\"mode\"").unwrap(),
3287            SessionConfigOptionCategory::Mode
3288        );
3289        assert_eq!(
3290            serde_json::from_str::<SessionConfigOptionCategory>("\"model\"").unwrap(),
3291            SessionConfigOptionCategory::Model
3292        );
3293        assert_eq!(
3294            serde_json::from_str::<SessionConfigOptionCategory>("\"thought_level\"").unwrap(),
3295            SessionConfigOptionCategory::ThoughtLevel
3296        );
3297    }
3298
3299    #[test]
3300    fn test_session_config_option_category_unknown_variants() {
3301        // Test that unknown strings are captured in Other variant
3302        let unknown: SessionConfigOptionCategory =
3303            serde_json::from_str("\"some_future_category\"").unwrap();
3304        assert_eq!(
3305            unknown,
3306            SessionConfigOptionCategory::Other("some_future_category".to_string())
3307        );
3308
3309        // Test round-trip of unknown category
3310        let json = serde_json::to_value(&unknown).unwrap();
3311        assert_eq!(json, json!("some_future_category"));
3312    }
3313
3314    #[test]
3315    fn test_session_config_option_category_custom_categories() {
3316        // Category names beginning with `_` are free for custom use
3317        let custom: SessionConfigOptionCategory =
3318            serde_json::from_str("\"_my_custom_category\"").unwrap();
3319        assert_eq!(
3320            custom,
3321            SessionConfigOptionCategory::Other("_my_custom_category".to_string())
3322        );
3323
3324        // Test round-trip preserves the custom category name
3325        let json = serde_json::to_value(&custom).unwrap();
3326        assert_eq!(json, json!("_my_custom_category"));
3327
3328        // Deserialize back and verify
3329        let deserialized: SessionConfigOptionCategory = serde_json::from_value(json).unwrap();
3330        assert_eq!(
3331            deserialized,
3332            SessionConfigOptionCategory::Other("_my_custom_category".to_string())
3333        );
3334    }
3335}