agent_client_protocol_schema/
agent.rs

1//! Methods and notifications the agent handles/receives.
2//!
3//! This module defines the Agent trait and all associated types for implementing
4//! an AI coding agent that follows the Agent Client Protocol (ACP).
5
6use std::{path::PathBuf, sync::Arc};
7
8use derive_more::{Display, From};
9use schemars::JsonSchema;
10use serde::{Deserialize, Serialize};
11use serde_json::value::RawValue;
12
13use crate::ext::ExtRequest;
14use crate::{ClientCapabilities, ContentBlock, ExtNotification, ProtocolVersion, SessionId};
15
16// Initialize
17
18/// Request parameters for the initialize method.
19///
20/// Sent by the client to establish connection and negotiate capabilities.
21///
22/// See protocol docs: [Initialization](https://agentclientprotocol.com/protocol/initialization)
23#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
24#[schemars(extend("x-side" = "agent", "x-method" = INITIALIZE_METHOD_NAME))]
25#[serde(rename_all = "camelCase")]
26#[non_exhaustive]
27pub struct InitializeRequest {
28    /// The latest protocol version supported by the client.
29    pub protocol_version: ProtocolVersion,
30    /// Capabilities supported by the client.
31    #[serde(default)]
32    pub client_capabilities: ClientCapabilities,
33    /// Information about the Client name and version sent to the Agent.
34    ///
35    /// Note: in future versions of the protocol, this will be required.
36    #[serde(skip_serializing_if = "Option::is_none")]
37    pub client_info: Option<Implementation>,
38    /// Extension point for implementations
39    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
40    pub meta: Option<serde_json::Value>,
41}
42
43impl InitializeRequest {
44    #[must_use]
45    pub fn new(protocol_version: ProtocolVersion) -> Self {
46        Self {
47            protocol_version,
48            client_capabilities: ClientCapabilities::default(),
49            client_info: None,
50            meta: None,
51        }
52    }
53
54    /// Capabilities supported by the client.
55    #[must_use]
56    pub fn client_capabilities(mut self, client_capabilities: ClientCapabilities) -> Self {
57        self.client_capabilities = client_capabilities;
58        self
59    }
60
61    /// Information about the Client name and version sent to the Agent.
62    #[must_use]
63    pub fn client_info(mut self, client_info: Implementation) -> Self {
64        self.client_info = Some(client_info);
65        self
66    }
67
68    /// Extension point for implementations
69    #[must_use]
70    pub fn meta(mut self, meta: serde_json::Value) -> Self {
71        self.meta = Some(meta);
72        self
73    }
74}
75
76/// Response to the `initialize` method.
77///
78/// Contains the negotiated protocol version and agent capabilities.
79///
80/// See protocol docs: [Initialization](https://agentclientprotocol.com/protocol/initialization)
81#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
82#[schemars(extend("x-side" = "agent", "x-method" = INITIALIZE_METHOD_NAME))]
83#[serde(rename_all = "camelCase")]
84#[non_exhaustive]
85pub struct InitializeResponse {
86    /// The protocol version the client specified if supported by the agent,
87    /// or the latest protocol version supported by the agent.
88    ///
89    /// The client should disconnect, if it doesn't support this version.
90    pub protocol_version: ProtocolVersion,
91    /// Capabilities supported by the agent.
92    #[serde(default)]
93    pub agent_capabilities: AgentCapabilities,
94    /// Authentication methods supported by the agent.
95    #[serde(default)]
96    pub auth_methods: Vec<AuthMethod>,
97    /// Information about the Agent name and version sent to the Client.
98    ///
99    /// Note: in future versions of the protocol, this will be required.
100    #[serde(skip_serializing_if = "Option::is_none")]
101    pub agent_info: Option<Implementation>,
102    /// Extension point for implementations
103    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
104    pub meta: Option<serde_json::Value>,
105}
106
107impl InitializeResponse {
108    #[must_use]
109    pub fn new(protocol_version: ProtocolVersion) -> Self {
110        Self {
111            protocol_version,
112            agent_capabilities: AgentCapabilities::default(),
113            auth_methods: vec![],
114            agent_info: None,
115            meta: None,
116        }
117    }
118
119    /// Capabilities supported by the agent.
120    #[must_use]
121    pub fn agent_capabilities(mut self, agent_capabilities: AgentCapabilities) -> Self {
122        self.agent_capabilities = agent_capabilities;
123        self
124    }
125
126    /// Authentication methods supported by the agent.
127    #[must_use]
128    pub fn auth_methods(mut self, auth_methods: Vec<AuthMethod>) -> Self {
129        self.auth_methods = auth_methods;
130        self
131    }
132
133    /// Information about the Agent name and version sent to the Client.
134    #[must_use]
135    pub fn agent_info(mut self, agent_info: Implementation) -> Self {
136        self.agent_info = Some(agent_info);
137        self
138    }
139
140    /// Extension point for implementations
141    #[must_use]
142    pub fn meta(mut self, meta: serde_json::Value) -> Self {
143        self.meta = Some(meta);
144        self
145    }
146}
147
148/// Metadata about the implementation of the client or agent.
149/// Describes the name and version of an MCP implementation, with an optional
150/// title for UI representation.
151#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
152#[serde(rename_all = "camelCase")]
153#[non_exhaustive]
154pub struct Implementation {
155    /// Intended for programmatic or logical use, but can be used as a display
156    /// name fallback if title isn’t present.
157    pub name: String,
158    /// Intended for UI and end-user contexts — optimized to be human-readable
159    /// and easily understood.
160    ///
161    /// If not provided, the name should be used for display.
162    pub title: Option<String>,
163    /// Version of the implementation. Can be displayed to the user or used
164    /// for debugging or metrics purposes. (e.g. "1.0.0").
165    pub version: String,
166    /// Extension point for implementations
167    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
168    pub meta: Option<serde_json::Value>,
169}
170
171impl Implementation {
172    pub fn new(name: impl Into<String>, version: impl Into<String>) -> Self {
173        Self {
174            name: name.into(),
175            title: None,
176            version: version.into(),
177            meta: None,
178        }
179    }
180
181    /// Intended for UI and end-user contexts — optimized to be human-readable
182    /// and easily understood.
183    ///
184    /// If not provided, the name should be used for display.
185    #[must_use]
186    pub fn title(mut self, title: impl Into<String>) -> Self {
187        self.title = Some(title.into());
188        self
189    }
190
191    /// Extension point for implementations
192    #[must_use]
193    pub fn meta(mut self, meta: serde_json::Value) -> Self {
194        self.meta = Some(meta);
195        self
196    }
197}
198
199// Authentication
200
201/// Request parameters for the authenticate method.
202///
203/// Specifies which authentication method to use.
204#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
205#[schemars(extend("x-side" = "agent", "x-method" = AUTHENTICATE_METHOD_NAME))]
206#[serde(rename_all = "camelCase")]
207#[non_exhaustive]
208pub struct AuthenticateRequest {
209    /// The ID of the authentication method to use.
210    /// Must be one of the methods advertised in the initialize response.
211    pub method_id: AuthMethodId,
212    /// Extension point for implementations
213    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
214    pub meta: Option<serde_json::Value>,
215}
216
217impl AuthenticateRequest {
218    #[must_use]
219    pub fn new(method_id: AuthMethodId) -> Self {
220        Self {
221            method_id,
222            meta: None,
223        }
224    }
225
226    #[must_use]
227    pub fn meta(mut self, meta: serde_json::Value) -> Self {
228        self.meta = Some(meta);
229        self
230    }
231}
232
233/// Response to the `authenticate` method.
234#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
235#[serde(rename_all = "camelCase")]
236#[schemars(extend("x-side" = "agent", "x-method" = AUTHENTICATE_METHOD_NAME))]
237#[non_exhaustive]
238pub struct AuthenticateResponse {
239    /// Extension point for implementations
240    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
241    pub meta: Option<serde_json::Value>,
242}
243
244impl AuthenticateResponse {
245    #[must_use]
246    pub fn new() -> Self {
247        Self::default()
248    }
249
250    #[must_use]
251    pub fn meta(mut self, meta: serde_json::Value) -> Self {
252        self.meta = Some(meta);
253        self
254    }
255}
256
257#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, Display, From)]
258#[serde(transparent)]
259#[from(Arc<str>, String, &'static str)]
260#[non_exhaustive]
261pub struct AuthMethodId(pub Arc<str>);
262
263impl AuthMethodId {
264    pub fn new(id: impl Into<Arc<str>>) -> Self {
265        Self(id.into())
266    }
267}
268
269/// Describes an available authentication method.
270#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
271#[serde(rename_all = "camelCase")]
272#[non_exhaustive]
273pub struct AuthMethod {
274    /// Unique identifier for this authentication method.
275    pub id: AuthMethodId,
276    /// Human-readable name of the authentication method.
277    pub name: String,
278    /// Optional description providing more details about this authentication method.
279    pub description: Option<String>,
280    /// Extension point for implementations
281    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
282    pub meta: Option<serde_json::Value>,
283}
284
285impl AuthMethod {
286    pub fn new(id: AuthMethodId, name: impl Into<String>) -> Self {
287        Self {
288            id,
289            name: name.into(),
290            description: None,
291            meta: None,
292        }
293    }
294
295    /// Optional description providing more details about this authentication method.
296    #[must_use]
297    pub fn description(mut self, description: impl Into<String>) -> Self {
298        self.description = Some(description.into());
299        self
300    }
301
302    /// Extension point for implementations
303    #[must_use]
304    pub fn meta(mut self, meta: serde_json::Value) -> Self {
305        self.meta = Some(meta);
306        self
307    }
308}
309
310// New session
311
312/// Request parameters for creating a new session.
313///
314/// See protocol docs: [Creating a Session](https://agentclientprotocol.com/protocol/session-setup#creating-a-session)
315#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
316#[schemars(extend("x-side" = "agent", "x-method" = SESSION_NEW_METHOD_NAME))]
317#[serde(rename_all = "camelCase")]
318#[non_exhaustive]
319pub struct NewSessionRequest {
320    /// The working directory for this session. Must be an absolute path.
321    pub cwd: PathBuf,
322    /// List of MCP (Model Context Protocol) servers the agent should connect to.
323    pub mcp_servers: Vec<McpServer>,
324    /// Extension point for implementations
325    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
326    pub meta: Option<serde_json::Value>,
327}
328
329impl NewSessionRequest {
330    pub fn new(cwd: impl Into<PathBuf>) -> Self {
331        Self {
332            cwd: cwd.into(),
333            mcp_servers: vec![],
334            meta: None,
335        }
336    }
337
338    /// List of MCP (Model Context Protocol) servers the agent should connect to.
339    #[must_use]
340    pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
341        self.mcp_servers = mcp_servers;
342        self
343    }
344
345    /// Extension point for implementations
346    #[must_use]
347    pub fn meta(mut self, meta: serde_json::Value) -> Self {
348        self.meta = Some(meta);
349        self
350    }
351}
352
353/// Response from 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 NewSessionResponse {
361    /// Unique identifier for the created session.
362    ///
363    /// Used in all subsequent requests for this conversation.
364    pub session_id: SessionId,
365    /// Initial mode state if supported by the Agent
366    ///
367    /// See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
368    #[serde(skip_serializing_if = "Option::is_none")]
369    pub modes: Option<SessionModeState>,
370    /// **UNSTABLE**
371    ///
372    /// This capability is not part of the spec yet, and may be removed or changed at any point.
373    ///
374    /// Initial model state if supported by the Agent
375    #[cfg(feature = "unstable_session_model")]
376    #[serde(skip_serializing_if = "Option::is_none")]
377    pub models: Option<SessionModelState>,
378    /// Extension point for implementations
379    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
380    pub meta: Option<serde_json::Value>,
381}
382
383impl NewSessionResponse {
384    #[must_use]
385    pub fn new(session_id: SessionId) -> Self {
386        Self {
387            session_id,
388            modes: None,
389            #[cfg(feature = "unstable_session_model")]
390            models: None,
391            meta: None,
392        }
393    }
394
395    /// Initial mode state if supported by the Agent
396    ///
397    /// See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
398    #[must_use]
399    pub fn modes(mut self, modes: SessionModeState) -> Self {
400        self.modes = Some(modes);
401        self
402    }
403
404    /// **UNSTABLE**
405    ///
406    /// This capability is not part of the spec yet, and may be removed or changed at any point.
407    ///
408    /// Initial model state if supported by the Agent
409    #[cfg(feature = "unstable_session_model")]
410    #[must_use]
411    pub fn models(mut self, models: SessionModelState) -> Self {
412        self.models = Some(models);
413        self
414    }
415
416    /// Extension point for implementations
417    #[must_use]
418    pub fn meta(mut self, meta: serde_json::Value) -> Self {
419        self.meta = Some(meta);
420        self
421    }
422}
423
424// Load session
425
426/// Request parameters for loading an existing session.
427///
428/// Only available if the Agent supports the `loadSession` capability.
429///
430/// See protocol docs: [Loading Sessions](https://agentclientprotocol.com/protocol/session-setup#loading-sessions)
431#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
432#[schemars(extend("x-side" = "agent", "x-method" = SESSION_LOAD_METHOD_NAME))]
433#[serde(rename_all = "camelCase")]
434#[non_exhaustive]
435pub struct LoadSessionRequest {
436    /// List of MCP servers to connect to for this session.
437    pub mcp_servers: Vec<McpServer>,
438    /// The working directory for this session.
439    pub cwd: PathBuf,
440    /// The ID of the session to load.
441    pub session_id: SessionId,
442    /// Extension point for implementations
443    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
444    pub meta: Option<serde_json::Value>,
445}
446
447impl LoadSessionRequest {
448    pub fn new(session_id: SessionId, cwd: impl Into<PathBuf>) -> Self {
449        Self {
450            mcp_servers: vec![],
451            cwd: cwd.into(),
452            session_id,
453            meta: None,
454        }
455    }
456
457    /// List of MCP servers to connect to for this session.
458    #[must_use]
459    pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
460        self.mcp_servers = mcp_servers;
461        self
462    }
463
464    /// Extension point for implementations
465    #[must_use]
466    pub fn meta(mut self, meta: serde_json::Value) -> Self {
467        self.meta = Some(meta);
468        self
469    }
470}
471
472/// Response from loading an existing session.
473#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
474#[schemars(extend("x-side" = "agent", "x-method" = SESSION_LOAD_METHOD_NAME))]
475#[serde(rename_all = "camelCase")]
476#[non_exhaustive]
477pub struct LoadSessionResponse {
478    /// Initial mode state if supported by the Agent
479    ///
480    /// See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
481    #[serde(default, skip_serializing_if = "Option::is_none")]
482    pub modes: Option<SessionModeState>,
483    /// **UNSTABLE**
484    ///
485    /// This capability is not part of the spec yet, and may be removed or changed at any point.
486    ///
487    /// Initial model state if supported by the Agent
488    #[cfg(feature = "unstable_session_model")]
489    #[serde(default, skip_serializing_if = "Option::is_none")]
490    pub models: Option<SessionModelState>,
491    /// Extension point for implementations
492    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
493    pub meta: Option<serde_json::Value>,
494}
495
496impl LoadSessionResponse {
497    #[must_use]
498    pub fn new() -> Self {
499        Self::default()
500    }
501
502    /// Initial mode state if supported by the Agent
503    ///
504    /// See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
505    #[must_use]
506    pub fn modes(mut self, modes: SessionModeState) -> Self {
507        self.modes = Some(modes);
508        self
509    }
510
511    /// **UNSTABLE**
512    ///
513    /// This capability is not part of the spec yet, and may be removed or changed at any point.
514    ///
515    /// Initial model state if supported by the Agent
516    #[cfg(feature = "unstable_session_model")]
517    #[must_use]
518    pub fn models(mut self, models: SessionModelState) -> Self {
519        self.models = Some(models);
520        self
521    }
522
523    /// Extension point for implementations
524    #[must_use]
525    pub fn meta(mut self, meta: serde_json::Value) -> Self {
526        self.meta = Some(meta);
527        self
528    }
529}
530
531// List sessions
532
533/// **UNSTABLE**
534///
535/// This capability is not part of the spec yet, and may be removed or changed at any point.
536///
537/// Request parameters for listing existing sessions.
538///
539/// Only available if the Agent supports the `listSessions` capability.
540#[cfg(feature = "unstable_session_list")]
541#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
542#[schemars(extend("x-side" = "agent", "x-method" = SESSION_LIST_METHOD_NAME))]
543#[serde(rename_all = "camelCase")]
544#[non_exhaustive]
545pub struct ListSessionsRequest {
546    /// Filter sessions by working directory. Must be an absolute path.
547    #[serde(skip_serializing_if = "Option::is_none")]
548    pub cwd: Option<PathBuf>,
549    /// Opaque cursor token from a previous response's nextCursor field for cursor-based pagination
550    #[serde(skip_serializing_if = "Option::is_none")]
551    pub cursor: Option<String>,
552    /// Extension point for implementations
553    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
554    pub meta: Option<serde_json::Value>,
555}
556
557#[cfg(feature = "unstable_session_list")]
558impl ListSessionsRequest {
559    #[must_use]
560    pub fn new() -> Self {
561        Self::default()
562    }
563
564    /// Filter sessions by working directory. Must be an absolute path.
565    #[must_use]
566    pub fn cwd(mut self, cwd: impl Into<PathBuf>) -> Self {
567        self.cwd = Some(cwd.into());
568        self
569    }
570
571    /// Opaque cursor token from a previous response's nextCursor field for cursor-based pagination
572    #[must_use]
573    pub fn cursor(mut self, cursor: impl Into<String>) -> Self {
574        self.cursor = Some(cursor.into());
575        self
576    }
577
578    /// Extension point for implementations
579    #[must_use]
580    pub fn meta(mut self, meta: serde_json::Value) -> Self {
581        self.meta = Some(meta);
582        self
583    }
584}
585
586/// **UNSTABLE**
587///
588/// This capability is not part of the spec yet, and may be removed or changed at any point.
589///
590/// Response from listing sessions.
591#[cfg(feature = "unstable_session_list")]
592#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
593#[schemars(extend("x-side" = "agent", "x-method" = SESSION_LIST_METHOD_NAME))]
594#[serde(rename_all = "camelCase")]
595#[non_exhaustive]
596pub struct ListSessionsResponse {
597    /// Array of session information objects
598    pub sessions: Vec<SessionInfo>,
599    /// Opaque cursor token. If present, pass this in the next request's cursor parameter
600    /// to fetch the next page. If absent, there are no more results.
601    #[serde(skip_serializing_if = "Option::is_none")]
602    pub next_cursor: Option<String>,
603    /// Extension point for implementations
604    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
605    pub meta: Option<serde_json::Value>,
606}
607
608#[cfg(feature = "unstable_session_list")]
609impl ListSessionsResponse {
610    #[must_use]
611    pub fn new(sessions: Vec<SessionInfo>) -> Self {
612        Self {
613            sessions,
614            next_cursor: None,
615            meta: None,
616        }
617    }
618
619    #[must_use]
620    pub fn next_cursor(mut self, next_cursor: impl Into<String>) -> Self {
621        self.next_cursor = Some(next_cursor.into());
622        self
623    }
624
625    /// Extension point for implementations
626    #[must_use]
627    pub fn meta(mut self, meta: serde_json::Value) -> Self {
628        self.meta = Some(meta);
629        self
630    }
631}
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/// Information about a session returned by session/list
638#[cfg(feature = "unstable_session_list")]
639#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
640#[serde(rename_all = "camelCase")]
641#[non_exhaustive]
642pub struct SessionInfo {
643    /// Unique identifier for the session
644    pub session_id: SessionId,
645    /// The working directory for this session. Must be an absolute path.
646    pub cwd: PathBuf,
647    /// Human-readable title for the session
648    #[serde(skip_serializing_if = "Option::is_none")]
649    pub title: Option<String>,
650    /// ISO 8601 timestamp of last activity
651    #[serde(skip_serializing_if = "Option::is_none")]
652    pub updated_at: Option<String>,
653    /// Extension point for implementations
654    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
655    pub meta: Option<serde_json::Value>,
656}
657
658#[cfg(feature = "unstable_session_list")]
659impl SessionInfo {
660    pub fn new(session_id: SessionId, cwd: impl Into<PathBuf>) -> Self {
661        Self {
662            session_id,
663            cwd: cwd.into(),
664            title: None,
665            updated_at: None,
666            meta: None,
667        }
668    }
669
670    /// Human-readable title for the session
671    #[must_use]
672    pub fn title(mut self, title: impl Into<String>) -> Self {
673        self.title = Some(title.into());
674        self
675    }
676
677    /// ISO 8601 timestamp of last activity
678    #[must_use]
679    pub fn updated_at(mut self, updated_at: impl Into<String>) -> Self {
680        self.updated_at = Some(updated_at.into());
681        self
682    }
683
684    /// Extension point for implementations
685    #[must_use]
686    pub fn meta(mut self, meta: serde_json::Value) -> Self {
687        self.meta = Some(meta);
688        self
689    }
690}
691
692// Session modes
693
694/// The set of modes and the one currently active.
695#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
696#[serde(rename_all = "camelCase")]
697#[non_exhaustive]
698pub struct SessionModeState {
699    /// The current mode the Agent is in.
700    pub current_mode_id: SessionModeId,
701    /// The set of modes that the Agent can operate in
702    pub available_modes: Vec<SessionMode>,
703    /// Extension point for implementations
704    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
705    pub meta: Option<serde_json::Value>,
706}
707
708impl SessionModeState {
709    #[must_use]
710    pub fn new(current_mode_id: SessionModeId, available_modes: Vec<SessionMode>) -> Self {
711        Self {
712            current_mode_id,
713            available_modes,
714            meta: None,
715        }
716    }
717
718    /// Extension point for implementations
719    #[must_use]
720    pub fn meta(mut self, meta: serde_json::Value) -> Self {
721        self.meta = Some(meta);
722        self
723    }
724}
725
726/// A mode the agent can operate in.
727///
728/// See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
729#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
730#[serde(rename_all = "camelCase")]
731#[non_exhaustive]
732pub struct SessionMode {
733    pub id: SessionModeId,
734    pub name: String,
735    #[serde(default, skip_serializing_if = "Option::is_none")]
736    pub description: Option<String>,
737    /// Extension point for implementations
738    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
739    pub meta: Option<serde_json::Value>,
740}
741
742impl SessionMode {
743    pub fn new(id: SessionModeId, name: impl Into<String>) -> Self {
744        Self {
745            id,
746            name: name.into(),
747            description: None,
748            meta: None,
749        }
750    }
751
752    #[must_use]
753    pub fn description(mut self, description: impl Into<String>) -> Self {
754        self.description = Some(description.into());
755        self
756    }
757
758    /// Extension point for implementations
759    #[must_use]
760    pub fn meta(mut self, meta: serde_json::Value) -> Self {
761        self.meta = Some(meta);
762        self
763    }
764}
765
766/// Unique identifier for a Session Mode.
767#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, From, Display)]
768#[serde(transparent)]
769#[from(Arc<str>, String, &'static str)]
770#[non_exhaustive]
771pub struct SessionModeId(pub Arc<str>);
772
773impl SessionModeId {
774    pub fn new(id: impl Into<Arc<str>>) -> Self {
775        Self(id.into())
776    }
777}
778
779/// Request parameters for setting a session mode.
780#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
781#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_MODE_METHOD_NAME))]
782#[serde(rename_all = "camelCase")]
783#[non_exhaustive]
784pub struct SetSessionModeRequest {
785    /// The ID of the session to set the mode for.
786    pub session_id: SessionId,
787    /// The ID of the mode to set.
788    pub mode_id: SessionModeId,
789    /// Extension point for implementations
790    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
791    pub meta: Option<serde_json::Value>,
792}
793
794impl SetSessionModeRequest {
795    #[must_use]
796    pub fn new(session_id: SessionId, mode_id: SessionModeId) -> Self {
797        Self {
798            session_id,
799            mode_id,
800            meta: None,
801        }
802    }
803
804    #[must_use]
805    pub fn meta(mut self, meta: serde_json::Value) -> Self {
806        self.meta = Some(meta);
807        self
808    }
809}
810
811/// Response to `session/set_mode` method.
812#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
813#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_MODE_METHOD_NAME))]
814#[serde(rename_all = "camelCase")]
815#[non_exhaustive]
816pub struct SetSessionModeResponse {
817    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
818    pub meta: Option<serde_json::Value>,
819}
820
821impl SetSessionModeResponse {
822    #[must_use]
823    pub fn new() -> Self {
824        Self::default()
825    }
826
827    #[must_use]
828    pub fn meta(mut self, meta: serde_json::Value) -> Self {
829        self.meta = Some(meta);
830        self
831    }
832}
833
834// MCP
835
836/// Configuration for connecting to an MCP (Model Context Protocol) server.
837///
838/// MCP servers provide tools and context that the agent can use when
839/// processing prompts.
840///
841/// See protocol docs: [MCP Servers](https://agentclientprotocol.com/protocol/session-setup#mcp-servers)
842#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
843#[serde(tag = "type", rename_all = "snake_case")]
844#[schemars(extend("discriminator" = {"propertyName": "type"}))]
845#[non_exhaustive]
846pub enum McpServer {
847    /// HTTP transport configuration
848    ///
849    /// Only available when the Agent capabilities indicate `mcp_capabilities.http` is `true`.
850    Http(McpServerHttp),
851    /// SSE transport configuration
852    ///
853    /// Only available when the Agent capabilities indicate `mcp_capabilities.sse` is `true`.
854    Sse(McpServerSse),
855    /// Stdio transport configuration
856    ///
857    /// All Agents MUST support this transport.
858    #[serde(untagged)]
859    Stdio(McpServerStdio),
860}
861
862/// HTTP transport configuration for MCP.
863#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
864#[serde(rename_all = "camelCase")]
865#[non_exhaustive]
866pub struct McpServerHttp {
867    /// Human-readable name identifying this MCP server.
868    pub name: String,
869    /// URL to the MCP server.
870    pub url: String,
871    /// HTTP headers to set when making requests to the MCP server.
872    pub headers: Vec<HttpHeader>,
873    /// Extension point for implementations
874    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
875    pub meta: Option<serde_json::Value>,
876}
877
878impl McpServerHttp {
879    pub fn new(name: impl Into<String>, url: impl Into<String>) -> Self {
880        Self {
881            name: name.into(),
882            url: url.into(),
883            headers: Vec::new(),
884            meta: None,
885        }
886    }
887
888    /// HTTP headers to set when making requests to the MCP server.
889    #[must_use]
890    pub fn headers(mut self, headers: Vec<HttpHeader>) -> Self {
891        self.headers = headers;
892        self
893    }
894
895    /// Extension point for implementations
896    #[must_use]
897    pub fn meta(mut self, meta: serde_json::Value) -> Self {
898        self.meta = Some(meta);
899        self
900    }
901}
902
903/// SSE transport configuration for MCP.
904#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
905#[serde(rename_all = "camelCase")]
906#[non_exhaustive]
907pub struct McpServerSse {
908    /// Human-readable name identifying this MCP server.
909    pub name: String,
910    /// URL to the MCP server.
911    pub url: String,
912    /// HTTP headers to set when making requests to the MCP server.
913    pub headers: Vec<HttpHeader>,
914    /// Extension point for implementations
915    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
916    pub meta: Option<serde_json::Value>,
917}
918
919impl McpServerSse {
920    pub fn new(name: impl Into<String>, url: impl Into<String>) -> Self {
921        Self {
922            name: name.into(),
923            url: url.into(),
924            headers: Vec::new(),
925            meta: None,
926        }
927    }
928
929    /// HTTP headers to set when making requests to the MCP server.
930    #[must_use]
931    pub fn headers(mut self, headers: Vec<HttpHeader>) -> Self {
932        self.headers = headers;
933        self
934    }
935
936    /// Extension point for implementations
937    #[must_use]
938    pub fn meta(mut self, meta: serde_json::Value) -> Self {
939        self.meta = Some(meta);
940        self
941    }
942}
943
944/// Stdio transport configuration for MCP.
945#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
946#[serde(rename_all = "camelCase")]
947#[non_exhaustive]
948pub struct McpServerStdio {
949    /// Human-readable name identifying this MCP server.
950    pub name: String,
951    /// Path to the MCP server executable.
952    pub command: PathBuf,
953    /// Command-line arguments to pass to the MCP server.
954    pub args: Vec<String>,
955    /// Environment variables to set when launching the MCP server.
956    pub env: Vec<EnvVariable>,
957    /// Extension point for implementations
958    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
959    pub meta: Option<serde_json::Value>,
960}
961
962impl McpServerStdio {
963    pub fn new(name: impl Into<String>, command: impl Into<PathBuf>) -> Self {
964        Self {
965            name: name.into(),
966            command: command.into(),
967            args: Vec::new(),
968            env: Vec::new(),
969            meta: None,
970        }
971    }
972
973    /// Command-line arguments to pass to the MCP server.
974    #[must_use]
975    pub fn args(mut self, args: Vec<String>) -> Self {
976        self.args = args;
977        self
978    }
979
980    /// Environment variables to set when launching the MCP server.
981    #[must_use]
982    pub fn env(mut self, env: Vec<EnvVariable>) -> Self {
983        self.env = env;
984        self
985    }
986
987    /// Extension point for implementations
988    #[must_use]
989    pub fn meta(mut self, meta: serde_json::Value) -> Self {
990        self.meta = Some(meta);
991        self
992    }
993}
994
995/// An environment variable to set when launching an MCP server.
996#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
997#[serde(rename_all = "camelCase")]
998#[non_exhaustive]
999pub struct EnvVariable {
1000    /// The name of the environment variable.
1001    pub name: String,
1002    /// The value to set for the environment variable.
1003    pub value: String,
1004    /// Extension point for implementations
1005    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1006    pub meta: Option<serde_json::Value>,
1007}
1008
1009impl EnvVariable {
1010    pub fn new(name: impl Into<String>, value: impl Into<String>) -> Self {
1011        Self {
1012            name: name.into(),
1013            value: value.into(),
1014            meta: None,
1015        }
1016    }
1017
1018    /// Extension point for implementations
1019    #[must_use]
1020    pub fn meta(mut self, meta: serde_json::Value) -> Self {
1021        self.meta = Some(meta);
1022        self
1023    }
1024}
1025
1026/// An HTTP header to set when making requests to the MCP server.
1027#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1028#[serde(rename_all = "camelCase")]
1029#[non_exhaustive]
1030pub struct HttpHeader {
1031    /// The name of the HTTP header.
1032    pub name: String,
1033    /// The value to set for the HTTP header.
1034    pub value: String,
1035    /// Extension point for implementations
1036    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1037    pub meta: Option<serde_json::Value>,
1038}
1039
1040impl HttpHeader {
1041    pub fn new(name: impl Into<String>, value: impl Into<String>) -> Self {
1042        Self {
1043            name: name.into(),
1044            value: value.into(),
1045            meta: None,
1046        }
1047    }
1048
1049    /// Extension point for implementations
1050    #[must_use]
1051    pub fn meta(mut self, meta: serde_json::Value) -> Self {
1052        self.meta = Some(meta);
1053        self
1054    }
1055}
1056
1057// Prompt
1058
1059/// Request parameters for sending a user prompt to the agent.
1060///
1061/// Contains the user's message and any additional context.
1062///
1063/// See protocol docs: [User Message](https://agentclientprotocol.com/protocol/prompt-turn#1-user-message)
1064#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
1065#[schemars(extend("x-side" = "agent", "x-method" = SESSION_PROMPT_METHOD_NAME))]
1066#[serde(rename_all = "camelCase")]
1067#[non_exhaustive]
1068pub struct PromptRequest {
1069    /// The ID of the session to send this user message to
1070    pub session_id: SessionId,
1071    /// The blocks of content that compose the user's message.
1072    ///
1073    /// As a baseline, the Agent MUST support [`ContentBlock::Text`] and [`ContentBlock::ResourceLink`],
1074    /// while other variants are optionally enabled via [`PromptCapabilities`].
1075    ///
1076    /// The Client MUST adapt its interface according to [`PromptCapabilities`].
1077    ///
1078    /// The client MAY include referenced pieces of context as either
1079    /// [`ContentBlock::Resource`] or [`ContentBlock::ResourceLink`].
1080    ///
1081    /// When available, [`ContentBlock::Resource`] is preferred
1082    /// as it avoids extra round-trips and allows the message to include
1083    /// pieces of context from sources the agent may not have access to.
1084    pub prompt: Vec<ContentBlock>,
1085    /// Extension point for implementations
1086    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1087    pub meta: Option<serde_json::Value>,
1088}
1089
1090impl PromptRequest {
1091    #[must_use]
1092    pub fn new(session_id: SessionId, prompt: Vec<ContentBlock>) -> Self {
1093        Self {
1094            session_id,
1095            prompt,
1096            meta: None,
1097        }
1098    }
1099
1100    /// Extension point for implementations
1101    #[must_use]
1102    pub fn meta(mut self, meta: serde_json::Value) -> Self {
1103        self.meta = Some(meta);
1104        self
1105    }
1106}
1107
1108/// Response from processing a user prompt.
1109///
1110/// See protocol docs: [Check for Completion](https://agentclientprotocol.com/protocol/prompt-turn#4-check-for-completion)
1111#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1112#[schemars(extend("x-side" = "agent", "x-method" = SESSION_PROMPT_METHOD_NAME))]
1113#[serde(rename_all = "camelCase")]
1114#[non_exhaustive]
1115pub struct PromptResponse {
1116    /// Indicates why the agent stopped processing the turn.
1117    pub stop_reason: StopReason,
1118    /// Extension point for implementations
1119    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1120    pub meta: Option<serde_json::Value>,
1121}
1122
1123impl PromptResponse {
1124    #[must_use]
1125    pub fn new(stop_reason: StopReason) -> Self {
1126        Self {
1127            stop_reason,
1128            meta: None,
1129        }
1130    }
1131
1132    /// Extension point for implementations
1133    #[must_use]
1134    pub fn meta(mut self, meta: serde_json::Value) -> Self {
1135        self.meta = Some(meta);
1136        self
1137    }
1138}
1139
1140/// Reasons why an agent stops processing a prompt turn.
1141///
1142/// See protocol docs: [Stop Reasons](https://agentclientprotocol.com/protocol/prompt-turn#stop-reasons)
1143#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
1144#[serde(rename_all = "snake_case")]
1145#[non_exhaustive]
1146pub enum StopReason {
1147    /// The turn ended successfully.
1148    EndTurn,
1149    /// The turn ended because the agent reached the maximum number of tokens.
1150    MaxTokens,
1151    /// The turn ended because the agent reached the maximum number of allowed
1152    /// agent requests between user turns.
1153    MaxTurnRequests,
1154    /// The turn ended because the agent refused to continue. The user prompt
1155    /// and everything that comes after it won't be included in the next
1156    /// prompt, so this should be reflected in the UI.
1157    Refusal,
1158    /// The turn was cancelled by the client via `session/cancel`.
1159    ///
1160    /// This stop reason MUST be returned when the client sends a `session/cancel`
1161    /// notification, even if the cancellation causes exceptions in underlying operations.
1162    /// Agents should catch these exceptions and return this semantically meaningful
1163    /// response to confirm successful cancellation.
1164    Cancelled,
1165}
1166
1167// Model
1168
1169/// **UNSTABLE**
1170///
1171/// This capability is not part of the spec yet, and may be removed or changed at any point.
1172///
1173/// The set of models and the one currently active.
1174#[cfg(feature = "unstable_session_model")]
1175#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1176#[serde(rename_all = "camelCase")]
1177#[non_exhaustive]
1178pub struct SessionModelState {
1179    /// The current model the Agent is in.
1180    pub current_model_id: ModelId,
1181    /// The set of models that the Agent can use
1182    pub available_models: Vec<ModelInfo>,
1183    /// Extension point for implementations
1184    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1185    pub meta: Option<serde_json::Value>,
1186}
1187
1188#[cfg(feature = "unstable_session_model")]
1189impl SessionModelState {
1190    #[must_use]
1191    pub fn new(current_model_id: ModelId, available_models: Vec<ModelInfo>) -> Self {
1192        Self {
1193            current_model_id,
1194            available_models,
1195            meta: None,
1196        }
1197    }
1198
1199    /// Extension point for implementations
1200    #[must_use]
1201    pub fn meta(mut self, meta: serde_json::Value) -> Self {
1202        self.meta = Some(meta);
1203        self
1204    }
1205}
1206
1207/// **UNSTABLE**
1208///
1209/// This capability is not part of the spec yet, and may be removed or changed at any point.
1210///
1211/// A unique identifier for a model.
1212#[cfg(feature = "unstable_session_model")]
1213#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, Display, From)]
1214#[serde(transparent)]
1215#[from(Arc<str>, String, &'static str)]
1216#[non_exhaustive]
1217pub struct ModelId(pub Arc<str>);
1218
1219#[cfg(feature = "unstable_session_model")]
1220impl ModelId {
1221    pub fn new(id: impl Into<Arc<str>>) -> Self {
1222        Self(id.into())
1223    }
1224}
1225
1226/// **UNSTABLE**
1227///
1228/// This capability is not part of the spec yet, and may be removed or changed at any point.
1229///
1230/// Information about a selectable model.
1231#[cfg(feature = "unstable_session_model")]
1232#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1233#[serde(rename_all = "camelCase")]
1234#[non_exhaustive]
1235pub struct ModelInfo {
1236    /// Unique identifier for the model.
1237    pub model_id: ModelId,
1238    /// Human-readable name of the model.
1239    pub name: String,
1240    /// Optional description of the model.
1241    #[serde(default, skip_serializing_if = "Option::is_none")]
1242    pub description: Option<String>,
1243    /// Extension point for implementations
1244    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1245    pub meta: Option<serde_json::Value>,
1246}
1247
1248#[cfg(feature = "unstable_session_model")]
1249impl ModelInfo {
1250    pub fn new(model_id: ModelId, name: impl Into<String>) -> Self {
1251        Self {
1252            model_id,
1253            name: name.into(),
1254            description: None,
1255            meta: None,
1256        }
1257    }
1258
1259    /// Optional description of the model.
1260    #[must_use]
1261    pub fn description(mut self, description: impl Into<String>) -> Self {
1262        self.description = Some(description.into());
1263        self
1264    }
1265
1266    /// Extension point for implementations
1267    #[must_use]
1268    pub fn meta(mut self, meta: serde_json::Value) -> Self {
1269        self.meta = Some(meta);
1270        self
1271    }
1272}
1273
1274/// **UNSTABLE**
1275///
1276/// This capability is not part of the spec yet, and may be removed or changed at any point.
1277///
1278/// Request parameters for setting a session model.
1279#[cfg(feature = "unstable_session_model")]
1280#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1281#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_MODEL_METHOD_NAME))]
1282#[serde(rename_all = "camelCase")]
1283#[non_exhaustive]
1284pub struct SetSessionModelRequest {
1285    /// The ID of the session to set the model for.
1286    pub session_id: SessionId,
1287    /// The ID of the model to set.
1288    pub model_id: ModelId,
1289    /// Extension point for implementations
1290    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1291    pub meta: Option<serde_json::Value>,
1292}
1293
1294#[cfg(feature = "unstable_session_model")]
1295impl SetSessionModelRequest {
1296    #[must_use]
1297    pub fn new(session_id: SessionId, model_id: ModelId) -> Self {
1298        Self {
1299            session_id,
1300            model_id,
1301            meta: None,
1302        }
1303    }
1304
1305    /// Extension point for implementations
1306    #[must_use]
1307    pub fn meta(mut self, meta: serde_json::Value) -> Self {
1308        self.meta = Some(meta);
1309        self
1310    }
1311}
1312
1313/// **UNSTABLE**
1314///
1315/// This capability is not part of the spec yet, and may be removed or changed at any point.
1316///
1317/// Response to `session/set_model` method.
1318#[cfg(feature = "unstable_session_model")]
1319#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1320#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_MODEL_METHOD_NAME))]
1321#[serde(rename_all = "camelCase")]
1322#[non_exhaustive]
1323pub struct SetSessionModelResponse {
1324    /// Extension point for implementations
1325    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1326    pub meta: Option<serde_json::Value>,
1327}
1328
1329#[cfg(feature = "unstable_session_model")]
1330impl SetSessionModelResponse {
1331    #[must_use]
1332    pub fn new() -> Self {
1333        Self::default()
1334    }
1335
1336    /// Extension point for implementations
1337    #[must_use]
1338    pub fn meta(mut self, meta: serde_json::Value) -> Self {
1339        self.meta = Some(meta);
1340        self
1341    }
1342}
1343
1344// Capabilities
1345
1346/// Capabilities supported by the agent.
1347///
1348/// Advertised during initialization to inform the client about
1349/// available features and content types.
1350///
1351/// See protocol docs: [Agent Capabilities](https://agentclientprotocol.com/protocol/initialization#agent-capabilities)
1352#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1353#[serde(rename_all = "camelCase")]
1354#[non_exhaustive]
1355pub struct AgentCapabilities {
1356    /// Whether the agent supports `session/load`.
1357    #[serde(default)]
1358    pub load_session: bool,
1359    /// Prompt capabilities supported by the agent.
1360    #[serde(default)]
1361    pub prompt_capabilities: PromptCapabilities,
1362    /// MCP capabilities supported by the agent.
1363    #[serde(default)]
1364    pub mcp_capabilities: McpCapabilities,
1365    #[serde(default)]
1366    pub session_capabilities: SessionCapabilities,
1367    /// Extension point for implementations
1368    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1369    pub meta: Option<serde_json::Value>,
1370}
1371
1372impl AgentCapabilities {
1373    #[must_use]
1374    pub fn new() -> Self {
1375        Self::default()
1376    }
1377
1378    /// Whether the agent supports `session/load`.
1379    #[must_use]
1380    pub fn load_session(mut self, load_session: bool) -> Self {
1381        self.load_session = load_session;
1382        self
1383    }
1384
1385    /// Prompt capabilities supported by the agent.
1386    #[must_use]
1387    pub fn prompt_capabilities(mut self, prompt_capabilities: PromptCapabilities) -> Self {
1388        self.prompt_capabilities = prompt_capabilities;
1389        self
1390    }
1391
1392    /// MCP capabilities supported by the agent.
1393    #[must_use]
1394    pub fn mcp_capabilities(mut self, mcp_capabilities: McpCapabilities) -> Self {
1395        self.mcp_capabilities = mcp_capabilities;
1396        self
1397    }
1398
1399    /// Extension point for implementations
1400    #[must_use]
1401    pub fn meta(mut self, meta: serde_json::Value) -> Self {
1402        self.meta = Some(meta);
1403        self
1404    }
1405}
1406
1407/// Session capabilities supported by the agent.
1408///
1409/// As a baseline, all Agents **MUST** support `session/new`, `session/prompt`, `session/cancel`, and `session/update`.
1410///
1411/// Optionally, they **MAY** support other session methods and notifications by specifying additional capabilities.
1412///
1413/// Note: `session/load` is still handled by the top-level `load_session` capability. This will be unified in future versions of the protocol.
1414///
1415/// See protocol docs: [Session Capabilities](https://agentclientprotocol.com/protocol/initialization#session-capabilities)
1416#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1417#[non_exhaustive]
1418pub struct SessionCapabilities {
1419    /// **UNSTABLE**
1420    ///
1421    /// This capability is not part of the spec yet, and may be removed or changed at any point.
1422    ///
1423    /// Whether the agent supports `session/list`.
1424    #[cfg(feature = "unstable_session_list")]
1425    #[serde(skip_serializing_if = "Option::is_none")]
1426    pub list: Option<SessionListCapabilities>,
1427    /// Extension point for implementations
1428    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1429    pub meta: Option<serde_json::Value>,
1430}
1431
1432impl SessionCapabilities {
1433    #[must_use]
1434    pub fn new() -> Self {
1435        Self::default()
1436    }
1437
1438    #[cfg(feature = "unstable_session_list")]
1439    /// Whether the agent supports `session/list`.
1440    #[must_use]
1441    pub fn list(mut self, list: SessionListCapabilities) -> Self {
1442        self.list = Some(list);
1443        self
1444    }
1445
1446    /// Extension point for implementations
1447    #[must_use]
1448    pub fn meta(mut self, meta: serde_json::Value) -> Self {
1449        self.meta = Some(meta);
1450        self
1451    }
1452}
1453
1454/// Capabilities for the `session/list` method.
1455///
1456/// By supplying `{}` it means that the agent supports listing of sessions.
1457///
1458/// Further capabilities can be added in the future for other means of filtering or searching the list.
1459#[cfg(feature = "unstable_session_list")]
1460#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1461#[non_exhaustive]
1462pub struct SessionListCapabilities {
1463    /// Extension point for implementations
1464    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1465    pub meta: Option<serde_json::Value>,
1466}
1467
1468#[cfg(feature = "unstable_session_list")]
1469impl SessionListCapabilities {
1470    #[must_use]
1471    pub fn new() -> Self {
1472        Self::default()
1473    }
1474    /// Extension point for implementations
1475    #[must_use]
1476    pub fn meta(mut self, meta: serde_json::Value) -> Self {
1477        self.meta = Some(meta);
1478        self
1479    }
1480}
1481
1482/// Prompt capabilities supported by the agent in `session/prompt` requests.
1483///
1484/// Baseline agent functionality requires support for [`ContentBlock::Text`]
1485/// and [`ContentBlock::ResourceLink`] in prompt requests.
1486///
1487/// Other variants must be explicitly opted in to.
1488/// Capabilities for different types of content in prompt requests.
1489///
1490/// Indicates which content types beyond the baseline (text and resource links)
1491/// the agent can process.
1492///
1493/// See protocol docs: [Prompt Capabilities](https://agentclientprotocol.com/protocol/initialization#prompt-capabilities)
1494#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1495#[serde(rename_all = "camelCase")]
1496#[non_exhaustive]
1497pub struct PromptCapabilities {
1498    /// Agent supports [`ContentBlock::Image`].
1499    #[serde(default)]
1500    pub image: bool,
1501    /// Agent supports [`ContentBlock::Audio`].
1502    #[serde(default)]
1503    pub audio: bool,
1504    /// Agent supports embedded context in `session/prompt` requests.
1505    ///
1506    /// When enabled, the Client is allowed to include [`ContentBlock::Resource`]
1507    /// in prompt requests for pieces of context that are referenced in the message.
1508    #[serde(default)]
1509    pub embedded_context: bool,
1510    /// Extension point for implementations
1511    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1512    pub meta: Option<serde_json::Value>,
1513}
1514
1515impl PromptCapabilities {
1516    #[must_use]
1517    pub fn new() -> Self {
1518        Self::default()
1519    }
1520
1521    /// Agent supports [`ContentBlock::Image`].
1522    #[must_use]
1523    pub fn image(mut self, image: bool) -> Self {
1524        self.image = image;
1525        self
1526    }
1527
1528    /// Agent supports [`ContentBlock::Audio`].
1529    #[must_use]
1530    pub fn audio(mut self, audio: bool) -> Self {
1531        self.audio = audio;
1532        self
1533    }
1534
1535    /// Agent supports embedded context in `session/prompt` requests.
1536    ///
1537    /// When enabled, the Client is allowed to include [`ContentBlock::Resource`]
1538    /// in prompt requests for pieces of context that are referenced in the message.
1539    #[must_use]
1540    pub fn embedded_context(mut self, embedded_context: bool) -> Self {
1541        self.embedded_context = embedded_context;
1542        self
1543    }
1544
1545    /// Extension point for implementations
1546    #[must_use]
1547    pub fn meta(mut self, meta: serde_json::Value) -> Self {
1548        self.meta = Some(meta);
1549        self
1550    }
1551}
1552
1553/// MCP capabilities supported by the agent
1554#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1555#[serde(rename_all = "camelCase")]
1556#[non_exhaustive]
1557pub struct McpCapabilities {
1558    /// Agent supports [`McpServer::Http`].
1559    #[serde(default)]
1560    pub http: bool,
1561    /// Agent supports [`McpServer::Sse`].
1562    #[serde(default)]
1563    pub sse: bool,
1564    /// Extension point for implementations
1565    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1566    pub meta: Option<serde_json::Value>,
1567}
1568
1569impl McpCapabilities {
1570    #[must_use]
1571    pub fn new() -> Self {
1572        Self::default()
1573    }
1574
1575    /// Agent supports [`McpServer::Http`].
1576    #[must_use]
1577    pub fn http(mut self, http: bool) -> Self {
1578        self.http = http;
1579        self
1580    }
1581
1582    /// Agent supports [`McpServer::Sse`].
1583    #[must_use]
1584    pub fn sse(mut self, sse: bool) -> Self {
1585        self.sse = sse;
1586        self
1587    }
1588
1589    /// Extension point for implementations
1590    #[must_use]
1591    pub fn meta(mut self, meta: serde_json::Value) -> Self {
1592        self.meta = Some(meta);
1593        self
1594    }
1595}
1596
1597// Method schema
1598
1599/// Names of all methods that agents handle.
1600///
1601/// Provides a centralized definition of method names used in the protocol.
1602#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1603#[non_exhaustive]
1604pub struct AgentMethodNames {
1605    /// Method for initializing the connection.
1606    pub initialize: &'static str,
1607    /// Method for authenticating with the agent.
1608    pub authenticate: &'static str,
1609    /// Method for creating a new session.
1610    pub session_new: &'static str,
1611    /// Method for loading an existing session.
1612    pub session_load: &'static str,
1613    /// Method for setting the mode for a session.
1614    pub session_set_mode: &'static str,
1615    /// Method for sending a prompt to the agent.
1616    pub session_prompt: &'static str,
1617    /// Notification for cancelling operations.
1618    pub session_cancel: &'static str,
1619    /// Method for selecting a model for a given session.
1620    #[cfg(feature = "unstable_session_model")]
1621    pub session_set_model: &'static str,
1622    /// Method for listing existing sessions.
1623    #[cfg(feature = "unstable_session_list")]
1624    pub session_list: &'static str,
1625}
1626
1627/// Constant containing all agent method names.
1628pub const AGENT_METHOD_NAMES: AgentMethodNames = AgentMethodNames {
1629    initialize: INITIALIZE_METHOD_NAME,
1630    authenticate: AUTHENTICATE_METHOD_NAME,
1631    session_new: SESSION_NEW_METHOD_NAME,
1632    session_load: SESSION_LOAD_METHOD_NAME,
1633    session_set_mode: SESSION_SET_MODE_METHOD_NAME,
1634    session_prompt: SESSION_PROMPT_METHOD_NAME,
1635    session_cancel: SESSION_CANCEL_METHOD_NAME,
1636    #[cfg(feature = "unstable_session_model")]
1637    session_set_model: SESSION_SET_MODEL_METHOD_NAME,
1638    #[cfg(feature = "unstable_session_list")]
1639    session_list: SESSION_LIST_METHOD_NAME,
1640};
1641
1642/// Method name for the initialize request.
1643pub(crate) const INITIALIZE_METHOD_NAME: &str = "initialize";
1644/// Method name for the authenticate request.
1645pub(crate) const AUTHENTICATE_METHOD_NAME: &str = "authenticate";
1646/// Method name for creating a new session.
1647pub(crate) const SESSION_NEW_METHOD_NAME: &str = "session/new";
1648/// Method name for loading an existing session.
1649pub(crate) const SESSION_LOAD_METHOD_NAME: &str = "session/load";
1650/// Method name for setting the mode for a session.
1651pub(crate) const SESSION_SET_MODE_METHOD_NAME: &str = "session/set_mode";
1652/// Method name for sending a prompt.
1653pub(crate) const SESSION_PROMPT_METHOD_NAME: &str = "session/prompt";
1654/// Method name for the cancel notification.
1655pub(crate) const SESSION_CANCEL_METHOD_NAME: &str = "session/cancel";
1656/// Method name for selecting a model for a given session.
1657#[cfg(feature = "unstable_session_model")]
1658pub(crate) const SESSION_SET_MODEL_METHOD_NAME: &str = "session/set_model";
1659/// Method name for listing existing sessions.
1660#[cfg(feature = "unstable_session_list")]
1661pub(crate) const SESSION_LIST_METHOD_NAME: &str = "session/list";
1662
1663/// All possible requests that a client can send to an agent.
1664///
1665/// This enum is used internally for routing RPC requests. You typically won't need
1666/// to use this directly - instead, use the methods on the [`Agent`] trait.
1667///
1668/// This enum encompasses all method calls from client to agent.
1669#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
1670#[serde(untagged)]
1671#[schemars(extend("x-docs-ignore" = true))]
1672#[non_exhaustive]
1673pub enum ClientRequest {
1674    /// Establishes the connection with a client and negotiates protocol capabilities.
1675    ///
1676    /// This method is called once at the beginning of the connection to:
1677    /// - Negotiate the protocol version to use
1678    /// - Exchange capability information between client and agent
1679    /// - Determine available authentication methods
1680    ///
1681    /// The agent should respond with its supported protocol version and capabilities.
1682    ///
1683    /// See protocol docs: [Initialization](https://agentclientprotocol.com/protocol/initialization)
1684    InitializeRequest(InitializeRequest),
1685    /// Authenticates the client using the specified authentication method.
1686    ///
1687    /// Called when the agent requires authentication before allowing session creation.
1688    /// The client provides the authentication method ID that was advertised during initialization.
1689    ///
1690    /// After successful authentication, the client can proceed to create sessions with
1691    /// `new_session` without receiving an `auth_required` error.
1692    ///
1693    /// See protocol docs: [Initialization](https://agentclientprotocol.com/protocol/initialization)
1694    AuthenticateRequest(AuthenticateRequest),
1695    /// Creates a new conversation session with the agent.
1696    ///
1697    /// Sessions represent independent conversation contexts with their own history and state.
1698    ///
1699    /// The agent should:
1700    /// - Create a new session context
1701    /// - Connect to any specified MCP servers
1702    /// - Return a unique session ID for future requests
1703    ///
1704    /// May return an `auth_required` error if the agent requires authentication.
1705    ///
1706    /// See protocol docs: [Session Setup](https://agentclientprotocol.com/protocol/session-setup)
1707    NewSessionRequest(NewSessionRequest),
1708    /// Loads an existing session to resume a previous conversation.
1709    ///
1710    /// This method is only available if the agent advertises the `loadSession` capability.
1711    ///
1712    /// The agent should:
1713    /// - Restore the session context and conversation history
1714    /// - Connect to the specified MCP servers
1715    /// - Stream the entire conversation history back to the client via notifications
1716    ///
1717    /// See protocol docs: [Loading Sessions](https://agentclientprotocol.com/protocol/session-setup#loading-sessions)
1718    LoadSessionRequest(LoadSessionRequest),
1719    #[cfg(feature = "unstable_session_list")]
1720    /// **UNSTABLE**
1721    ///
1722    /// This capability is not part of the spec yet, and may be removed or changed at any point.
1723    ///
1724    /// Lists existing sessions known to the agent.
1725    ///
1726    /// This method is only available if the agent advertises the `listSessions` capability.
1727    ///
1728    /// The agent should return metadata about sessions with optional filtering and pagination support.
1729    ListSessionsRequest(ListSessionsRequest),
1730    /// Sets the current mode for a session.
1731    ///
1732    /// Allows switching between different agent modes (e.g., "ask", "architect", "code")
1733    /// that affect system prompts, tool availability, and permission behaviors.
1734    ///
1735    /// The mode must be one of the modes advertised in `availableModes` during session
1736    /// creation or loading. Agents may also change modes autonomously and notify the
1737    /// client via `current_mode_update` notifications.
1738    ///
1739    /// This method can be called at any time during a session, whether the Agent is
1740    /// idle or actively generating a response.
1741    ///
1742    /// See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
1743    SetSessionModeRequest(SetSessionModeRequest),
1744    /// Processes a user prompt within a session.
1745    ///
1746    /// This method handles the whole lifecycle of a prompt:
1747    /// - Receives user messages with optional context (files, images, etc.)
1748    /// - Processes the prompt using language models
1749    /// - Reports language model content and tool calls to the Clients
1750    /// - Requests permission to run tools
1751    /// - Executes any requested tool calls
1752    /// - Returns when the turn is complete with a stop reason
1753    ///
1754    /// See protocol docs: [Prompt Turn](https://agentclientprotocol.com/protocol/prompt-turn)
1755    PromptRequest(PromptRequest),
1756    #[cfg(feature = "unstable_session_model")]
1757    /// **UNSTABLE**
1758    ///
1759    /// This capability is not part of the spec yet, and may be removed or changed at any point.
1760    ///
1761    /// Select a model for a given session.
1762    SetSessionModelRequest(SetSessionModelRequest),
1763    /// Handles extension method requests from the client.
1764    ///
1765    /// Extension methods provide a way to add custom functionality while maintaining
1766    /// protocol compatibility.
1767    ///
1768    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1769    ExtMethodRequest(ExtRequest),
1770}
1771
1772/// All possible responses that an agent can send to a client.
1773///
1774/// This enum is used internally for routing RPC responses. You typically won't need
1775/// to use this directly - the responses are handled automatically by the connection.
1776///
1777/// These are responses to the corresponding `ClientRequest` variants.
1778#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
1779#[serde(untagged)]
1780#[schemars(extend("x-docs-ignore" = true))]
1781#[non_exhaustive]
1782pub enum AgentResponse {
1783    InitializeResponse(InitializeResponse),
1784    AuthenticateResponse(#[serde(default)] AuthenticateResponse),
1785    NewSessionResponse(NewSessionResponse),
1786    LoadSessionResponse(#[serde(default)] LoadSessionResponse),
1787    #[cfg(feature = "unstable_session_list")]
1788    ListSessionsResponse(ListSessionsResponse),
1789    SetSessionModeResponse(#[serde(default)] SetSessionModeResponse),
1790    PromptResponse(PromptResponse),
1791    #[cfg(feature = "unstable_session_model")]
1792    SetSessionModelResponse(SetSessionModelResponse),
1793    ExtMethodResponse(#[schemars(with = "serde_json::Value")] Arc<RawValue>),
1794}
1795
1796/// All possible notifications that a client can send to an agent.
1797///
1798/// This enum is used internally for routing RPC notifications. You typically won't need
1799/// to use this directly - use the notification methods on the [`Agent`] trait instead.
1800///
1801/// Notifications do not expect a response.
1802#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
1803#[serde(untagged)]
1804#[schemars(extend("x-docs-ignore" = true))]
1805#[non_exhaustive]
1806pub enum ClientNotification {
1807    /// Cancels ongoing operations for a session.
1808    ///
1809    /// This is a notification sent by the client to cancel an ongoing prompt turn.
1810    ///
1811    /// Upon receiving this notification, the Agent SHOULD:
1812    /// - Stop all language model requests as soon as possible
1813    /// - Abort all tool call invocations in progress
1814    /// - Send any pending `session/update` notifications
1815    /// - Respond to the original `session/prompt` request with `StopReason::Cancelled`
1816    ///
1817    /// See protocol docs: [Cancellation](https://agentclientprotocol.com/protocol/prompt-turn#cancellation)
1818    CancelNotification(CancelNotification),
1819    /// Handles extension notifications from the client.
1820    ///
1821    /// Extension notifications provide a way to send one-way messages for custom functionality
1822    /// while maintaining protocol compatibility.
1823    ///
1824    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1825    ExtNotification(ExtNotification),
1826}
1827
1828/// Notification to cancel ongoing operations for a session.
1829///
1830/// See protocol docs: [Cancellation](https://agentclientprotocol.com/protocol/prompt-turn#cancellation)
1831#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1832#[schemars(extend("x-side" = "agent", "x-method" = SESSION_CANCEL_METHOD_NAME))]
1833#[serde(rename_all = "camelCase")]
1834#[non_exhaustive]
1835pub struct CancelNotification {
1836    /// The ID of the session to cancel operations for.
1837    pub session_id: SessionId,
1838    /// Extension point for implementations
1839    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1840    pub meta: Option<serde_json::Value>,
1841}
1842
1843impl CancelNotification {
1844    #[must_use]
1845    pub fn new(session_id: SessionId) -> Self {
1846        Self {
1847            session_id,
1848            meta: None,
1849        }
1850    }
1851
1852    /// Extension point for implementations
1853    #[must_use]
1854    pub fn meta(mut self, meta: serde_json::Value) -> Self {
1855        self.meta = Some(meta);
1856        self
1857    }
1858}
1859
1860#[cfg(test)]
1861mod test_serialization {
1862    use super::*;
1863    use serde_json::json;
1864
1865    #[test]
1866    fn test_mcp_server_stdio_serialization() {
1867        let server = McpServer::Stdio(
1868            McpServerStdio::new("test-server", "/usr/bin/server")
1869                .args(vec!["--port".to_string(), "3000".to_string()])
1870                .env(vec![EnvVariable::new("API_KEY", "secret123")]),
1871        );
1872
1873        let json = serde_json::to_value(&server).unwrap();
1874        assert_eq!(
1875            json,
1876            json!({
1877                "name": "test-server",
1878                "command": "/usr/bin/server",
1879                "args": ["--port", "3000"],
1880                "env": [
1881                    {
1882                        "name": "API_KEY",
1883                        "value": "secret123"
1884                    }
1885                ]
1886            })
1887        );
1888
1889        let deserialized: McpServer = serde_json::from_value(json).unwrap();
1890        match deserialized {
1891            McpServer::Stdio(McpServerStdio {
1892                name,
1893                command,
1894                args,
1895                env,
1896                meta: _,
1897            }) => {
1898                assert_eq!(name, "test-server");
1899                assert_eq!(command, PathBuf::from("/usr/bin/server"));
1900                assert_eq!(args, vec!["--port", "3000"]);
1901                assert_eq!(env.len(), 1);
1902                assert_eq!(env[0].name, "API_KEY");
1903                assert_eq!(env[0].value, "secret123");
1904            }
1905            _ => panic!("Expected Stdio variant"),
1906        }
1907    }
1908
1909    #[test]
1910    fn test_mcp_server_http_serialization() {
1911        let server = McpServer::Http(
1912            McpServerHttp::new("http-server", "https://api.example.com").headers(vec![
1913                HttpHeader::new("Authorization", "Bearer token123"),
1914                HttpHeader::new("Content-Type", "application/json"),
1915            ]),
1916        );
1917
1918        let json = serde_json::to_value(&server).unwrap();
1919        assert_eq!(
1920            json,
1921            json!({
1922                "type": "http",
1923                "name": "http-server",
1924                "url": "https://api.example.com",
1925                "headers": [
1926                    {
1927                        "name": "Authorization",
1928                        "value": "Bearer token123"
1929                    },
1930                    {
1931                        "name": "Content-Type",
1932                        "value": "application/json"
1933                    }
1934                ]
1935            })
1936        );
1937
1938        let deserialized: McpServer = serde_json::from_value(json).unwrap();
1939        match deserialized {
1940            McpServer::Http(McpServerHttp {
1941                name,
1942                url,
1943                headers,
1944                meta: _,
1945            }) => {
1946                assert_eq!(name, "http-server");
1947                assert_eq!(url, "https://api.example.com");
1948                assert_eq!(headers.len(), 2);
1949                assert_eq!(headers[0].name, "Authorization");
1950                assert_eq!(headers[0].value, "Bearer token123");
1951                assert_eq!(headers[1].name, "Content-Type");
1952                assert_eq!(headers[1].value, "application/json");
1953            }
1954            _ => panic!("Expected Http variant"),
1955        }
1956    }
1957
1958    #[test]
1959    fn test_mcp_server_sse_serialization() {
1960        let server = McpServer::Sse(
1961            McpServerSse::new("sse-server", "https://sse.example.com/events")
1962                .headers(vec![HttpHeader::new("X-API-Key", "apikey456")]),
1963        );
1964
1965        let json = serde_json::to_value(&server).unwrap();
1966        assert_eq!(
1967            json,
1968            json!({
1969                "type": "sse",
1970                "name": "sse-server",
1971                "url": "https://sse.example.com/events",
1972                "headers": [
1973                    {
1974                        "name": "X-API-Key",
1975                        "value": "apikey456"
1976                    }
1977                ]
1978            })
1979        );
1980
1981        let deserialized: McpServer = serde_json::from_value(json).unwrap();
1982        match deserialized {
1983            McpServer::Sse(McpServerSse {
1984                name,
1985                url,
1986                headers,
1987                meta: _,
1988            }) => {
1989                assert_eq!(name, "sse-server");
1990                assert_eq!(url, "https://sse.example.com/events");
1991                assert_eq!(headers.len(), 1);
1992                assert_eq!(headers[0].name, "X-API-Key");
1993                assert_eq!(headers[0].value, "apikey456");
1994            }
1995            _ => panic!("Expected Sse variant"),
1996        }
1997    }
1998}