agent_client_protocol_schema/v1/client.rs
1//! Methods and notifications the client handles/receives.
2//!
3//! This module defines the Client trait and all associated types for implementing
4//! a client that interacts with AI coding agents via 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_with::{DefaultOnError, VecSkipError, serde_as, skip_serializing_none};
12
13#[cfg(feature = "unstable_elicitation")]
14use super::{
15 CompleteElicitationNotification, CreateElicitationRequest, CreateElicitationResponse,
16 ElicitationCapabilities,
17};
18use crate::{IntoMaybeUndefined, IntoOption, MaybeUndefined, SkipListener};
19
20use super::{
21 ContentBlock, EnvVariable, ExtNotification, ExtRequest, ExtResponse, Meta, Plan,
22 SessionConfigOption, SessionId, SessionModeId, ToolCall, ToolCallUpdate,
23};
24#[cfg(feature = "unstable_plan_operations")]
25use super::{PlanCapabilities, PlanRemoved, PlanUpdate};
26
27#[cfg(feature = "unstable_mcp_over_acp")]
28use super::mcp::{
29 ConnectMcpRequest, ConnectMcpResponse, DisconnectMcpRequest, DisconnectMcpResponse,
30 MCP_CONNECT_METHOD_NAME, MCP_DISCONNECT_METHOD_NAME, MCP_MESSAGE_METHOD_NAME,
31 MessageMcpNotification, MessageMcpRequest, MessageMcpResponse,
32};
33
34#[cfg(feature = "unstable_nes")]
35use super::{ClientNesCapabilities, PositionEncodingKind};
36
37// Session updates
38
39/// Notification containing a session update from the agent.
40///
41/// Used to stream real-time progress and results during prompt processing.
42///
43/// See protocol docs: [Agent Reports Output](https://agentclientprotocol.com/protocol/prompt-turn#3-agent-reports-output)
44#[serde_as]
45#[skip_serializing_none]
46#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
47#[schemars(extend("x-side" = "client", "x-method" = SESSION_UPDATE_NOTIFICATION))]
48#[serde(rename_all = "camelCase")]
49#[non_exhaustive]
50pub struct SessionNotification {
51 /// The ID of the session this update pertains to.
52 pub session_id: SessionId,
53 /// The actual update content.
54 pub update: SessionUpdate,
55 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
56 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
57 /// these keys.
58 ///
59 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
60 #[serde_as(deserialize_as = "DefaultOnError")]
61 #[schemars(extend("x-deserialize-default-on-error" = true))]
62 #[serde(default)]
63 #[serde(rename = "_meta")]
64 pub meta: Option<Meta>,
65}
66
67impl SessionNotification {
68 /// Builds [`SessionNotification`] with the required notification fields set; optional fields start unset or empty.
69 #[must_use]
70 pub fn new(session_id: impl Into<SessionId>, update: SessionUpdate) -> Self {
71 Self {
72 session_id: session_id.into(),
73 update,
74 meta: None,
75 }
76 }
77
78 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
79 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
80 /// these keys.
81 ///
82 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
83 #[must_use]
84 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
85 self.meta = meta.into_option();
86 self
87 }
88}
89
90/// Different types of updates that can be sent during session processing.
91///
92/// These updates provide real-time feedback about the agent's progress.
93///
94/// See protocol docs: [Agent Reports Output](https://agentclientprotocol.com/protocol/prompt-turn#3-agent-reports-output)
95#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
96#[serde(tag = "sessionUpdate", rename_all = "snake_case")]
97#[schemars(extend("discriminator" = {"propertyName": "sessionUpdate"}))]
98#[non_exhaustive]
99pub enum SessionUpdate {
100 /// A chunk of the user's message being streamed.
101 UserMessageChunk(ContentChunk),
102 /// A chunk of the agent's response being streamed.
103 AgentMessageChunk(ContentChunk),
104 /// A chunk of the agent's internal reasoning being streamed.
105 AgentThoughtChunk(ContentChunk),
106 /// Notification that a new tool call has been initiated.
107 ToolCall(ToolCall),
108 /// Update on the status or results of a tool call.
109 ToolCallUpdate(ToolCallUpdate),
110 /// The agent's execution plan for complex tasks.
111 /// See protocol docs: [Agent Plan](https://agentclientprotocol.com/protocol/agent-plan)
112 Plan(Plan),
113 /// **UNSTABLE**
114 ///
115 /// This capability is not part of the spec yet, and may be removed or changed at any point.
116 ///
117 /// A content update for a plan identified by ID.
118 #[cfg(feature = "unstable_plan_operations")]
119 PlanUpdate(PlanUpdate),
120 /// **UNSTABLE**
121 ///
122 /// This capability is not part of the spec yet, and may be removed or changed at any point.
123 ///
124 /// Removal notice for a plan identified by ID.
125 #[cfg(feature = "unstable_plan_operations")]
126 PlanRemoved(PlanRemoved),
127 /// Available commands are ready or have changed
128 AvailableCommandsUpdate(AvailableCommandsUpdate),
129 /// The current mode of the session has changed
130 ///
131 /// See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
132 CurrentModeUpdate(CurrentModeUpdate),
133 /// Session configuration options have been updated.
134 ConfigOptionUpdate(ConfigOptionUpdate),
135 /// Session metadata has been updated (title, timestamps, custom metadata)
136 SessionInfoUpdate(SessionInfoUpdate),
137 /// Context window and cost update for the session.
138 UsageUpdate(UsageUpdate),
139}
140
141/// The current mode of the session has changed
142///
143/// See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
144#[serde_as]
145#[skip_serializing_none]
146#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
147#[serde(rename_all = "camelCase")]
148#[non_exhaustive]
149pub struct CurrentModeUpdate {
150 /// The ID of the current mode
151 pub current_mode_id: SessionModeId,
152 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
153 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
154 /// these keys.
155 ///
156 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
157 #[serde_as(deserialize_as = "DefaultOnError")]
158 #[schemars(extend("x-deserialize-default-on-error" = true))]
159 #[serde(default)]
160 #[serde(rename = "_meta")]
161 pub meta: Option<Meta>,
162}
163
164impl CurrentModeUpdate {
165 /// Builds [`CurrentModeUpdate`] with the required fields set; optional fields start unset or empty.
166 #[must_use]
167 pub fn new(current_mode_id: impl Into<SessionModeId>) -> Self {
168 Self {
169 current_mode_id: current_mode_id.into(),
170 meta: None,
171 }
172 }
173
174 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
175 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
176 /// these keys.
177 ///
178 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
179 #[must_use]
180 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
181 self.meta = meta.into_option();
182 self
183 }
184}
185
186/// Session configuration options have been updated.
187#[serde_as]
188#[skip_serializing_none]
189#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
190#[serde(rename_all = "camelCase")]
191#[non_exhaustive]
192pub struct ConfigOptionUpdate {
193 /// The full set of configuration options and their current values.
194 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
195 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
196 pub config_options: Vec<SessionConfigOption>,
197 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
198 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
199 /// these keys.
200 ///
201 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
202 #[serde_as(deserialize_as = "DefaultOnError")]
203 #[schemars(extend("x-deserialize-default-on-error" = true))]
204 #[serde(default)]
205 #[serde(rename = "_meta")]
206 pub meta: Option<Meta>,
207}
208
209impl ConfigOptionUpdate {
210 /// Builds [`ConfigOptionUpdate`] with the required fields set; optional fields start unset or empty.
211 #[must_use]
212 pub fn new(config_options: Vec<SessionConfigOption>) -> Self {
213 Self {
214 config_options,
215 meta: None,
216 }
217 }
218
219 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
220 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
221 /// these keys.
222 ///
223 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
224 #[must_use]
225 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
226 self.meta = meta.into_option();
227 self
228 }
229}
230
231/// Update to session metadata. All fields are optional to support partial updates.
232///
233/// Agents send this notification to update session information like title or custom metadata.
234/// This allows clients to display dynamic session names and track session state changes.
235#[serde_as]
236#[skip_serializing_none]
237#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
238#[serde(rename_all = "camelCase")]
239#[non_exhaustive]
240pub struct SessionInfoUpdate {
241 /// Human-readable title for the session. Set to null to clear.
242 #[serde_as(deserialize_as = "DefaultOnError")]
243 #[schemars(extend("x-deserialize-default-on-error" = true))]
244 #[serde(default, skip_serializing_if = "MaybeUndefined::is_undefined")]
245 pub title: MaybeUndefined<String>,
246 /// ISO 8601 timestamp of last activity. Set to null to clear.
247 #[serde_as(deserialize_as = "DefaultOnError")]
248 #[schemars(extend("x-deserialize-default-on-error" = true))]
249 #[serde(default, skip_serializing_if = "MaybeUndefined::is_undefined")]
250 pub updated_at: MaybeUndefined<String>,
251 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
252 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
253 /// these keys.
254 ///
255 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
256 #[serde_as(deserialize_as = "DefaultOnError")]
257 #[schemars(extend("x-deserialize-default-on-error" = true))]
258 #[serde(default)]
259 #[serde(rename = "_meta")]
260 pub meta: Option<Meta>,
261}
262
263impl SessionInfoUpdate {
264 /// Builds [`SessionInfoUpdate`] with the required fields set; optional fields start unset or empty.
265 #[must_use]
266 pub fn new() -> Self {
267 Self::default()
268 }
269
270 /// Human-readable title for the session. Set to null to clear.
271 #[must_use]
272 pub fn title(mut self, title: impl IntoMaybeUndefined<String>) -> Self {
273 self.title = title.into_maybe_undefined();
274 self
275 }
276
277 /// ISO 8601 timestamp of last activity. Set to null to clear.
278 #[must_use]
279 pub fn updated_at(mut self, updated_at: impl IntoMaybeUndefined<String>) -> Self {
280 self.updated_at = updated_at.into_maybe_undefined();
281 self
282 }
283
284 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
285 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
286 /// these keys.
287 ///
288 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
289 #[must_use]
290 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
291 self.meta = meta.into_option();
292 self
293 }
294}
295
296/// Context window and cost update for a session.
297#[serde_as]
298#[skip_serializing_none]
299#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
300#[serde(rename_all = "camelCase")]
301#[non_exhaustive]
302pub struct UsageUpdate {
303 /// Tokens currently in context.
304 pub used: u64,
305 /// Total context window size in tokens.
306 pub size: u64,
307 /// Cumulative session cost (optional).
308 #[serde_as(deserialize_as = "DefaultOnError")]
309 #[schemars(extend("x-deserialize-default-on-error" = true))]
310 #[serde(default)]
311 pub cost: Option<Cost>,
312 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
313 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
314 /// these keys.
315 ///
316 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
317 #[serde_as(deserialize_as = "DefaultOnError")]
318 #[schemars(extend("x-deserialize-default-on-error" = true))]
319 #[serde(default)]
320 #[serde(rename = "_meta")]
321 pub meta: Option<Meta>,
322}
323
324impl UsageUpdate {
325 /// Builds [`UsageUpdate`] with the required fields set; optional fields start unset or empty.
326 #[must_use]
327 pub fn new(used: u64, size: u64) -> Self {
328 Self {
329 used,
330 size,
331 cost: None,
332 meta: None,
333 }
334 }
335
336 /// Cumulative session cost (optional).
337 #[must_use]
338 pub fn cost(mut self, cost: impl IntoOption<Cost>) -> Self {
339 self.cost = cost.into_option();
340 self
341 }
342
343 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
344 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
345 /// these keys.
346 ///
347 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
348 #[must_use]
349 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
350 self.meta = meta.into_option();
351 self
352 }
353}
354
355/// Cost information for a session.
356#[serde_as]
357#[skip_serializing_none]
358#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
359#[serde(rename_all = "camelCase")]
360#[non_exhaustive]
361pub struct Cost {
362 /// Total cumulative cost for session.
363 pub amount: f64,
364 /// ISO 4217 currency code (e.g., "USD", "EUR").
365 pub currency: String,
366 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
367 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
368 /// these keys.
369 ///
370 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
371 #[serde_as(deserialize_as = "DefaultOnError")]
372 #[schemars(extend("x-deserialize-default-on-error" = true))]
373 #[serde(default)]
374 #[serde(rename = "_meta")]
375 pub meta: Option<Meta>,
376}
377
378impl Cost {
379 /// Builds [`Cost`] with the required fields set; optional fields start unset or empty.
380 #[must_use]
381 pub fn new(amount: f64, currency: impl Into<String>) -> Self {
382 Self {
383 amount,
384 currency: currency.into(),
385 meta: None,
386 }
387 }
388
389 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
390 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
391 /// these keys.
392 ///
393 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
394 #[must_use]
395 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
396 self.meta = meta.into_option();
397 self
398 }
399}
400
401/// A streamed item of content
402#[serde_as]
403#[skip_serializing_none]
404#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
405#[serde(rename_all = "camelCase")]
406#[non_exhaustive]
407pub struct ContentChunk {
408 /// A single item of content
409 pub content: ContentBlock,
410 /// A unique identifier for the message this chunk belongs to.
411 ///
412 /// All chunks belonging to the same message share the same `messageId`.
413 /// A change in `messageId` indicates a new message has started.
414 #[serde_as(deserialize_as = "DefaultOnError")]
415 #[schemars(extend("x-deserialize-default-on-error" = true))]
416 #[serde(default)]
417 pub message_id: Option<MessageId>,
418 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
419 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
420 /// these keys.
421 ///
422 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
423 #[serde_as(deserialize_as = "DefaultOnError")]
424 #[schemars(extend("x-deserialize-default-on-error" = true))]
425 #[serde(default)]
426 #[serde(rename = "_meta")]
427 pub meta: Option<Meta>,
428}
429
430impl ContentChunk {
431 /// Builds [`ContentChunk`] with the required fields set; optional fields start unset or empty.
432 #[must_use]
433 pub fn new(content: ContentBlock) -> Self {
434 Self {
435 content,
436 message_id: None,
437 meta: None,
438 }
439 }
440
441 /// A unique identifier for the message this chunk belongs to.
442 ///
443 /// All chunks belonging to the same message share the same `messageId`.
444 /// A change in `messageId` indicates a new message has started.
445 #[must_use]
446 pub fn message_id(mut self, message_id: impl IntoOption<MessageId>) -> Self {
447 self.message_id = message_id.into_option();
448 self
449 }
450
451 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
452 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
453 /// these keys.
454 ///
455 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
456 #[must_use]
457 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
458 self.meta = meta.into_option();
459 self
460 }
461}
462
463/// Unique identifier for a message within a session.
464#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, Display, From)]
465#[serde(transparent)]
466#[from(Arc<str>, String, &'static str)]
467#[non_exhaustive]
468pub struct MessageId(pub Arc<str>);
469
470impl MessageId {
471 /// Wraps a protocol string as a typed [`MessageId`].
472 #[must_use]
473 pub fn new(id: impl Into<Arc<str>>) -> Self {
474 Self(id.into())
475 }
476}
477
478impl IntoOption<MessageId> for &str {
479 fn into_option(self) -> Option<MessageId> {
480 Some(MessageId::new(self))
481 }
482}
483
484/// Available commands are ready or have changed
485#[serde_as]
486#[skip_serializing_none]
487#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
488#[serde(rename_all = "camelCase")]
489#[non_exhaustive]
490pub struct AvailableCommandsUpdate {
491 /// Commands the agent can execute
492 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
493 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
494 pub available_commands: Vec<AvailableCommand>,
495 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
496 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
497 /// these keys.
498 ///
499 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
500 #[serde_as(deserialize_as = "DefaultOnError")]
501 #[schemars(extend("x-deserialize-default-on-error" = true))]
502 #[serde(default)]
503 #[serde(rename = "_meta")]
504 pub meta: Option<Meta>,
505}
506
507impl AvailableCommandsUpdate {
508 /// Builds [`AvailableCommandsUpdate`] with the required fields set; optional fields start unset or empty.
509 #[must_use]
510 pub fn new(available_commands: Vec<AvailableCommand>) -> Self {
511 Self {
512 available_commands,
513 meta: None,
514 }
515 }
516
517 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
518 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
519 /// these keys.
520 ///
521 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
522 #[must_use]
523 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
524 self.meta = meta.into_option();
525 self
526 }
527}
528
529/// Information about a command.
530#[serde_as]
531#[skip_serializing_none]
532#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
533#[serde(rename_all = "camelCase")]
534#[non_exhaustive]
535pub struct AvailableCommand {
536 /// Command name (e.g., `create_plan`, `research_codebase`).
537 pub name: String,
538 /// Human-readable description of what the command does.
539 pub description: String,
540 /// Input for the command if required
541 #[serde_as(deserialize_as = "DefaultOnError")]
542 #[schemars(extend("x-deserialize-default-on-error" = true))]
543 #[serde(default)]
544 pub input: Option<AvailableCommandInput>,
545 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
546 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
547 /// these keys.
548 ///
549 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
550 #[serde_as(deserialize_as = "DefaultOnError")]
551 #[schemars(extend("x-deserialize-default-on-error" = true))]
552 #[serde(default)]
553 #[serde(rename = "_meta")]
554 pub meta: Option<Meta>,
555}
556
557impl AvailableCommand {
558 /// Builds [`AvailableCommand`] with the required fields set; optional fields start unset or empty.
559 #[must_use]
560 pub fn new(name: impl Into<String>, description: impl Into<String>) -> Self {
561 Self {
562 name: name.into(),
563 description: description.into(),
564 input: None,
565 meta: None,
566 }
567 }
568
569 /// Input for the command if required
570 #[must_use]
571 pub fn input(mut self, input: impl IntoOption<AvailableCommandInput>) -> Self {
572 self.input = input.into_option();
573 self
574 }
575
576 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
577 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
578 /// these keys.
579 ///
580 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
581 #[must_use]
582 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
583 self.meta = meta.into_option();
584 self
585 }
586}
587
588/// The input specification for a command.
589#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
590#[serde(untagged, rename_all = "camelCase")]
591#[non_exhaustive]
592pub enum AvailableCommandInput {
593 /// All text that was typed after the command name is provided as input.
594 Unstructured(UnstructuredCommandInput),
595}
596
597/// All text that was typed after the command name is provided as input.
598#[serde_as]
599#[skip_serializing_none]
600#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
601#[serde(rename_all = "camelCase")]
602#[non_exhaustive]
603pub struct UnstructuredCommandInput {
604 /// A hint to display when the input hasn't been provided yet
605 pub hint: String,
606 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
607 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
608 /// these keys.
609 ///
610 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
611 #[serde_as(deserialize_as = "DefaultOnError")]
612 #[schemars(extend("x-deserialize-default-on-error" = true))]
613 #[serde(default)]
614 #[serde(rename = "_meta")]
615 pub meta: Option<Meta>,
616}
617
618impl UnstructuredCommandInput {
619 /// Builds [`UnstructuredCommandInput`] with the required fields set; optional fields start unset or empty.
620 #[must_use]
621 pub fn new(hint: impl Into<String>) -> Self {
622 Self {
623 hint: hint.into(),
624 meta: None,
625 }
626 }
627
628 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
629 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
630 /// these keys.
631 ///
632 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
633 #[must_use]
634 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
635 self.meta = meta.into_option();
636 self
637 }
638}
639
640// Permission
641
642/// Request for user permission to execute a tool call.
643///
644/// Sent when the agent needs authorization before performing a sensitive operation.
645///
646/// See protocol docs: [Requesting Permission](https://agentclientprotocol.com/protocol/tool-calls#requesting-permission)
647#[serde_as]
648#[skip_serializing_none]
649#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
650#[schemars(extend("x-side" = "client", "x-method" = SESSION_REQUEST_PERMISSION_METHOD_NAME))]
651#[serde(rename_all = "camelCase")]
652#[non_exhaustive]
653pub struct RequestPermissionRequest {
654 /// The session ID for this request.
655 pub session_id: SessionId,
656 /// Details about the tool call requiring permission.
657 pub tool_call: ToolCallUpdate,
658 /// Available permission options for the user to choose from.
659 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
660 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
661 pub options: Vec<PermissionOption>,
662 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
663 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
664 /// these keys.
665 ///
666 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
667 #[serde_as(deserialize_as = "DefaultOnError")]
668 #[schemars(extend("x-deserialize-default-on-error" = true))]
669 #[serde(default)]
670 #[serde(rename = "_meta")]
671 pub meta: Option<Meta>,
672}
673
674impl RequestPermissionRequest {
675 /// Builds [`RequestPermissionRequest`] with the required request fields set; optional fields start unset or empty.
676 #[must_use]
677 pub fn new(
678 session_id: impl Into<SessionId>,
679 tool_call: ToolCallUpdate,
680 options: Vec<PermissionOption>,
681 ) -> Self {
682 Self {
683 session_id: session_id.into(),
684 tool_call,
685 options,
686 meta: None,
687 }
688 }
689
690 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
691 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
692 /// these keys.
693 ///
694 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
695 #[must_use]
696 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
697 self.meta = meta.into_option();
698 self
699 }
700}
701
702/// An option presented to the user when requesting permission.
703#[serde_as]
704#[skip_serializing_none]
705#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
706#[serde(rename_all = "camelCase")]
707#[non_exhaustive]
708pub struct PermissionOption {
709 /// Unique identifier for this permission option.
710 pub option_id: PermissionOptionId,
711 /// Human-readable label to display to the user.
712 pub name: String,
713 /// Hint about the nature of this permission option.
714 pub kind: PermissionOptionKind,
715 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
716 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
717 /// these keys.
718 ///
719 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
720 #[serde_as(deserialize_as = "DefaultOnError")]
721 #[schemars(extend("x-deserialize-default-on-error" = true))]
722 #[serde(default)]
723 #[serde(rename = "_meta")]
724 pub meta: Option<Meta>,
725}
726
727impl PermissionOption {
728 /// Builds [`PermissionOption`] with the required fields set; optional fields start unset or empty.
729 #[must_use]
730 pub fn new(
731 option_id: impl Into<PermissionOptionId>,
732 name: impl Into<String>,
733 kind: PermissionOptionKind,
734 ) -> Self {
735 Self {
736 option_id: option_id.into(),
737 name: name.into(),
738 kind,
739 meta: None,
740 }
741 }
742
743 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
744 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
745 /// these keys.
746 ///
747 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
748 #[must_use]
749 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
750 self.meta = meta.into_option();
751 self
752 }
753}
754
755/// Unique identifier for a permission option.
756#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, Display, From)]
757#[serde(transparent)]
758#[from(Arc<str>, String, &'static str)]
759#[non_exhaustive]
760pub struct PermissionOptionId(pub Arc<str>);
761
762impl PermissionOptionId {
763 /// Wraps a protocol string as a typed [`PermissionOptionId`].
764 #[must_use]
765 pub fn new(id: impl Into<Arc<str>>) -> Self {
766 Self(id.into())
767 }
768}
769
770/// The type of permission option being presented to the user.
771///
772/// Helps clients choose appropriate icons and UI treatment.
773#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
774#[serde(rename_all = "snake_case")]
775#[non_exhaustive]
776pub enum PermissionOptionKind {
777 /// Allow this operation only this time.
778 AllowOnce,
779 /// Allow this operation and remember the choice.
780 AllowAlways,
781 /// Reject this operation only this time.
782 RejectOnce,
783 /// Reject this operation and remember the choice.
784 RejectAlways,
785}
786
787/// Response to a permission request.
788#[serde_as]
789#[skip_serializing_none]
790#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
791#[schemars(extend("x-side" = "client", "x-method" = SESSION_REQUEST_PERMISSION_METHOD_NAME))]
792#[serde(rename_all = "camelCase")]
793#[non_exhaustive]
794pub struct RequestPermissionResponse {
795 /// The user's decision on the permission request.
796 // This extra-level is unfortunately needed because the output must be an object
797 pub outcome: RequestPermissionOutcome,
798 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
799 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
800 /// these keys.
801 ///
802 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
803 #[serde_as(deserialize_as = "DefaultOnError")]
804 #[schemars(extend("x-deserialize-default-on-error" = true))]
805 #[serde(default)]
806 #[serde(rename = "_meta")]
807 pub meta: Option<Meta>,
808}
809
810impl RequestPermissionResponse {
811 /// Builds [`RequestPermissionResponse`] with the required response fields set; optional fields start unset or empty.
812 #[must_use]
813 pub fn new(outcome: RequestPermissionOutcome) -> Self {
814 Self {
815 outcome,
816 meta: None,
817 }
818 }
819
820 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
821 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
822 /// these keys.
823 ///
824 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
825 #[must_use]
826 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
827 self.meta = meta.into_option();
828 self
829 }
830}
831
832/// The outcome of a permission request.
833#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
834#[serde(tag = "outcome", rename_all = "snake_case")]
835#[schemars(extend("discriminator" = {"propertyName": "outcome"}))]
836#[non_exhaustive]
837pub enum RequestPermissionOutcome {
838 /// The prompt turn was cancelled before the user responded.
839 ///
840 /// When a client sends a `session/cancel` notification to cancel an ongoing
841 /// prompt turn, it MUST respond to all pending `session/request_permission`
842 /// requests with this `Cancelled` outcome.
843 ///
844 /// See protocol docs: [Cancellation](https://agentclientprotocol.com/protocol/prompt-turn#cancellation)
845 Cancelled,
846 /// The user selected one of the provided options.
847 #[serde(rename_all = "camelCase")]
848 Selected(SelectedPermissionOutcome),
849}
850
851/// The user selected one of the provided options.
852#[serde_as]
853#[skip_serializing_none]
854#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
855#[serde(rename_all = "camelCase")]
856#[non_exhaustive]
857pub struct SelectedPermissionOutcome {
858 /// The ID of the option the user selected.
859 pub option_id: PermissionOptionId,
860 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
861 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
862 /// these keys.
863 ///
864 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
865 #[serde_as(deserialize_as = "DefaultOnError")]
866 #[schemars(extend("x-deserialize-default-on-error" = true))]
867 #[serde(default)]
868 #[serde(rename = "_meta")]
869 pub meta: Option<Meta>,
870}
871
872impl SelectedPermissionOutcome {
873 /// Builds [`SelectedPermissionOutcome`] with the required fields set; optional fields start unset or empty.
874 #[must_use]
875 pub fn new(option_id: impl Into<PermissionOptionId>) -> Self {
876 Self {
877 option_id: option_id.into(),
878 meta: None,
879 }
880 }
881
882 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
883 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
884 /// these keys.
885 ///
886 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
887 #[must_use]
888 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
889 self.meta = meta.into_option();
890 self
891 }
892}
893
894// Write text file
895
896/// Request to write content to a text file.
897///
898/// Only available if the client supports the `fs.writeTextFile` capability.
899#[serde_as]
900#[skip_serializing_none]
901#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
902#[schemars(extend("x-side" = "client", "x-method" = FS_WRITE_TEXT_FILE_METHOD_NAME))]
903#[serde(rename_all = "camelCase")]
904#[non_exhaustive]
905pub struct WriteTextFileRequest {
906 /// The session ID for this request.
907 pub session_id: SessionId,
908 /// Absolute path to the file to write.
909 pub path: PathBuf,
910 /// The text content to write to the file.
911 pub content: String,
912 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
913 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
914 /// these keys.
915 ///
916 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
917 #[serde_as(deserialize_as = "DefaultOnError")]
918 #[schemars(extend("x-deserialize-default-on-error" = true))]
919 #[serde(default)]
920 #[serde(rename = "_meta")]
921 pub meta: Option<Meta>,
922}
923
924impl WriteTextFileRequest {
925 /// Builds [`WriteTextFileRequest`] with the required request fields set; optional fields start unset or empty.
926 #[must_use]
927 pub fn new(
928 session_id: impl Into<SessionId>,
929 path: impl Into<PathBuf>,
930 content: impl Into<String>,
931 ) -> Self {
932 Self {
933 session_id: session_id.into(),
934 path: path.into(),
935 content: content.into(),
936 meta: None,
937 }
938 }
939
940 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
941 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
942 /// these keys.
943 ///
944 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
945 #[must_use]
946 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
947 self.meta = meta.into_option();
948 self
949 }
950}
951
952/// Response to `fs/write_text_file`
953#[serde_as]
954#[skip_serializing_none]
955#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
956#[serde(rename_all = "camelCase")]
957#[schemars(extend("x-side" = "client", "x-method" = FS_WRITE_TEXT_FILE_METHOD_NAME))]
958#[non_exhaustive]
959pub struct WriteTextFileResponse {
960 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
961 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
962 /// these keys.
963 ///
964 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
965 #[serde_as(deserialize_as = "DefaultOnError")]
966 #[schemars(extend("x-deserialize-default-on-error" = true))]
967 #[serde(default)]
968 #[serde(rename = "_meta")]
969 pub meta: Option<Meta>,
970}
971
972impl WriteTextFileResponse {
973 /// Builds [`WriteTextFileResponse`] with the required response fields set; optional fields start unset or empty.
974 #[must_use]
975 pub fn new() -> Self {
976 Self::default()
977 }
978
979 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
980 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
981 /// these keys.
982 ///
983 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
984 #[must_use]
985 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
986 self.meta = meta.into_option();
987 self
988 }
989}
990
991// Read text file
992
993/// Request to read content from a text file.
994///
995/// Only available if the client supports the `fs.readTextFile` capability.
996#[serde_as]
997#[skip_serializing_none]
998#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
999#[schemars(extend("x-side" = "client", "x-method" = FS_READ_TEXT_FILE_METHOD_NAME))]
1000#[serde(rename_all = "camelCase")]
1001#[non_exhaustive]
1002pub struct ReadTextFileRequest {
1003 /// The session ID for this request.
1004 pub session_id: SessionId,
1005 /// Absolute path to the file to read.
1006 pub path: PathBuf,
1007 /// Line number to start reading from (1-based).
1008 #[serde_as(deserialize_as = "DefaultOnError")]
1009 #[schemars(extend("x-deserialize-default-on-error" = true))]
1010 #[serde(default)]
1011 pub line: Option<u32>,
1012 /// Maximum number of lines to read.
1013 #[serde_as(deserialize_as = "DefaultOnError")]
1014 #[schemars(extend("x-deserialize-default-on-error" = true))]
1015 #[serde(default)]
1016 pub limit: Option<u32>,
1017 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1018 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1019 /// these keys.
1020 ///
1021 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1022 #[serde_as(deserialize_as = "DefaultOnError")]
1023 #[schemars(extend("x-deserialize-default-on-error" = true))]
1024 #[serde(default)]
1025 #[serde(rename = "_meta")]
1026 pub meta: Option<Meta>,
1027}
1028
1029impl ReadTextFileRequest {
1030 /// Builds [`ReadTextFileRequest`] with the required request fields set; optional fields start unset or empty.
1031 #[must_use]
1032 pub fn new(session_id: impl Into<SessionId>, path: impl Into<PathBuf>) -> Self {
1033 Self {
1034 session_id: session_id.into(),
1035 path: path.into(),
1036 line: None,
1037 limit: None,
1038 meta: None,
1039 }
1040 }
1041
1042 /// Line number to start reading from (1-based).
1043 #[must_use]
1044 pub fn line(mut self, line: impl IntoOption<u32>) -> Self {
1045 self.line = line.into_option();
1046 self
1047 }
1048
1049 /// Maximum number of lines to read.
1050 #[must_use]
1051 pub fn limit(mut self, limit: impl IntoOption<u32>) -> Self {
1052 self.limit = limit.into_option();
1053 self
1054 }
1055
1056 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1057 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1058 /// these keys.
1059 ///
1060 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1061 #[must_use]
1062 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1063 self.meta = meta.into_option();
1064 self
1065 }
1066}
1067
1068/// Response containing the contents of a text file.
1069#[serde_as]
1070#[skip_serializing_none]
1071#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1072#[schemars(extend("x-side" = "client", "x-method" = FS_READ_TEXT_FILE_METHOD_NAME))]
1073#[serde(rename_all = "camelCase")]
1074#[non_exhaustive]
1075pub struct ReadTextFileResponse {
1076 /// Content payload returned by this response.
1077 pub content: String,
1078 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1079 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1080 /// these keys.
1081 ///
1082 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1083 #[serde_as(deserialize_as = "DefaultOnError")]
1084 #[schemars(extend("x-deserialize-default-on-error" = true))]
1085 #[serde(default)]
1086 #[serde(rename = "_meta")]
1087 pub meta: Option<Meta>,
1088}
1089
1090impl ReadTextFileResponse {
1091 /// Builds [`ReadTextFileResponse`] with the required response fields set; optional fields start unset or empty.
1092 #[must_use]
1093 pub fn new(content: impl Into<String>) -> Self {
1094 Self {
1095 content: content.into(),
1096 meta: None,
1097 }
1098 }
1099
1100 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1101 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1102 /// these keys.
1103 ///
1104 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1105 #[must_use]
1106 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1107 self.meta = meta.into_option();
1108 self
1109 }
1110}
1111
1112// Terminals
1113
1114/// Typed identifier used for terminal values on the wire.
1115#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, Display, From)]
1116#[serde(transparent)]
1117#[from(Arc<str>, String, &'static str)]
1118#[non_exhaustive]
1119pub struct TerminalId(pub Arc<str>);
1120
1121impl TerminalId {
1122 /// Wraps a protocol string as a typed [`TerminalId`].
1123 #[must_use]
1124 pub fn new(id: impl Into<Arc<str>>) -> Self {
1125 Self(id.into())
1126 }
1127}
1128
1129/// Request to create a new terminal and execute a command.
1130#[serde_as]
1131#[skip_serializing_none]
1132#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1133#[serde(rename_all = "camelCase")]
1134#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_CREATE_METHOD_NAME))]
1135#[non_exhaustive]
1136pub struct CreateTerminalRequest {
1137 /// The session ID for this request.
1138 pub session_id: SessionId,
1139 /// The command to execute.
1140 pub command: String,
1141 /// Array of command arguments.
1142 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1143 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1144 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1145 pub args: Vec<String>,
1146 /// Environment variables for the command.
1147 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1148 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1149 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1150 pub env: Vec<EnvVariable>,
1151 /// Working directory for the command (absolute path).
1152 #[serde_as(deserialize_as = "DefaultOnError")]
1153 #[schemars(extend("x-deserialize-default-on-error" = true))]
1154 #[serde(default)]
1155 pub cwd: Option<PathBuf>,
1156 /// Maximum number of output bytes to retain.
1157 ///
1158 /// When the limit is exceeded, the Client truncates from the beginning of the output
1159 /// to stay within the limit.
1160 ///
1161 /// The Client MUST ensure truncation happens at a character boundary to maintain valid
1162 /// string output, even if this means the retained output is slightly less than the
1163 /// specified limit.
1164 #[serde_as(deserialize_as = "DefaultOnError")]
1165 #[schemars(extend("x-deserialize-default-on-error" = true))]
1166 #[serde(default)]
1167 pub output_byte_limit: Option<u64>,
1168 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1169 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1170 /// these keys.
1171 ///
1172 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1173 #[serde_as(deserialize_as = "DefaultOnError")]
1174 #[schemars(extend("x-deserialize-default-on-error" = true))]
1175 #[serde(default)]
1176 #[serde(rename = "_meta")]
1177 pub meta: Option<Meta>,
1178}
1179
1180impl CreateTerminalRequest {
1181 /// Builds [`CreateTerminalRequest`] with the required request fields set; optional fields start unset or empty.
1182 #[must_use]
1183 pub fn new(session_id: impl Into<SessionId>, command: impl Into<String>) -> Self {
1184 Self {
1185 session_id: session_id.into(),
1186 command: command.into(),
1187 args: Vec::new(),
1188 env: Vec::new(),
1189 cwd: None,
1190 output_byte_limit: None,
1191 meta: None,
1192 }
1193 }
1194
1195 /// Array of command arguments.
1196 #[must_use]
1197 pub fn args(mut self, args: Vec<String>) -> Self {
1198 self.args = args;
1199 self
1200 }
1201
1202 /// Environment variables for the command.
1203 #[must_use]
1204 pub fn env(mut self, env: Vec<EnvVariable>) -> Self {
1205 self.env = env;
1206 self
1207 }
1208
1209 /// Working directory for the command (absolute path).
1210 #[must_use]
1211 pub fn cwd(mut self, cwd: impl IntoOption<PathBuf>) -> Self {
1212 self.cwd = cwd.into_option();
1213 self
1214 }
1215
1216 /// Maximum number of output bytes to retain.
1217 ///
1218 /// When the limit is exceeded, the Client truncates from the beginning of the output
1219 /// to stay within the limit.
1220 ///
1221 /// The Client MUST ensure truncation happens at a character boundary to maintain valid
1222 /// string output, even if this means the retained output is slightly less than the
1223 /// specified limit.
1224 #[must_use]
1225 pub fn output_byte_limit(mut self, output_byte_limit: impl IntoOption<u64>) -> Self {
1226 self.output_byte_limit = output_byte_limit.into_option();
1227 self
1228 }
1229
1230 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1231 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1232 /// these keys.
1233 ///
1234 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1235 #[must_use]
1236 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1237 self.meta = meta.into_option();
1238 self
1239 }
1240}
1241
1242/// Response containing the ID of the created terminal.
1243#[serde_as]
1244#[skip_serializing_none]
1245#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1246#[serde(rename_all = "camelCase")]
1247#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_CREATE_METHOD_NAME))]
1248#[non_exhaustive]
1249pub struct CreateTerminalResponse {
1250 /// The unique identifier for the created terminal.
1251 pub terminal_id: TerminalId,
1252 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1253 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1254 /// these keys.
1255 ///
1256 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1257 #[serde_as(deserialize_as = "DefaultOnError")]
1258 #[schemars(extend("x-deserialize-default-on-error" = true))]
1259 #[serde(default)]
1260 #[serde(rename = "_meta")]
1261 pub meta: Option<Meta>,
1262}
1263
1264impl CreateTerminalResponse {
1265 /// Builds [`CreateTerminalResponse`] with the required response fields set; optional fields start unset or empty.
1266 #[must_use]
1267 pub fn new(terminal_id: impl Into<TerminalId>) -> Self {
1268 Self {
1269 terminal_id: terminal_id.into(),
1270 meta: None,
1271 }
1272 }
1273
1274 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1275 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1276 /// these keys.
1277 ///
1278 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1279 #[must_use]
1280 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1281 self.meta = meta.into_option();
1282 self
1283 }
1284}
1285
1286/// Request to get the current output and status of a terminal.
1287#[serde_as]
1288#[skip_serializing_none]
1289#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1290#[serde(rename_all = "camelCase")]
1291#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_OUTPUT_METHOD_NAME))]
1292#[non_exhaustive]
1293pub struct TerminalOutputRequest {
1294 /// The session ID for this request.
1295 pub session_id: SessionId,
1296 /// The ID of the terminal to get output from.
1297 pub terminal_id: TerminalId,
1298 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1299 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1300 /// these keys.
1301 ///
1302 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1303 #[serde_as(deserialize_as = "DefaultOnError")]
1304 #[schemars(extend("x-deserialize-default-on-error" = true))]
1305 #[serde(default)]
1306 #[serde(rename = "_meta")]
1307 pub meta: Option<Meta>,
1308}
1309
1310impl TerminalOutputRequest {
1311 /// Builds [`TerminalOutputRequest`] with the required request fields set; optional fields start unset or empty.
1312 #[must_use]
1313 pub fn new(session_id: impl Into<SessionId>, terminal_id: impl Into<TerminalId>) -> Self {
1314 Self {
1315 session_id: session_id.into(),
1316 terminal_id: terminal_id.into(),
1317 meta: None,
1318 }
1319 }
1320
1321 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1322 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1323 /// these keys.
1324 ///
1325 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1326 #[must_use]
1327 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1328 self.meta = meta.into_option();
1329 self
1330 }
1331}
1332
1333/// Response containing the terminal output and exit status.
1334#[serde_as]
1335#[skip_serializing_none]
1336#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1337#[serde(rename_all = "camelCase")]
1338#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_OUTPUT_METHOD_NAME))]
1339#[non_exhaustive]
1340pub struct TerminalOutputResponse {
1341 /// The terminal output captured so far.
1342 pub output: String,
1343 /// Whether the output was truncated due to byte limits.
1344 pub truncated: bool,
1345 /// Exit status if the command has completed.
1346 #[serde_as(deserialize_as = "DefaultOnError")]
1347 #[schemars(extend("x-deserialize-default-on-error" = true))]
1348 #[serde(default)]
1349 pub exit_status: Option<TerminalExitStatus>,
1350 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1351 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1352 /// these keys.
1353 ///
1354 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1355 #[serde_as(deserialize_as = "DefaultOnError")]
1356 #[schemars(extend("x-deserialize-default-on-error" = true))]
1357 #[serde(default)]
1358 #[serde(rename = "_meta")]
1359 pub meta: Option<Meta>,
1360}
1361
1362impl TerminalOutputResponse {
1363 /// Builds [`TerminalOutputResponse`] with the required response fields set; optional fields start unset or empty.
1364 #[must_use]
1365 pub fn new(output: impl Into<String>, truncated: bool) -> Self {
1366 Self {
1367 output: output.into(),
1368 truncated,
1369 exit_status: None,
1370 meta: None,
1371 }
1372 }
1373
1374 /// Exit status if the command has completed.
1375 #[must_use]
1376 pub fn exit_status(mut self, exit_status: impl IntoOption<TerminalExitStatus>) -> Self {
1377 self.exit_status = exit_status.into_option();
1378 self
1379 }
1380
1381 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1382 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1383 /// these keys.
1384 ///
1385 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1386 #[must_use]
1387 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1388 self.meta = meta.into_option();
1389 self
1390 }
1391}
1392
1393/// Request to release a terminal and free its resources.
1394#[serde_as]
1395#[skip_serializing_none]
1396#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1397#[serde(rename_all = "camelCase")]
1398#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_RELEASE_METHOD_NAME))]
1399#[non_exhaustive]
1400pub struct ReleaseTerminalRequest {
1401 /// The session ID for this request.
1402 pub session_id: SessionId,
1403 /// The ID of the terminal to release.
1404 pub terminal_id: TerminalId,
1405 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1406 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1407 /// these keys.
1408 ///
1409 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1410 #[serde_as(deserialize_as = "DefaultOnError")]
1411 #[schemars(extend("x-deserialize-default-on-error" = true))]
1412 #[serde(default)]
1413 #[serde(rename = "_meta")]
1414 pub meta: Option<Meta>,
1415}
1416
1417impl ReleaseTerminalRequest {
1418 /// Builds [`ReleaseTerminalRequest`] with the required request fields set; optional fields start unset or empty.
1419 #[must_use]
1420 pub fn new(session_id: impl Into<SessionId>, terminal_id: impl Into<TerminalId>) -> Self {
1421 Self {
1422 session_id: session_id.into(),
1423 terminal_id: terminal_id.into(),
1424 meta: None,
1425 }
1426 }
1427
1428 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1429 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1430 /// these keys.
1431 ///
1432 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1433 #[must_use]
1434 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1435 self.meta = meta.into_option();
1436 self
1437 }
1438}
1439
1440/// Response to terminal/release method
1441#[serde_as]
1442#[skip_serializing_none]
1443#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1444#[serde(rename_all = "camelCase")]
1445#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_RELEASE_METHOD_NAME))]
1446#[non_exhaustive]
1447pub struct ReleaseTerminalResponse {
1448 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1449 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1450 /// these keys.
1451 ///
1452 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1453 #[serde_as(deserialize_as = "DefaultOnError")]
1454 #[schemars(extend("x-deserialize-default-on-error" = true))]
1455 #[serde(default)]
1456 #[serde(rename = "_meta")]
1457 pub meta: Option<Meta>,
1458}
1459
1460impl ReleaseTerminalResponse {
1461 /// Builds [`ReleaseTerminalResponse`] with the required response fields set; optional fields start unset or empty.
1462 #[must_use]
1463 pub fn new() -> Self {
1464 Self::default()
1465 }
1466
1467 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1468 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1469 /// these keys.
1470 ///
1471 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1472 #[must_use]
1473 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1474 self.meta = meta.into_option();
1475 self
1476 }
1477}
1478
1479/// Request to kill a terminal without releasing it.
1480#[serde_as]
1481#[skip_serializing_none]
1482#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1483#[serde(rename_all = "camelCase")]
1484#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_KILL_METHOD_NAME))]
1485#[non_exhaustive]
1486pub struct KillTerminalRequest {
1487 /// The session ID for this request.
1488 pub session_id: SessionId,
1489 /// The ID of the terminal to kill.
1490 pub terminal_id: TerminalId,
1491 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1492 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1493 /// these keys.
1494 ///
1495 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1496 #[serde_as(deserialize_as = "DefaultOnError")]
1497 #[schemars(extend("x-deserialize-default-on-error" = true))]
1498 #[serde(default)]
1499 #[serde(rename = "_meta")]
1500 pub meta: Option<Meta>,
1501}
1502
1503impl KillTerminalRequest {
1504 /// Builds [`KillTerminalRequest`] with the required request fields set; optional fields start unset or empty.
1505 #[must_use]
1506 pub fn new(session_id: impl Into<SessionId>, terminal_id: impl Into<TerminalId>) -> Self {
1507 Self {
1508 session_id: session_id.into(),
1509 terminal_id: terminal_id.into(),
1510 meta: None,
1511 }
1512 }
1513
1514 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1515 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1516 /// these keys.
1517 ///
1518 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1519 #[must_use]
1520 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1521 self.meta = meta.into_option();
1522 self
1523 }
1524}
1525
1526/// Response to `terminal/kill` method
1527#[serde_as]
1528#[skip_serializing_none]
1529#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1530#[serde(rename_all = "camelCase")]
1531#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_KILL_METHOD_NAME))]
1532#[non_exhaustive]
1533pub struct KillTerminalResponse {
1534 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1535 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1536 /// these keys.
1537 ///
1538 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1539 #[serde_as(deserialize_as = "DefaultOnError")]
1540 #[schemars(extend("x-deserialize-default-on-error" = true))]
1541 #[serde(default)]
1542 #[serde(rename = "_meta")]
1543 pub meta: Option<Meta>,
1544}
1545
1546impl KillTerminalResponse {
1547 /// Builds [`KillTerminalResponse`] with the required response fields set; optional fields start unset or empty.
1548 #[must_use]
1549 pub fn new() -> Self {
1550 Self::default()
1551 }
1552
1553 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1554 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1555 /// these keys.
1556 ///
1557 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1558 #[must_use]
1559 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1560 self.meta = meta.into_option();
1561 self
1562 }
1563}
1564
1565/// Request to wait for a terminal command to exit.
1566#[serde_as]
1567#[skip_serializing_none]
1568#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1569#[serde(rename_all = "camelCase")]
1570#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_WAIT_FOR_EXIT_METHOD_NAME))]
1571#[non_exhaustive]
1572pub struct WaitForTerminalExitRequest {
1573 /// The session ID for this request.
1574 pub session_id: SessionId,
1575 /// The ID of the terminal to wait for.
1576 pub terminal_id: TerminalId,
1577 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1578 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1579 /// these keys.
1580 ///
1581 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1582 #[serde_as(deserialize_as = "DefaultOnError")]
1583 #[schemars(extend("x-deserialize-default-on-error" = true))]
1584 #[serde(default)]
1585 #[serde(rename = "_meta")]
1586 pub meta: Option<Meta>,
1587}
1588
1589impl WaitForTerminalExitRequest {
1590 /// Builds [`WaitForTerminalExitRequest`] with the required request fields set; optional fields start unset or empty.
1591 #[must_use]
1592 pub fn new(session_id: impl Into<SessionId>, terminal_id: impl Into<TerminalId>) -> Self {
1593 Self {
1594 session_id: session_id.into(),
1595 terminal_id: terminal_id.into(),
1596 meta: None,
1597 }
1598 }
1599
1600 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1601 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1602 /// these keys.
1603 ///
1604 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1605 #[must_use]
1606 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1607 self.meta = meta.into_option();
1608 self
1609 }
1610}
1611
1612/// Response containing the exit status of a terminal command.
1613#[serde_as]
1614#[skip_serializing_none]
1615#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1616#[serde(rename_all = "camelCase")]
1617#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_WAIT_FOR_EXIT_METHOD_NAME))]
1618#[non_exhaustive]
1619pub struct WaitForTerminalExitResponse {
1620 /// The exit status of the terminal command.
1621 #[serde(flatten)]
1622 pub exit_status: TerminalExitStatus,
1623 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1624 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1625 /// these keys.
1626 ///
1627 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1628 #[serde_as(deserialize_as = "DefaultOnError")]
1629 #[schemars(extend("x-deserialize-default-on-error" = true))]
1630 #[serde(default)]
1631 #[serde(rename = "_meta")]
1632 pub meta: Option<Meta>,
1633}
1634
1635impl WaitForTerminalExitResponse {
1636 /// Builds [`WaitForTerminalExitResponse`] with the required response fields set; optional fields start unset or empty.
1637 #[must_use]
1638 pub fn new(exit_status: TerminalExitStatus) -> Self {
1639 Self {
1640 exit_status,
1641 meta: None,
1642 }
1643 }
1644
1645 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1646 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1647 /// these keys.
1648 ///
1649 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1650 #[must_use]
1651 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1652 self.meta = meta.into_option();
1653 self
1654 }
1655}
1656
1657/// Exit status of a terminal command.
1658#[serde_as]
1659#[skip_serializing_none]
1660#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1661#[serde(rename_all = "camelCase")]
1662#[non_exhaustive]
1663pub struct TerminalExitStatus {
1664 /// The process exit code (may be null if terminated by signal).
1665 #[serde_as(deserialize_as = "DefaultOnError")]
1666 #[schemars(extend("x-deserialize-default-on-error" = true))]
1667 #[serde(default)]
1668 pub exit_code: Option<u32>,
1669 /// The signal that terminated the process (may be null if exited normally).
1670 #[serde_as(deserialize_as = "DefaultOnError")]
1671 #[schemars(extend("x-deserialize-default-on-error" = true))]
1672 #[serde(default)]
1673 pub signal: Option<String>,
1674 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1675 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1676 /// these keys.
1677 ///
1678 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1679 #[serde_as(deserialize_as = "DefaultOnError")]
1680 #[schemars(extend("x-deserialize-default-on-error" = true))]
1681 #[serde(default)]
1682 #[serde(rename = "_meta")]
1683 pub meta: Option<Meta>,
1684}
1685
1686impl TerminalExitStatus {
1687 /// Builds [`TerminalExitStatus`] with the required fields set; optional fields start unset or empty.
1688 #[must_use]
1689 pub fn new() -> Self {
1690 Self::default()
1691 }
1692
1693 /// The process exit code (may be null if terminated by signal).
1694 #[must_use]
1695 pub fn exit_code(mut self, exit_code: impl IntoOption<u32>) -> Self {
1696 self.exit_code = exit_code.into_option();
1697 self
1698 }
1699
1700 /// The signal that terminated the process (may be null if exited normally).
1701 #[must_use]
1702 pub fn signal(mut self, signal: impl IntoOption<String>) -> Self {
1703 self.signal = signal.into_option();
1704 self
1705 }
1706
1707 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1708 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1709 /// these keys.
1710 ///
1711 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1712 #[must_use]
1713 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1714 self.meta = meta.into_option();
1715 self
1716 }
1717}
1718
1719// Capabilities
1720
1721/// Capabilities supported by the client.
1722///
1723/// Advertised during initialization to inform the agent about
1724/// available features and methods.
1725///
1726/// See protocol docs: [Client Capabilities](https://agentclientprotocol.com/protocol/initialization#client-capabilities)
1727#[serde_as]
1728#[skip_serializing_none]
1729#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1730#[serde(rename_all = "camelCase")]
1731#[non_exhaustive]
1732pub struct ClientCapabilities {
1733 /// File system capabilities supported by the client.
1734 /// Determines which file operations the agent can request.
1735 #[serde_as(deserialize_as = "DefaultOnError")]
1736 #[schemars(extend("x-deserialize-default-on-error" = true))]
1737 #[serde(default)]
1738 pub fs: FileSystemCapabilities,
1739 /// Whether the Client support all `terminal/*` methods.
1740 #[serde_as(deserialize_as = "DefaultOnError")]
1741 #[schemars(extend("x-deserialize-default-on-error" = true))]
1742 #[serde(default)]
1743 pub terminal: bool,
1744 /// **UNSTABLE**
1745 ///
1746 /// This capability is not part of the spec yet, and may be removed or changed at any point.
1747 ///
1748 /// Session-related capabilities supported by the client.
1749 #[cfg(feature = "unstable_boolean_config")]
1750 #[serde_as(deserialize_as = "DefaultOnError")]
1751 #[schemars(extend("x-deserialize-default-on-error" = true))]
1752 #[serde(default)]
1753 pub session: Option<ClientSessionCapabilities>,
1754 /// **UNSTABLE**
1755 ///
1756 /// This capability is not part of the spec yet, and may be removed or changed at any point.
1757 ///
1758 /// Whether the client supports `plan_update` and `plan_removed` session updates.
1759 ///
1760 /// Optional. Omitted means the client does not advertise support.
1761 /// Supplying `{}` means the client can receive both update types.
1762 #[cfg(feature = "unstable_plan_operations")]
1763 #[serde_as(deserialize_as = "DefaultOnError")]
1764 #[schemars(extend("x-deserialize-default-on-error" = true))]
1765 #[serde(default)]
1766 pub plan: Option<PlanCapabilities>,
1767 /// **UNSTABLE**
1768 ///
1769 /// This capability is not part of the spec yet, and may be removed or changed at any point.
1770 ///
1771 /// Authentication capabilities supported by the client.
1772 /// Determines which authentication method types the agent may include
1773 /// in its `InitializeResponse`.
1774 #[cfg(feature = "unstable_auth_methods")]
1775 #[serde_as(deserialize_as = "DefaultOnError")]
1776 #[schemars(extend("x-deserialize-default-on-error" = true))]
1777 #[serde(default)]
1778 pub auth: AuthCapabilities,
1779 /// **UNSTABLE**
1780 ///
1781 /// This capability is not part of the spec yet, and may be removed or changed at any point.
1782 ///
1783 /// Elicitation capabilities supported by the client.
1784 /// Determines which elicitation modes the agent may use.
1785 #[cfg(feature = "unstable_elicitation")]
1786 #[serde_as(deserialize_as = "DefaultOnError")]
1787 #[schemars(extend("x-deserialize-default-on-error" = true))]
1788 #[serde(default)]
1789 pub elicitation: Option<ElicitationCapabilities>,
1790 /// **UNSTABLE**
1791 ///
1792 /// This capability is not part of the spec yet, and may be removed or changed at any point.
1793 ///
1794 /// NES (Next Edit Suggestions) capabilities supported by the client.
1795 #[cfg(feature = "unstable_nes")]
1796 #[serde_as(deserialize_as = "DefaultOnError")]
1797 #[schemars(extend("x-deserialize-default-on-error" = true))]
1798 #[serde(default)]
1799 pub nes: Option<ClientNesCapabilities>,
1800 /// **UNSTABLE**
1801 ///
1802 /// This capability is not part of the spec yet, and may be removed or changed at any point.
1803 ///
1804 /// The position encodings supported by the client, in order of preference.
1805 #[cfg(feature = "unstable_nes")]
1806 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1807 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1808 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1809 pub position_encodings: Vec<PositionEncodingKind>,
1810
1811 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1812 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1813 /// these keys.
1814 ///
1815 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1816 #[serde_as(deserialize_as = "DefaultOnError")]
1817 #[schemars(extend("x-deserialize-default-on-error" = true))]
1818 #[serde(default)]
1819 #[serde(rename = "_meta")]
1820 pub meta: Option<Meta>,
1821}
1822
1823impl ClientCapabilities {
1824 /// Builds an empty [`ClientCapabilities`]; use builder methods to advertise supported sub-capabilities.
1825 #[must_use]
1826 pub fn new() -> Self {
1827 Self::default()
1828 }
1829
1830 /// File system capabilities supported by the client.
1831 /// Determines which file operations the agent can request.
1832 #[must_use]
1833 pub fn fs(mut self, fs: FileSystemCapabilities) -> Self {
1834 self.fs = fs;
1835 self
1836 }
1837
1838 /// Whether the Client support all `terminal/*` methods.
1839 #[must_use]
1840 pub fn terminal(mut self, terminal: bool) -> Self {
1841 self.terminal = terminal;
1842 self
1843 }
1844
1845 /// **UNSTABLE**
1846 ///
1847 /// This capability is not part of the spec yet, and may be removed or changed at any point.
1848 ///
1849 /// Session-related capabilities supported by the client.
1850 #[cfg(feature = "unstable_boolean_config")]
1851 #[must_use]
1852 pub fn session(mut self, session: impl IntoOption<ClientSessionCapabilities>) -> Self {
1853 self.session = session.into_option();
1854 self
1855 }
1856
1857 /// **UNSTABLE**
1858 ///
1859 /// This capability is not part of the spec yet, and may be removed or changed at any point.
1860 ///
1861 /// Whether the client supports `plan_update` and `plan_removed` session updates.
1862 ///
1863 /// Omitted means the client does not advertise support.
1864 /// Supplying `{}` means the client can receive both update types.
1865 #[cfg(feature = "unstable_plan_operations")]
1866 #[must_use]
1867 pub fn plan(mut self, plan: impl IntoOption<PlanCapabilities>) -> Self {
1868 self.plan = plan.into_option();
1869 self
1870 }
1871
1872 /// **UNSTABLE**
1873 ///
1874 /// This capability is not part of the spec yet, and may be removed or changed at any point.
1875 ///
1876 /// Authentication capabilities supported by the client.
1877 /// Determines which authentication method types the agent may include
1878 /// in its `InitializeResponse`.
1879 #[cfg(feature = "unstable_auth_methods")]
1880 #[must_use]
1881 pub fn auth(mut self, auth: AuthCapabilities) -> Self {
1882 self.auth = auth;
1883 self
1884 }
1885
1886 /// **UNSTABLE**
1887 ///
1888 /// This capability is not part of the spec yet, and may be removed or changed at any point.
1889 ///
1890 /// Elicitation capabilities supported by the client.
1891 /// Determines which elicitation modes the agent may use.
1892 #[cfg(feature = "unstable_elicitation")]
1893 #[must_use]
1894 pub fn elicitation(mut self, elicitation: impl IntoOption<ElicitationCapabilities>) -> Self {
1895 self.elicitation = elicitation.into_option();
1896 self
1897 }
1898
1899 /// **UNSTABLE**
1900 ///
1901 /// NES (Next Edit Suggestions) capabilities supported by the client.
1902 #[cfg(feature = "unstable_nes")]
1903 #[must_use]
1904 pub fn nes(mut self, nes: impl IntoOption<ClientNesCapabilities>) -> Self {
1905 self.nes = nes.into_option();
1906 self
1907 }
1908
1909 /// **UNSTABLE**
1910 ///
1911 /// The position encodings supported by the client, in order of preference.
1912 #[cfg(feature = "unstable_nes")]
1913 #[must_use]
1914 pub fn position_encodings(mut self, position_encodings: Vec<PositionEncodingKind>) -> Self {
1915 self.position_encodings = position_encodings;
1916 self
1917 }
1918
1919 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1920 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1921 /// these keys.
1922 ///
1923 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1924 #[must_use]
1925 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1926 self.meta = meta.into_option();
1927 self
1928 }
1929}
1930
1931/// **UNSTABLE**
1932///
1933/// This capability is not part of the spec yet, and may be removed or changed at any point.
1934///
1935/// Session-related capabilities supported by the client.
1936#[cfg(feature = "unstable_boolean_config")]
1937#[serde_as]
1938#[skip_serializing_none]
1939#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1940#[serde(rename_all = "camelCase")]
1941#[non_exhaustive]
1942pub struct ClientSessionCapabilities {
1943 /// Config option capabilities supported by the client.
1944 ///
1945 /// Omitted or `null` means the client does not advertise support for any
1946 /// config option extensions.
1947 #[serde_as(deserialize_as = "DefaultOnError")]
1948 #[schemars(extend("x-deserialize-default-on-error" = true))]
1949 #[serde(default)]
1950 pub config_options: Option<SessionConfigOptionsCapabilities>,
1951 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1952 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1953 /// these keys.
1954 ///
1955 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1956 #[serde_as(deserialize_as = "DefaultOnError")]
1957 #[schemars(extend("x-deserialize-default-on-error" = true))]
1958 #[serde(default)]
1959 #[serde(rename = "_meta")]
1960 pub meta: Option<Meta>,
1961}
1962
1963#[cfg(feature = "unstable_boolean_config")]
1964impl ClientSessionCapabilities {
1965 /// Builds an empty [`ClientSessionCapabilities`]; use builder methods to advertise supported sub-capabilities.
1966 #[must_use]
1967 pub fn new() -> Self {
1968 Self::default()
1969 }
1970
1971 /// Config option capabilities supported by the client.
1972 ///
1973 /// Omitted or `null` means the client does not advertise support for any
1974 /// config option extensions.
1975 #[must_use]
1976 pub fn config_options(
1977 mut self,
1978 config_options: impl IntoOption<SessionConfigOptionsCapabilities>,
1979 ) -> Self {
1980 self.config_options = config_options.into_option();
1981 self
1982 }
1983
1984 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1985 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1986 /// these keys.
1987 ///
1988 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1989 #[must_use]
1990 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1991 self.meta = meta.into_option();
1992 self
1993 }
1994}
1995
1996/// **UNSTABLE**
1997///
1998/// This capability is not part of the spec yet, and may be removed or changed at any point.
1999///
2000/// Session configuration option capabilities supported by the client.
2001#[cfg(feature = "unstable_boolean_config")]
2002#[serde_as]
2003#[skip_serializing_none]
2004#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2005#[serde(rename_all = "camelCase")]
2006#[non_exhaustive]
2007pub struct SessionConfigOptionsCapabilities {
2008 /// Whether the client supports boolean session configuration options.
2009 ///
2010 /// Omitted or `null` means the client does not advertise support.
2011 /// Supplying `{}` means agents may include `type: "boolean"` entries in
2012 /// `configOptions`, and the client may send `session/set_config_option`
2013 /// requests with `type: "boolean"` and a boolean `value`.
2014 #[serde_as(deserialize_as = "DefaultOnError")]
2015 #[schemars(extend("x-deserialize-default-on-error" = true))]
2016 #[serde(default)]
2017 pub boolean: Option<BooleanConfigOptionCapabilities>,
2018 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2019 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2020 /// these keys.
2021 ///
2022 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2023 #[serde_as(deserialize_as = "DefaultOnError")]
2024 #[schemars(extend("x-deserialize-default-on-error" = true))]
2025 #[serde(default)]
2026 #[serde(rename = "_meta")]
2027 pub meta: Option<Meta>,
2028}
2029
2030#[cfg(feature = "unstable_boolean_config")]
2031impl SessionConfigOptionsCapabilities {
2032 /// Builds an empty [`SessionConfigOptionsCapabilities`]; use builder methods to advertise supported sub-capabilities.
2033 #[must_use]
2034 pub fn new() -> Self {
2035 Self::default()
2036 }
2037
2038 /// Whether the client supports boolean session configuration options.
2039 ///
2040 /// Omitted or `null` means the client does not advertise support.
2041 /// Supplying `{}` means agents may include `type: "boolean"` entries in
2042 /// `configOptions`, and the client may send `session/set_config_option`
2043 /// requests with `type: "boolean"` and a boolean `value`.
2044 #[must_use]
2045 pub fn boolean(mut self, boolean: impl IntoOption<BooleanConfigOptionCapabilities>) -> Self {
2046 self.boolean = boolean.into_option();
2047 self
2048 }
2049
2050 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2051 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2052 /// these keys.
2053 ///
2054 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2055 #[must_use]
2056 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2057 self.meta = meta.into_option();
2058 self
2059 }
2060}
2061
2062/// **UNSTABLE**
2063///
2064/// This capability is not part of the spec yet, and may be removed or changed at any point.
2065///
2066/// Capabilities for boolean session configuration options.
2067///
2068/// Supplying `{}` means the client supports boolean session configuration options.
2069#[cfg(feature = "unstable_boolean_config")]
2070#[serde_as]
2071#[skip_serializing_none]
2072#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2073#[non_exhaustive]
2074pub struct BooleanConfigOptionCapabilities {
2075 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2076 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2077 /// these keys.
2078 ///
2079 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2080 #[serde_as(deserialize_as = "DefaultOnError")]
2081 #[schemars(extend("x-deserialize-default-on-error" = true))]
2082 #[serde(default)]
2083 #[serde(rename = "_meta")]
2084 pub meta: Option<Meta>,
2085}
2086
2087#[cfg(feature = "unstable_boolean_config")]
2088impl BooleanConfigOptionCapabilities {
2089 /// Builds an empty [`BooleanConfigOptionCapabilities`]; use builder methods to advertise supported sub-capabilities.
2090 #[must_use]
2091 pub fn new() -> Self {
2092 Self::default()
2093 }
2094
2095 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2096 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2097 /// these keys.
2098 ///
2099 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2100 #[must_use]
2101 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2102 self.meta = meta.into_option();
2103 self
2104 }
2105}
2106
2107/// **UNSTABLE**
2108///
2109/// This capability is not part of the spec yet, and may be removed or changed at any point.
2110///
2111/// Authentication capabilities supported by the client.
2112///
2113/// Advertised during initialization to inform the agent which authentication
2114/// method types the client can handle. This governs opt-in types that require
2115/// additional client-side support.
2116#[cfg(feature = "unstable_auth_methods")]
2117#[serde_as]
2118#[skip_serializing_none]
2119#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2120#[serde(rename_all = "camelCase")]
2121#[non_exhaustive]
2122pub struct AuthCapabilities {
2123 /// Whether the client supports `terminal` authentication methods.
2124 ///
2125 /// When `true`, the agent may include `terminal` entries in its authentication methods.
2126 #[serde_as(deserialize_as = "DefaultOnError")]
2127 #[schemars(extend("x-deserialize-default-on-error" = true))]
2128 #[serde(default)]
2129 pub terminal: bool,
2130 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2131 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2132 /// these keys.
2133 ///
2134 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2135 #[serde_as(deserialize_as = "DefaultOnError")]
2136 #[schemars(extend("x-deserialize-default-on-error" = true))]
2137 #[serde(default)]
2138 #[serde(rename = "_meta")]
2139 pub meta: Option<Meta>,
2140}
2141
2142#[cfg(feature = "unstable_auth_methods")]
2143impl AuthCapabilities {
2144 /// Builds an empty [`AuthCapabilities`]; use builder methods to advertise supported sub-capabilities.
2145 #[must_use]
2146 pub fn new() -> Self {
2147 Self::default()
2148 }
2149
2150 /// Whether the client supports `terminal` authentication methods.
2151 ///
2152 /// When `true`, the agent may include `AuthMethod::Terminal`
2153 /// entries in its authentication methods.
2154 #[must_use]
2155 pub fn terminal(mut self, terminal: bool) -> Self {
2156 self.terminal = terminal;
2157 self
2158 }
2159
2160 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2161 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2162 /// these keys.
2163 ///
2164 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2165 #[must_use]
2166 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2167 self.meta = meta.into_option();
2168 self
2169 }
2170}
2171
2172/// File system capabilities that a client may support.
2173///
2174/// See protocol docs: [FileSystem](https://agentclientprotocol.com/protocol/initialization#filesystem)
2175#[serde_as]
2176#[skip_serializing_none]
2177#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2178#[serde(rename_all = "camelCase")]
2179#[non_exhaustive]
2180pub struct FileSystemCapabilities {
2181 /// Whether the Client supports `fs/read_text_file` requests.
2182 #[serde_as(deserialize_as = "DefaultOnError")]
2183 #[schemars(extend("x-deserialize-default-on-error" = true))]
2184 #[serde(default)]
2185 pub read_text_file: bool,
2186 /// Whether the Client supports `fs/write_text_file` requests.
2187 #[serde_as(deserialize_as = "DefaultOnError")]
2188 #[schemars(extend("x-deserialize-default-on-error" = true))]
2189 #[serde(default)]
2190 pub write_text_file: bool,
2191 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2192 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2193 /// these keys.
2194 ///
2195 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2196 #[serde_as(deserialize_as = "DefaultOnError")]
2197 #[schemars(extend("x-deserialize-default-on-error" = true))]
2198 #[serde(default)]
2199 #[serde(rename = "_meta")]
2200 pub meta: Option<Meta>,
2201}
2202
2203impl FileSystemCapabilities {
2204 /// Builds an empty [`FileSystemCapabilities`]; use builder methods to advertise supported sub-capabilities.
2205 #[must_use]
2206 pub fn new() -> Self {
2207 Self::default()
2208 }
2209
2210 /// Whether the Client supports `fs/read_text_file` requests.
2211 #[must_use]
2212 pub fn read_text_file(mut self, read_text_file: bool) -> Self {
2213 self.read_text_file = read_text_file;
2214 self
2215 }
2216
2217 /// Whether the Client supports `fs/write_text_file` requests.
2218 #[must_use]
2219 pub fn write_text_file(mut self, write_text_file: bool) -> Self {
2220 self.write_text_file = write_text_file;
2221 self
2222 }
2223
2224 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2225 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2226 /// these keys.
2227 ///
2228 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2229 #[must_use]
2230 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2231 self.meta = meta.into_option();
2232 self
2233 }
2234}
2235
2236// Method schema
2237
2238/// Names of all methods that clients handle.
2239///
2240/// Provides a centralized definition of method names used in the protocol.
2241#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2242#[non_exhaustive]
2243pub struct ClientMethodNames {
2244 /// Method for requesting permission from the user.
2245 pub session_request_permission: &'static str,
2246 /// Notification for session updates.
2247 pub session_update: &'static str,
2248 /// Method for writing text files.
2249 pub fs_write_text_file: &'static str,
2250 /// Method for reading text files.
2251 pub fs_read_text_file: &'static str,
2252 /// Method for creating new terminals.
2253 pub terminal_create: &'static str,
2254 /// Method for getting terminals output.
2255 pub terminal_output: &'static str,
2256 /// Method for releasing a terminal.
2257 pub terminal_release: &'static str,
2258 /// Method for waiting for a terminal to finish.
2259 pub terminal_wait_for_exit: &'static str,
2260 /// Method for killing a terminal.
2261 pub terminal_kill: &'static str,
2262 /// Method for opening an MCP-over-ACP connection.
2263 #[cfg(feature = "unstable_mcp_over_acp")]
2264 pub mcp_connect: &'static str,
2265 /// Method for exchanging MCP-over-ACP messages.
2266 #[cfg(feature = "unstable_mcp_over_acp")]
2267 pub mcp_message: &'static str,
2268 /// Method for closing an MCP-over-ACP connection.
2269 #[cfg(feature = "unstable_mcp_over_acp")]
2270 pub mcp_disconnect: &'static str,
2271 /// Method for elicitation.
2272 #[cfg(feature = "unstable_elicitation")]
2273 pub elicitation_create: &'static str,
2274 /// Notification for elicitation completion.
2275 #[cfg(feature = "unstable_elicitation")]
2276 pub elicitation_complete: &'static str,
2277}
2278
2279/// Constant containing all client method names.
2280pub const CLIENT_METHOD_NAMES: ClientMethodNames = ClientMethodNames {
2281 session_update: SESSION_UPDATE_NOTIFICATION,
2282 session_request_permission: SESSION_REQUEST_PERMISSION_METHOD_NAME,
2283 fs_write_text_file: FS_WRITE_TEXT_FILE_METHOD_NAME,
2284 fs_read_text_file: FS_READ_TEXT_FILE_METHOD_NAME,
2285 terminal_create: TERMINAL_CREATE_METHOD_NAME,
2286 terminal_output: TERMINAL_OUTPUT_METHOD_NAME,
2287 terminal_release: TERMINAL_RELEASE_METHOD_NAME,
2288 terminal_wait_for_exit: TERMINAL_WAIT_FOR_EXIT_METHOD_NAME,
2289 terminal_kill: TERMINAL_KILL_METHOD_NAME,
2290 #[cfg(feature = "unstable_mcp_over_acp")]
2291 mcp_connect: MCP_CONNECT_METHOD_NAME,
2292 #[cfg(feature = "unstable_mcp_over_acp")]
2293 mcp_message: MCP_MESSAGE_METHOD_NAME,
2294 #[cfg(feature = "unstable_mcp_over_acp")]
2295 mcp_disconnect: MCP_DISCONNECT_METHOD_NAME,
2296 #[cfg(feature = "unstable_elicitation")]
2297 elicitation_create: ELICITATION_CREATE_METHOD_NAME,
2298 #[cfg(feature = "unstable_elicitation")]
2299 elicitation_complete: ELICITATION_COMPLETE_NOTIFICATION,
2300};
2301
2302/// Notification name for session updates.
2303pub(crate) const SESSION_UPDATE_NOTIFICATION: &str = "session/update";
2304/// Method name for requesting user permission.
2305pub(crate) const SESSION_REQUEST_PERMISSION_METHOD_NAME: &str = "session/request_permission";
2306/// Method name for writing text files.
2307pub(crate) const FS_WRITE_TEXT_FILE_METHOD_NAME: &str = "fs/write_text_file";
2308/// Method name for reading text files.
2309pub(crate) const FS_READ_TEXT_FILE_METHOD_NAME: &str = "fs/read_text_file";
2310/// Method name for creating a new terminal.
2311pub(crate) const TERMINAL_CREATE_METHOD_NAME: &str = "terminal/create";
2312/// Method for getting terminals output.
2313pub(crate) const TERMINAL_OUTPUT_METHOD_NAME: &str = "terminal/output";
2314/// Method for releasing a terminal.
2315pub(crate) const TERMINAL_RELEASE_METHOD_NAME: &str = "terminal/release";
2316/// Method for waiting for a terminal to finish.
2317pub(crate) const TERMINAL_WAIT_FOR_EXIT_METHOD_NAME: &str = "terminal/wait_for_exit";
2318/// Method for killing a terminal.
2319pub(crate) const TERMINAL_KILL_METHOD_NAME: &str = "terminal/kill";
2320/// Method name for elicitation.
2321#[cfg(feature = "unstable_elicitation")]
2322pub(crate) const ELICITATION_CREATE_METHOD_NAME: &str = "elicitation/create";
2323/// Notification name for elicitation completion.
2324#[cfg(feature = "unstable_elicitation")]
2325pub(crate) const ELICITATION_COMPLETE_NOTIFICATION: &str = "elicitation/complete";
2326
2327/// All possible requests that an agent can send to a client.
2328///
2329/// This enum is used internally for routing RPC requests. You typically won't need
2330/// to use this directly.
2331///
2332/// This enum encompasses all method calls from agent to client.
2333#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
2334#[serde(untagged)]
2335#[schemars(inline)]
2336#[non_exhaustive]
2337#[allow(clippy::large_enum_variant)]
2338pub enum AgentRequest {
2339 /// Writes content to a text file in the client's file system.
2340 ///
2341 /// Only available if the client advertises the `fs.writeTextFile` capability.
2342 /// Allows the agent to create or modify files within the client's environment.
2343 ///
2344 /// See protocol docs: [Client](https://agentclientprotocol.com/protocol/overview#client)
2345 WriteTextFileRequest(WriteTextFileRequest),
2346 /// Reads content from a text file in the client's file system.
2347 ///
2348 /// Only available if the client advertises the `fs.readTextFile` capability.
2349 /// Allows the agent to access file contents within the client's environment.
2350 ///
2351 /// See protocol docs: [Client](https://agentclientprotocol.com/protocol/overview#client)
2352 ReadTextFileRequest(ReadTextFileRequest),
2353 /// Requests permission from the user for a tool call operation.
2354 ///
2355 /// Called by the agent when it needs user authorization before executing
2356 /// a potentially sensitive operation. The client should present the options
2357 /// to the user and return their decision.
2358 ///
2359 /// If the client cancels the prompt turn via `session/cancel`, it MUST
2360 /// respond to this request with `RequestPermissionOutcome::Cancelled`.
2361 ///
2362 /// See protocol docs: [Requesting Permission](https://agentclientprotocol.com/protocol/tool-calls#requesting-permission)
2363 RequestPermissionRequest(RequestPermissionRequest),
2364 /// Executes a command in a new terminal
2365 ///
2366 /// Only available if the `terminal` Client capability is set to `true`.
2367 ///
2368 /// Returns a `TerminalId` that can be used with other terminal methods
2369 /// to get the current output, wait for exit, and kill the command.
2370 ///
2371 /// The `TerminalId` can also be used to embed the terminal in a tool call
2372 /// by using the `ToolCallContent::Terminal` variant.
2373 ///
2374 /// The Agent is responsible for releasing the terminal by using the `terminal/release`
2375 /// method.
2376 ///
2377 /// See protocol docs: [Terminals](https://agentclientprotocol.com/protocol/terminals)
2378 CreateTerminalRequest(CreateTerminalRequest),
2379 /// Gets the terminal output and exit status
2380 ///
2381 /// Returns the current content in the terminal without waiting for the command to exit.
2382 /// If the command has already exited, the exit status is included.
2383 ///
2384 /// See protocol docs: [Terminals](https://agentclientprotocol.com/protocol/terminals)
2385 TerminalOutputRequest(TerminalOutputRequest),
2386 /// Releases a terminal
2387 ///
2388 /// The command is killed if it hasn't exited yet. Use `terminal/wait_for_exit`
2389 /// to wait for the command to exit before releasing the terminal.
2390 ///
2391 /// After release, the `TerminalId` can no longer be used with other `terminal/*` methods,
2392 /// but tool calls that already contain it, continue to display its output.
2393 ///
2394 /// The `terminal/kill` method can be used to terminate the command without releasing
2395 /// the terminal, allowing the Agent to call `terminal/output` and other methods.
2396 ///
2397 /// See protocol docs: [Terminals](https://agentclientprotocol.com/protocol/terminals)
2398 ReleaseTerminalRequest(ReleaseTerminalRequest),
2399 /// Waits for the terminal command to exit and return its exit status
2400 ///
2401 /// See protocol docs: [Terminals](https://agentclientprotocol.com/protocol/terminals)
2402 WaitForTerminalExitRequest(WaitForTerminalExitRequest),
2403 /// Kills the terminal command without releasing the terminal
2404 ///
2405 /// While `terminal/release` will also kill the command, this method will keep
2406 /// the `TerminalId` valid so it can be used with other methods.
2407 ///
2408 /// This method can be helpful when implementing command timeouts which terminate
2409 /// the command as soon as elapsed, and then get the final output so it can be sent
2410 /// to the model.
2411 ///
2412 /// Note: Call `terminal/release` when `TerminalId` is no longer needed.
2413 ///
2414 /// See protocol docs: [Terminals](https://agentclientprotocol.com/protocol/terminals)
2415 KillTerminalRequest(KillTerminalRequest),
2416 /// **UNSTABLE**
2417 ///
2418 /// This capability is not part of the spec yet, and may be removed or changed at any point.
2419 ///
2420 /// Requests structured user input via a form or URL.
2421 #[cfg(feature = "unstable_elicitation")]
2422 CreateElicitationRequest(CreateElicitationRequest),
2423 /// **UNSTABLE**
2424 ///
2425 /// This capability is not part of the spec yet, and may be removed or changed at any point.
2426 ///
2427 /// Opens an MCP-over-ACP connection.
2428 #[cfg(feature = "unstable_mcp_over_acp")]
2429 ConnectMcpRequest(ConnectMcpRequest),
2430 /// **UNSTABLE**
2431 ///
2432 /// This capability is not part of the spec yet, and may be removed or changed at any point.
2433 ///
2434 /// Exchanges an MCP-over-ACP message.
2435 #[cfg(feature = "unstable_mcp_over_acp")]
2436 MessageMcpRequest(MessageMcpRequest),
2437 /// **UNSTABLE**
2438 ///
2439 /// This capability is not part of the spec yet, and may be removed or changed at any point.
2440 ///
2441 /// Closes an MCP-over-ACP connection.
2442 #[cfg(feature = "unstable_mcp_over_acp")]
2443 DisconnectMcpRequest(DisconnectMcpRequest),
2444 /// Handles extension method requests from the agent.
2445 ///
2446 /// Allows the Agent to send an arbitrary request that is not part of the ACP spec.
2447 /// Extension methods provide a way to add custom functionality while maintaining
2448 /// protocol compatibility.
2449 ///
2450 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2451 ExtMethodRequest(ExtRequest),
2452}
2453
2454impl AgentRequest {
2455 /// Returns the corresponding method name of the request.
2456 #[must_use]
2457 pub fn method(&self) -> &str {
2458 match self {
2459 Self::WriteTextFileRequest(_) => CLIENT_METHOD_NAMES.fs_write_text_file,
2460 Self::ReadTextFileRequest(_) => CLIENT_METHOD_NAMES.fs_read_text_file,
2461 Self::RequestPermissionRequest(_) => CLIENT_METHOD_NAMES.session_request_permission,
2462 Self::CreateTerminalRequest(_) => CLIENT_METHOD_NAMES.terminal_create,
2463 Self::TerminalOutputRequest(_) => CLIENT_METHOD_NAMES.terminal_output,
2464 Self::ReleaseTerminalRequest(_) => CLIENT_METHOD_NAMES.terminal_release,
2465 Self::WaitForTerminalExitRequest(_) => CLIENT_METHOD_NAMES.terminal_wait_for_exit,
2466 Self::KillTerminalRequest(_) => CLIENT_METHOD_NAMES.terminal_kill,
2467 #[cfg(feature = "unstable_elicitation")]
2468 Self::CreateElicitationRequest(_) => CLIENT_METHOD_NAMES.elicitation_create,
2469 #[cfg(feature = "unstable_mcp_over_acp")]
2470 Self::ConnectMcpRequest(_) => CLIENT_METHOD_NAMES.mcp_connect,
2471 #[cfg(feature = "unstable_mcp_over_acp")]
2472 Self::MessageMcpRequest(_) => CLIENT_METHOD_NAMES.mcp_message,
2473 #[cfg(feature = "unstable_mcp_over_acp")]
2474 Self::DisconnectMcpRequest(_) => CLIENT_METHOD_NAMES.mcp_disconnect,
2475 Self::ExtMethodRequest(ext_request) => &ext_request.method,
2476 }
2477 }
2478}
2479
2480/// All possible responses that a client can send to an agent.
2481///
2482/// This enum is used internally for routing RPC responses. You typically won't need
2483/// to use this directly - the responses are handled automatically by the connection.
2484///
2485/// These are responses to the corresponding `AgentRequest` variants.
2486#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
2487#[serde(untagged)]
2488#[schemars(inline)]
2489#[non_exhaustive]
2490pub enum ClientResponse {
2491 /// Successful result returned for a `fs/write_text_file` request.
2492 WriteTextFileResponse(#[serde(default)] WriteTextFileResponse),
2493 /// Successful result returned for a `fs/read_text_file` request.
2494 ReadTextFileResponse(ReadTextFileResponse),
2495 /// Successful result returned for a `session/request_permission` request.
2496 RequestPermissionResponse(RequestPermissionResponse),
2497 /// Successful result returned for a `terminal/create` request.
2498 CreateTerminalResponse(CreateTerminalResponse),
2499 /// Successful result returned for a `terminal/output` request.
2500 TerminalOutputResponse(TerminalOutputResponse),
2501 /// Successful result returned for a `terminal/release` request.
2502 ReleaseTerminalResponse(#[serde(default)] ReleaseTerminalResponse),
2503 /// Successful result returned for a `terminal/wait_for_exit` request.
2504 WaitForTerminalExitResponse(WaitForTerminalExitResponse),
2505 /// Successful result returned for a `terminal/kill` request.
2506 KillTerminalResponse(#[serde(default)] KillTerminalResponse),
2507 /// Successful result returned for a `elicitation/create` request.
2508 #[cfg(feature = "unstable_elicitation")]
2509 CreateElicitationResponse(CreateElicitationResponse),
2510 /// Successful result returned for a `mcp/connect` request.
2511 #[cfg(feature = "unstable_mcp_over_acp")]
2512 ConnectMcpResponse(ConnectMcpResponse),
2513 /// Successful result returned for a `mcp/disconnect` request.
2514 #[cfg(feature = "unstable_mcp_over_acp")]
2515 DisconnectMcpResponse(#[serde(default)] DisconnectMcpResponse),
2516 /// Successful result returned by an MCP-over-ACP `mcp/message` request.
2517 #[cfg(feature = "unstable_mcp_over_acp")]
2518 MessageMcpResponse(MessageMcpResponse),
2519 /// Successful result returned by an extension method outside the core ACP method set.
2520 ExtMethodResponse(ExtResponse),
2521}
2522
2523/// All possible notifications that an agent can send to a client.
2524///
2525/// This enum is used internally for routing RPC notifications. You typically won't need
2526/// to use this directly.
2527///
2528/// Notifications do not expect a response.
2529#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
2530#[serde(untagged)]
2531#[expect(clippy::large_enum_variant)]
2532#[schemars(inline)]
2533#[non_exhaustive]
2534pub enum AgentNotification {
2535 /// Handles session update notifications from the agent.
2536 ///
2537 /// This is a notification endpoint (no response expected) that receives
2538 /// real-time updates about session progress, including message chunks,
2539 /// tool calls, and execution plans.
2540 ///
2541 /// Note: Clients SHOULD continue accepting tool call updates even after
2542 /// sending a `session/cancel` notification, as the agent may send final
2543 /// updates before responding with the cancelled stop reason.
2544 ///
2545 /// See protocol docs: [Agent Reports Output](https://agentclientprotocol.com/protocol/prompt-turn#3-agent-reports-output)
2546 SessionNotification(SessionNotification),
2547 /// **UNSTABLE**
2548 ///
2549 /// This capability is not part of the spec yet, and may be removed or changed at any point.
2550 ///
2551 /// Notification that a URL-based elicitation has completed.
2552 #[cfg(feature = "unstable_elicitation")]
2553 CompleteElicitationNotification(CompleteElicitationNotification),
2554 /// **UNSTABLE**
2555 ///
2556 /// This capability is not part of the spec yet, and may be removed or changed at any point.
2557 ///
2558 /// Receives an MCP-over-ACP notification.
2559 #[cfg(feature = "unstable_mcp_over_acp")]
2560 MessageMcpNotification(MessageMcpNotification),
2561 /// Handles extension notifications from the agent.
2562 ///
2563 /// Allows the Agent to send an arbitrary notification that is not part of the ACP spec.
2564 /// Extension notifications provide a way to send one-way messages for custom functionality
2565 /// while maintaining protocol compatibility.
2566 ///
2567 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2568 ExtNotification(ExtNotification),
2569}
2570
2571impl AgentNotification {
2572 /// Returns the corresponding method name of the notification.
2573 #[must_use]
2574 pub fn method(&self) -> &str {
2575 match self {
2576 Self::SessionNotification(_) => CLIENT_METHOD_NAMES.session_update,
2577 #[cfg(feature = "unstable_elicitation")]
2578 Self::CompleteElicitationNotification(_) => CLIENT_METHOD_NAMES.elicitation_complete,
2579 #[cfg(feature = "unstable_mcp_over_acp")]
2580 Self::MessageMcpNotification(_) => CLIENT_METHOD_NAMES.mcp_message,
2581 Self::ExtNotification(ext_notification) => &ext_notification.method,
2582 }
2583 }
2584}
2585
2586#[cfg(test)]
2587mod tests {
2588 use super::*;
2589
2590 #[test]
2591 fn test_client_capabilities_default_on_malformed_values() {
2592 use serde_json::json;
2593
2594 let capabilities: ClientCapabilities = serde_json::from_value(json!({
2595 "fs": {
2596 "readTextFile": "yes",
2597 "writeTextFile": true
2598 },
2599 "terminal": {}
2600 }))
2601 .unwrap();
2602
2603 assert!(!capabilities.fs.read_text_file);
2604 assert!(capabilities.fs.write_text_file);
2605 assert!(!capabilities.terminal);
2606
2607 let capabilities: ClientCapabilities = serde_json::from_value(json!({
2608 "fs": false
2609 }))
2610 .unwrap();
2611 assert_eq!(capabilities.fs, FileSystemCapabilities::default());
2612
2613 #[cfg(feature = "unstable_auth_methods")]
2614 {
2615 let capabilities: ClientCapabilities = serde_json::from_value(json!({
2616 "auth": false
2617 }))
2618 .unwrap();
2619 assert_eq!(capabilities.auth, AuthCapabilities::default());
2620
2621 let capabilities: AuthCapabilities = serde_json::from_value(json!({
2622 "terminal": {}
2623 }))
2624 .unwrap();
2625 assert!(!capabilities.terminal);
2626 }
2627 }
2628
2629 #[test]
2630 fn test_serialization_behavior() {
2631 use serde_json::json;
2632
2633 assert_eq!(
2634 serde_json::from_value::<SessionInfoUpdate>(json!({})).unwrap(),
2635 SessionInfoUpdate {
2636 title: MaybeUndefined::Undefined,
2637 updated_at: MaybeUndefined::Undefined,
2638 meta: None
2639 }
2640 );
2641 assert_eq!(
2642 serde_json::from_value::<SessionInfoUpdate>(json!({"title": null, "updatedAt": null}))
2643 .unwrap(),
2644 SessionInfoUpdate {
2645 title: MaybeUndefined::Null,
2646 updated_at: MaybeUndefined::Null,
2647 meta: None
2648 }
2649 );
2650 assert_eq!(
2651 serde_json::from_value::<SessionInfoUpdate>(
2652 json!({"title": "title", "updatedAt": "timestamp"})
2653 )
2654 .unwrap(),
2655 SessionInfoUpdate {
2656 title: MaybeUndefined::Value("title".to_string()),
2657 updated_at: MaybeUndefined::Value("timestamp".to_string()),
2658 meta: None
2659 }
2660 );
2661
2662 assert_eq!(
2663 serde_json::to_value(SessionInfoUpdate::new()).unwrap(),
2664 json!({})
2665 );
2666 assert_eq!(
2667 serde_json::to_value(SessionInfoUpdate::new().title("title")).unwrap(),
2668 json!({"title": "title"})
2669 );
2670 assert_eq!(
2671 serde_json::to_value(SessionInfoUpdate::new().title(None)).unwrap(),
2672 json!({"title": null})
2673 );
2674 assert_eq!(
2675 serde_json::to_value(
2676 SessionInfoUpdate::new()
2677 .title("title")
2678 .title(MaybeUndefined::Undefined)
2679 )
2680 .unwrap(),
2681 json!({})
2682 );
2683 }
2684
2685 #[test]
2686 fn test_content_chunk_message_id_serialization() {
2687 use serde_json::json;
2688
2689 assert_eq!(
2690 serde_json::to_value(SessionUpdate::AgentMessageChunk(ContentChunk::new(
2691 ContentBlock::Text(crate::v1::TextContent::new("Hello"))
2692 )))
2693 .unwrap(),
2694 json!({
2695 "sessionUpdate": "agent_message_chunk",
2696 "content": {
2697 "type": "text",
2698 "text": "Hello"
2699 }
2700 })
2701 );
2702
2703 assert_eq!(
2704 serde_json::to_value(SessionUpdate::AgentMessageChunk(
2705 ContentChunk::new(ContentBlock::Text(crate::v1::TextContent::new("Hello")))
2706 .message_id("msg_agent_c42b9")
2707 ))
2708 .unwrap(),
2709 json!({
2710 "sessionUpdate": "agent_message_chunk",
2711 "messageId": "msg_agent_c42b9",
2712 "content": {
2713 "type": "text",
2714 "text": "Hello"
2715 }
2716 })
2717 );
2718
2719 let SessionUpdate::AgentMessageChunk(chunk) = serde_json::from_value(json!({
2720 "sessionUpdate": "agent_message_chunk",
2721 "messageId": null,
2722 "content": {
2723 "type": "text",
2724 "text": "Hello"
2725 }
2726 }))
2727 .unwrap() else {
2728 panic!("expected agent message chunk");
2729 };
2730
2731 assert_eq!(chunk.message_id, None);
2732 }
2733
2734 #[test]
2735 fn test_usage_update_serialization() {
2736 use serde_json::json;
2737
2738 assert_eq!(
2739 serde_json::to_value(SessionUpdate::UsageUpdate(UsageUpdate::new(
2740 53_000, 200_000
2741 )))
2742 .unwrap(),
2743 json!({
2744 "sessionUpdate": "usage_update",
2745 "used": 53000,
2746 "size": 200_000
2747 })
2748 );
2749
2750 assert_eq!(
2751 serde_json::to_value(SessionUpdate::UsageUpdate(
2752 UsageUpdate::new(53_000, 200_000).cost(Cost::new(0.045, "USD"))
2753 ))
2754 .unwrap(),
2755 json!({
2756 "sessionUpdate": "usage_update",
2757 "used": 53000,
2758 "size": 200_000,
2759 "cost": {
2760 "amount": 0.045,
2761 "currency": "USD"
2762 }
2763 })
2764 );
2765
2766 let SessionUpdate::UsageUpdate(update) = serde_json::from_value(json!({
2767 "sessionUpdate": "usage_update",
2768 "used": 53000,
2769 "size": 200_000,
2770 "cost": null
2771 }))
2772 .unwrap() else {
2773 panic!("expected usage update");
2774 };
2775
2776 assert_eq!(update.cost, None);
2777 }
2778
2779 #[cfg(feature = "unstable_nes")]
2780 #[test]
2781 fn test_client_capabilities_position_encodings_serialization() {
2782 use serde_json::json;
2783
2784 let capabilities = ClientCapabilities::new().position_encodings(vec![
2785 PositionEncodingKind::Utf32,
2786 PositionEncodingKind::Utf16,
2787 ]);
2788 let json = serde_json::to_value(&capabilities).unwrap();
2789
2790 assert_eq!(json["positionEncodings"], json!(["utf-32", "utf-16"]));
2791 }
2792
2793 #[cfg(feature = "unstable_boolean_config")]
2794 #[test]
2795 fn test_client_capabilities_boolean_config_options_serialization() {
2796 use serde_json::json;
2797
2798 let capabilities = ClientCapabilities::new().session(
2799 ClientSessionCapabilities::new().config_options(
2800 SessionConfigOptionsCapabilities::new()
2801 .boolean(BooleanConfigOptionCapabilities::new()),
2802 ),
2803 );
2804 let json = serde_json::to_value(&capabilities).unwrap();
2805
2806 assert_eq!(json["session"]["configOptions"]["boolean"], json!({}));
2807
2808 let omitted: ClientCapabilities = serde_json::from_value(json!({})).unwrap();
2809 assert!(omitted.session.is_none());
2810
2811 let null_session: ClientCapabilities = serde_json::from_value(json!({
2812 "session": null
2813 }))
2814 .unwrap();
2815 assert!(null_session.session.is_none());
2816
2817 let null_config_options: ClientCapabilities = serde_json::from_value(json!({
2818 "session": {
2819 "configOptions": null
2820 }
2821 }))
2822 .unwrap();
2823 assert!(
2824 null_config_options
2825 .session
2826 .and_then(|session| session.config_options)
2827 .is_none()
2828 );
2829
2830 let null_boolean: ClientCapabilities = serde_json::from_value(json!({
2831 "session": {
2832 "configOptions": {
2833 "boolean": null
2834 }
2835 }
2836 }))
2837 .unwrap();
2838 assert!(
2839 null_boolean
2840 .session
2841 .and_then(|session| session.config_options)
2842 .and_then(|config_options| config_options.boolean)
2843 .is_none()
2844 );
2845 }
2846
2847 #[cfg(feature = "unstable_plan_operations")]
2848 #[test]
2849 fn test_plan_operations_serialization() {
2850 use serde_json::json;
2851
2852 use crate::v1::{PlanEntry, PlanEntryPriority, PlanEntryStatus, PlanUpdateContent};
2853
2854 let plan_update = SessionUpdate::PlanUpdate(PlanUpdate::new(PlanUpdateContent::items(
2855 "plan-1",
2856 vec![PlanEntry::new(
2857 "Step 1",
2858 PlanEntryPriority::High,
2859 PlanEntryStatus::Pending,
2860 )],
2861 )));
2862
2863 assert_eq!(
2864 serde_json::to_value(plan_update).unwrap(),
2865 json!({
2866 "sessionUpdate": "plan_update",
2867 "plan": {
2868 "type": "items",
2869 "id": "plan-1",
2870 "entries": [
2871 {
2872 "content": "Step 1",
2873 "priority": "high",
2874 "status": "pending"
2875 }
2876 ]
2877 }
2878 })
2879 );
2880
2881 assert_eq!(
2882 serde_json::to_value(SessionUpdate::PlanRemoved(PlanRemoved::new("plan-1"))).unwrap(),
2883 json!({
2884 "sessionUpdate": "plan_removed",
2885 "id": "plan-1"
2886 })
2887 );
2888
2889 let capabilities = ClientCapabilities::new().plan(PlanCapabilities::new());
2890 let json = serde_json::to_value(&capabilities).unwrap();
2891 assert_eq!(json["plan"], json!({}));
2892
2893 assert_eq!(
2894 serde_json::from_value::<ClientCapabilities>(json!({ "plan": null }))
2895 .unwrap()
2896 .plan,
2897 None
2898 );
2899 }
2900
2901 #[cfg(feature = "unstable_mcp_over_acp")]
2902 #[test]
2903 fn test_agent_mcp_request_method_names() {
2904 use serde_json::json;
2905
2906 let params: serde_json::Map<String, serde_json::Value> =
2907 [("cursor".to_string(), json!("abc"))].into_iter().collect();
2908
2909 assert_eq!(CLIENT_METHOD_NAMES.mcp_connect, "mcp/connect");
2910 assert_eq!(CLIENT_METHOD_NAMES.mcp_message, "mcp/message");
2911 assert_eq!(CLIENT_METHOD_NAMES.mcp_disconnect, "mcp/disconnect");
2912
2913 assert_eq!(
2914 AgentRequest::ConnectMcpRequest(ConnectMcpRequest::new("server-1")).method(),
2915 "mcp/connect"
2916 );
2917 assert_eq!(
2918 AgentRequest::MessageMcpRequest(MessageMcpRequest::new("conn-1", "tools/list"))
2919 .method(),
2920 "mcp/message"
2921 );
2922 assert_eq!(
2923 AgentRequest::DisconnectMcpRequest(DisconnectMcpRequest::new("conn-1")).method(),
2924 "mcp/disconnect"
2925 );
2926 assert_eq!(
2927 AgentNotification::MessageMcpNotification(MessageMcpNotification::new(
2928 "conn-1",
2929 "notifications/progress"
2930 ))
2931 .method(),
2932 "mcp/message"
2933 );
2934
2935 assert_eq!(
2936 serde_json::to_value(ConnectMcpRequest::new("server-1")).unwrap(),
2937 json!({ "acpId": "server-1" })
2938 );
2939 assert_eq!(
2940 serde_json::to_value(ConnectMcpResponse::new("conn-1")).unwrap(),
2941 json!({ "connectionId": "conn-1" })
2942 );
2943 assert_eq!(
2944 serde_json::to_value(MessageMcpRequest::new("conn-1", "tools/list").params(params))
2945 .unwrap(),
2946 json!({
2947 "connectionId": "conn-1",
2948 "method": "tools/list",
2949 "params": { "cursor": "abc" }
2950 })
2951 );
2952 assert_eq!(
2953 serde_json::to_value(DisconnectMcpRequest::new("conn-1")).unwrap(),
2954 json!({ "connectionId": "conn-1" })
2955 );
2956 assert_eq!(
2957 serde_json::to_value(MessageMcpNotification::new(
2958 "conn-1",
2959 "notifications/progress"
2960 ))
2961 .unwrap(),
2962 json!({
2963 "connectionId": "conn-1",
2964 "method": "notifications/progress"
2965 })
2966 );
2967
2968 let request_with_null_params: MessageMcpRequest = serde_json::from_value(json!({
2969 "connectionId": "conn-1",
2970 "method": "tools/list",
2971 "params": null
2972 }))
2973 .unwrap();
2974 assert_eq!(request_with_null_params.params, None);
2975 }
2976}