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