diff --git a/.gitignore b/.gitignore index fac65dd9..5e93ca7d 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,8 @@ typescript/*.js.map # TypeDoc generated documentation typescript/docs/ + +.agents +.kiro +.claude + diff --git a/Cargo.toml b/Cargo.toml index ff0761ac..2ff641af 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,7 @@ unstable = [ "unstable_elicitation", "unstable_llm_providers", "unstable_logout", + "unstable_mcp_over_acp", "unstable_nes", "unstable_session_additional_directories", "unstable_session_fork", @@ -38,6 +39,7 @@ unstable_cancel_request = [] unstable_elicitation = [] unstable_llm_providers = [] unstable_logout = [] +unstable_mcp_over_acp = [] unstable_nes = [] unstable_session_additional_directories = [] unstable_session_fork = [] diff --git a/docs/protocol/draft/schema-v2.mdx b/docs/protocol/draft/schema-v2.mdx index b97b07c3..0450ceb6 100644 --- a/docs/protocol/draft/schema-v2.mdx +++ b/docs/protocol/draft/schema-v2.mdx @@ -309,7 +309,7 @@ See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/exte AgentCapabilities} > Capabilities supported by the agent. - - Default: `{"auth":{},"loadSession":false,"mcpCapabilities":{"http":false,"sse":false},"promptCapabilities":{"audio":false,"embeddedContext":false,"image":false},"sessionCapabilities":{}}` + - Default: `{"auth":{},"loadSession":false,"mcpCapabilities":{"acp":false,"http":false,"sse":false},"promptCapabilities":{"audio":false,"embeddedContext":false,"image":false},"sessionCapabilities":{}}` Implementation | null} > @@ -2491,7 +2491,7 @@ Authentication-related capabilities supported by the agent. McpCapabilities} > MCP capabilities supported by the agent. - - Default: `{"http":false,"sse":false}` + - Default: `{"acp":false,"http":false,"sse":false}` NesCapabilities | null} > @@ -4367,6 +4367,16 @@ these keys. See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + + + **UNSTABLE** + +This capability is not part of the spec yet, and may be removed or changed at any point. + +Agent supports `McpServer::Acp`. + + - Default: `false` + Agent supports `McpServer::Http`. @@ -4454,6 +4464,43 @@ See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/exte + +**UNSTABLE** + +This capability is not part of the spec yet, and may be removed or changed at any point. + +ACP transport configuration + +Only available when the Agent capabilities indicate `mcp_capabilities.acp` is `true`. +The MCP server is provided by an ACP component and communicates over the ACP channel. + + + + + The _meta property is reserved by ACP to allow clients and agents to attach additional +metadata to their interactions. Implementations MUST NOT make assumptions about values at +these keys. + +See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + + +McpServerAcpId} required> + Unique identifier for this MCP server, generated by the component providing it. + +Providers MUST NOT reuse an ID for multiple ACP-transport MCP servers that are visible +on the same ACP connection. + + + + Human-readable name identifying this MCP server. + + + The discriminator value. Must be `"acp"`. + + + + + Stdio transport configuration @@ -4485,6 +4532,54 @@ See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/exte +## McpServerAcp + +**UNSTABLE** + +This capability is not part of the spec yet, and may be removed or changed at any point. + +ACP transport configuration for MCP. + +The MCP server is provided by an ACP component and communicates over the ACP channel +using `mcp/connect`, `mcp/message`, and `mcp/disconnect`. + +**Type:** Object + +**Properties:** + + + The _meta property is reserved by ACP to allow clients and agents to attach additional +metadata to their interactions. Implementations MUST NOT make assumptions about values at +these keys. + +See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + + +McpServerAcpId} required> + Unique identifier for this MCP server, generated by the component providing it. + +Providers MUST NOT reuse an ID for multiple ACP-transport MCP servers that are visible +on the same ACP connection. + + + + Human-readable name identifying this MCP server. + + +## McpServerAcpId + +**UNSTABLE** + +This capability is not part of the spec yet, and may be removed or changed at any point. + +Unique identifier for an MCP server using the ACP transport. + +The value is opaque and generated by the ACP component providing the MCP server. It is +used by `mcp/connect` to route connection requests back to the component that declared the +server. + +**Type:** `string` + ## McpServerHttp HTTP transport configuration for MCP. diff --git a/docs/protocol/draft/schema.mdx b/docs/protocol/draft/schema.mdx index b97b07c3..0450ceb6 100644 --- a/docs/protocol/draft/schema.mdx +++ b/docs/protocol/draft/schema.mdx @@ -309,7 +309,7 @@ See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/exte AgentCapabilities} > Capabilities supported by the agent. - - Default: `{"auth":{},"loadSession":false,"mcpCapabilities":{"http":false,"sse":false},"promptCapabilities":{"audio":false,"embeddedContext":false,"image":false},"sessionCapabilities":{}}` + - Default: `{"auth":{},"loadSession":false,"mcpCapabilities":{"acp":false,"http":false,"sse":false},"promptCapabilities":{"audio":false,"embeddedContext":false,"image":false},"sessionCapabilities":{}}` Implementation | null} > @@ -2491,7 +2491,7 @@ Authentication-related capabilities supported by the agent. McpCapabilities} > MCP capabilities supported by the agent. - - Default: `{"http":false,"sse":false}` + - Default: `{"acp":false,"http":false,"sse":false}` NesCapabilities | null} > @@ -4367,6 +4367,16 @@ these keys. See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + + + **UNSTABLE** + +This capability is not part of the spec yet, and may be removed or changed at any point. + +Agent supports `McpServer::Acp`. + + - Default: `false` + Agent supports `McpServer::Http`. @@ -4454,6 +4464,43 @@ See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/exte + +**UNSTABLE** + +This capability is not part of the spec yet, and may be removed or changed at any point. + +ACP transport configuration + +Only available when the Agent capabilities indicate `mcp_capabilities.acp` is `true`. +The MCP server is provided by an ACP component and communicates over the ACP channel. + + + + + The _meta property is reserved by ACP to allow clients and agents to attach additional +metadata to their interactions. Implementations MUST NOT make assumptions about values at +these keys. + +See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + + +McpServerAcpId} required> + Unique identifier for this MCP server, generated by the component providing it. + +Providers MUST NOT reuse an ID for multiple ACP-transport MCP servers that are visible +on the same ACP connection. + + + + Human-readable name identifying this MCP server. + + + The discriminator value. Must be `"acp"`. + + + + + Stdio transport configuration @@ -4485,6 +4532,54 @@ See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/exte +## McpServerAcp + +**UNSTABLE** + +This capability is not part of the spec yet, and may be removed or changed at any point. + +ACP transport configuration for MCP. + +The MCP server is provided by an ACP component and communicates over the ACP channel +using `mcp/connect`, `mcp/message`, and `mcp/disconnect`. + +**Type:** Object + +**Properties:** + + + The _meta property is reserved by ACP to allow clients and agents to attach additional +metadata to their interactions. Implementations MUST NOT make assumptions about values at +these keys. + +See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + + +McpServerAcpId} required> + Unique identifier for this MCP server, generated by the component providing it. + +Providers MUST NOT reuse an ID for multiple ACP-transport MCP servers that are visible +on the same ACP connection. + + + + Human-readable name identifying this MCP server. + + +## McpServerAcpId + +**UNSTABLE** + +This capability is not part of the spec yet, and may be removed or changed at any point. + +Unique identifier for an MCP server using the ACP transport. + +The value is opaque and generated by the ACP component providing the MCP server. It is +used by `mcp/connect` to route connection requests back to the component that declared the +server. + +**Type:** `string` + ## McpServerHttp HTTP transport configuration for MCP. diff --git a/schema/schema.unstable.json b/schema/schema.unstable.json index b304602c..b419997a 100644 --- a/schema/schema.unstable.json +++ b/schema/schema.unstable.json @@ -77,6 +77,7 @@ } ], "default": { + "acp": false, "http": false, "sse": false }, @@ -2942,6 +2943,7 @@ "auth": {}, "loadSession": false, "mcpCapabilities": { + "acp": false, "http": false, "sse": false }, @@ -3304,6 +3306,11 @@ "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", "type": ["object", "null"] }, + "acp": { + "default": false, + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nAgent supports [`McpServer::Acp`].", + "type": "boolean" + }, "http": { "default": false, "description": "Agent supports [`McpServer::Http`].", @@ -3351,6 +3358,22 @@ "required": ["type"], "type": "object" }, + { + "allOf": [ + { + "$ref": "#/$defs/McpServerAcp" + } + ], + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nACP transport configuration\n\nOnly available when the Agent capabilities indicate `mcp_capabilities.acp` is `true`.\nThe MCP server is provided by an ACP component and communicates over the ACP channel.", + "properties": { + "type": { + "const": "acp", + "type": "string" + } + }, + "required": ["type"], + "type": "object" + }, { "allOf": [ { @@ -3363,6 +3386,34 @@ ], "description": "Configuration for connecting to an MCP (Model Context Protocol) server.\n\nMCP servers provide tools and context that the agent can use when\nprocessing prompts.\n\nSee protocol docs: [MCP Servers](https://agentclientprotocol.com/protocol/session-setup#mcp-servers)" }, + "McpServerAcp": { + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nACP transport configuration for MCP.\n\nThe MCP server is provided by an ACP component and communicates over the ACP channel\nusing `mcp/connect`, `mcp/message`, and `mcp/disconnect`.", + "properties": { + "_meta": { + "additionalProperties": true, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": ["object", "null"] + }, + "id": { + "allOf": [ + { + "$ref": "#/$defs/McpServerAcpId" + } + ], + "description": "Unique identifier for this MCP server, generated by the component providing it.\n\nProviders MUST NOT reuse an ID for multiple ACP-transport MCP servers that are visible\non the same ACP connection." + }, + "name": { + "description": "Human-readable name identifying this MCP server.", + "type": "string" + } + }, + "required": ["name", "id"], + "type": "object" + }, + "McpServerAcpId": { + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nUnique identifier for an MCP server using the ACP transport.\n\nThe value is opaque and generated by the ACP component providing the MCP server. It is\nused by `mcp/connect` to route connection requests back to the component that declared the\nserver.", + "type": "string" + }, "McpServerHttp": { "description": "HTTP transport configuration for MCP.", "properties": { diff --git a/schema/schema.v2.unstable.json b/schema/schema.v2.unstable.json index b304602c..b419997a 100644 --- a/schema/schema.v2.unstable.json +++ b/schema/schema.v2.unstable.json @@ -77,6 +77,7 @@ } ], "default": { + "acp": false, "http": false, "sse": false }, @@ -2942,6 +2943,7 @@ "auth": {}, "loadSession": false, "mcpCapabilities": { + "acp": false, "http": false, "sse": false }, @@ -3304,6 +3306,11 @@ "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", "type": ["object", "null"] }, + "acp": { + "default": false, + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nAgent supports [`McpServer::Acp`].", + "type": "boolean" + }, "http": { "default": false, "description": "Agent supports [`McpServer::Http`].", @@ -3351,6 +3358,22 @@ "required": ["type"], "type": "object" }, + { + "allOf": [ + { + "$ref": "#/$defs/McpServerAcp" + } + ], + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nACP transport configuration\n\nOnly available when the Agent capabilities indicate `mcp_capabilities.acp` is `true`.\nThe MCP server is provided by an ACP component and communicates over the ACP channel.", + "properties": { + "type": { + "const": "acp", + "type": "string" + } + }, + "required": ["type"], + "type": "object" + }, { "allOf": [ { @@ -3363,6 +3386,34 @@ ], "description": "Configuration for connecting to an MCP (Model Context Protocol) server.\n\nMCP servers provide tools and context that the agent can use when\nprocessing prompts.\n\nSee protocol docs: [MCP Servers](https://agentclientprotocol.com/protocol/session-setup#mcp-servers)" }, + "McpServerAcp": { + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nACP transport configuration for MCP.\n\nThe MCP server is provided by an ACP component and communicates over the ACP channel\nusing `mcp/connect`, `mcp/message`, and `mcp/disconnect`.", + "properties": { + "_meta": { + "additionalProperties": true, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": ["object", "null"] + }, + "id": { + "allOf": [ + { + "$ref": "#/$defs/McpServerAcpId" + } + ], + "description": "Unique identifier for this MCP server, generated by the component providing it.\n\nProviders MUST NOT reuse an ID for multiple ACP-transport MCP servers that are visible\non the same ACP connection." + }, + "name": { + "description": "Human-readable name identifying this MCP server.", + "type": "string" + } + }, + "required": ["name", "id"], + "type": "object" + }, + "McpServerAcpId": { + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nUnique identifier for an MCP server using the ACP transport.\n\nThe value is opaque and generated by the ACP component providing the MCP server. It is\nused by `mcp/connect` to route connection requests back to the component that declared the\nserver.", + "type": "string" + }, "McpServerHttp": { "description": "HTTP transport configuration for MCP.", "properties": { diff --git a/src/v1/agent.rs b/src/v1/agent.rs index 00498888..cd59e5fa 100644 --- a/src/v1/agent.rs +++ b/src/v1/agent.rs @@ -2689,6 +2689,16 @@ pub enum McpServer { /// /// Only available when the Agent capabilities indicate `mcp_capabilities.sse` is `true`. Sse(McpServerSse), + /// **UNSTABLE** + /// + /// This capability is not part of the spec yet, and may be removed or changed at any point. + /// + /// ACP transport configuration + /// + /// Only available when the Agent capabilities indicate `mcp_capabilities.acp` is `true`. + /// The MCP server is provided by an ACP component and communicates over the ACP channel. + #[cfg(feature = "unstable_mcp_over_acp")] + Acp(McpServerAcp), /// Stdio transport configuration /// /// All Agents MUST support this transport. @@ -2798,6 +2808,83 @@ impl McpServerSse { } } +/// **UNSTABLE** +/// +/// This capability is not part of the spec yet, and may be removed or changed at any point. +/// +/// Unique identifier for an MCP server using the ACP transport. +/// +/// The value is opaque and generated by the ACP component providing the MCP server. It is +/// used by `mcp/connect` to route connection requests back to the component that declared the +/// server. +#[cfg(feature = "unstable_mcp_over_acp")] +#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, Display, From)] +#[serde(transparent)] +#[from(Arc, String, &'static str)] +#[non_exhaustive] +pub struct McpServerAcpId(pub Arc); + +#[cfg(feature = "unstable_mcp_over_acp")] +impl McpServerAcpId { + #[must_use] + pub fn new(id: impl Into>) -> Self { + Self(id.into()) + } +} + +/// **UNSTABLE** +/// +/// This capability is not part of the spec yet, and may be removed or changed at any point. +/// +/// ACP transport configuration for MCP. +/// +/// The MCP server is provided by an ACP component and communicates over the ACP channel +/// using `mcp/connect`, `mcp/message`, and `mcp/disconnect`. +#[skip_serializing_none] +#[cfg(feature = "unstable_mcp_over_acp")] +#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +#[non_exhaustive] +pub struct McpServerAcp { + /// Human-readable name identifying this MCP server. + pub name: String, + /// Unique identifier for this MCP server, generated by the component providing it. + /// + /// Providers MUST NOT reuse an ID for multiple ACP-transport MCP servers that are visible + /// on the same ACP connection. + pub id: McpServerAcpId, + /// The _meta property is reserved by ACP to allow clients and agents to attach additional + /// metadata to their interactions. Implementations MUST NOT make assumptions about values at + /// these keys. + /// + /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + #[serde(rename = "_meta")] + pub meta: Option, +} + +#[cfg(feature = "unstable_mcp_over_acp")] +impl McpServerAcp { + #[must_use] + pub fn new(name: impl Into, id: impl Into) -> Self { + Self { + name: name.into(), + id: id.into(), + meta: None, + } + } + + /// The _meta property is reserved by ACP to allow clients and agents to attach additional + /// metadata to their interactions. Implementations MUST NOT make assumptions about values at + /// these keys. + /// + /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + #[must_use] + pub fn meta(mut self, meta: impl IntoOption) -> Self { + self.meta = meta.into_option(); + self + } +} + /// Stdio transport configuration for MCP. #[skip_serializing_none] #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] @@ -4427,6 +4514,14 @@ pub struct McpCapabilities { /// Agent supports [`McpServer::Sse`]. #[serde(default)] pub sse: bool, + /// **UNSTABLE** + /// + /// This capability is not part of the spec yet, and may be removed or changed at any point. + /// + /// Agent supports [`McpServer::Acp`]. + #[cfg(feature = "unstable_mcp_over_acp")] + #[serde(default)] + pub acp: bool, /// The _meta property is reserved by ACP to allow clients and agents to attach additional /// metadata to their interactions. Implementations MUST NOT make assumptions about values at /// these keys. @@ -4456,6 +4551,18 @@ impl McpCapabilities { self } + /// **UNSTABLE** + /// + /// This capability is not part of the spec yet, and may be removed or changed at any point. + /// + /// Agent supports [`McpServer::Acp`]. + #[cfg(feature = "unstable_mcp_over_acp")] + #[must_use] + pub fn acp(mut self, acp: bool) -> Self { + self.acp = acp; + self + } + /// The _meta property is reserved by ACP to allow clients and agents to attach additional /// metadata to their interactions. Implementations MUST NOT make assumptions about values at /// these keys. @@ -5137,6 +5244,84 @@ mod test_serialization { } } + #[cfg(feature = "unstable_mcp_over_acp")] + #[test] + fn test_mcp_server_acp_serialization() { + let server = McpServer::Acp(McpServerAcp::new("project-tools", "project-tools-id")); + + let json = serde_json::to_value(&server).unwrap(); + assert_eq!( + json, + json!({ + "type": "acp", + "name": "project-tools", + "id": "project-tools-id" + }) + ); + + let deserialized: McpServer = serde_json::from_value(json).unwrap(); + match deserialized { + McpServer::Acp(McpServerAcp { name, id, meta: _ }) => { + assert_eq!(name, "project-tools"); + assert_eq!(id, McpServerAcpId::new("project-tools-id")); + } + _ => panic!("Expected Acp variant"), + } + } + + #[cfg(feature = "unstable_mcp_over_acp")] + #[test] + fn test_mcp_server_acp_schema() { + let mcp_server_schema = serde_json::to_value(schemars::schema_for!(McpServer)).unwrap(); + assert!(json_contains_entry( + &mcp_server_schema, + "const", + &json!("acp") + )); + assert!(json_contains_entry( + &mcp_server_schema, + "$ref", + &json!("#/$defs/McpServerAcp") + )); + + let capabilities_schema = + serde_json::to_value(schemars::schema_for!(McpCapabilities)).unwrap(); + assert!(json_contains_key(&capabilities_schema, "acp")); + } + + #[cfg(feature = "unstable_mcp_over_acp")] + fn json_contains_entry( + value: &serde_json::Value, + key: &str, + expected: &serde_json::Value, + ) -> bool { + match value { + serde_json::Value::Object(map) => { + map.get(key) == Some(expected) + || map + .values() + .any(|value| json_contains_entry(value, key, expected)) + } + serde_json::Value::Array(values) => values + .iter() + .any(|value| json_contains_entry(value, key, expected)), + _ => false, + } + } + + #[cfg(feature = "unstable_mcp_over_acp")] + fn json_contains_key(value: &serde_json::Value, key: &str) -> bool { + match value { + serde_json::Value::Object(map) => { + map.contains_key(key) || map.values().any(|value| json_contains_key(value, key)) + } + serde_json::Value::Array(values) => { + values.iter().any(|value| json_contains_key(value, key)) + } + _ => false, + } + } + #[test] fn test_mcp_server_sse_serialization() { let server = McpServer::Sse( diff --git a/src/v2/agent.rs b/src/v2/agent.rs index e7322fd6..a6e8210d 100644 --- a/src/v2/agent.rs +++ b/src/v2/agent.rs @@ -2689,6 +2689,16 @@ pub enum McpServer { /// /// Only available when the Agent capabilities indicate `mcp_capabilities.sse` is `true`. Sse(McpServerSse), + /// **UNSTABLE** + /// + /// This capability is not part of the spec yet, and may be removed or changed at any point. + /// + /// ACP transport configuration + /// + /// Only available when the Agent capabilities indicate `mcp_capabilities.acp` is `true`. + /// The MCP server is provided by an ACP component and communicates over the ACP channel. + #[cfg(feature = "unstable_mcp_over_acp")] + Acp(McpServerAcp), /// Stdio transport configuration /// /// All Agents MUST support this transport. @@ -2798,6 +2808,83 @@ impl McpServerSse { } } +/// **UNSTABLE** +/// +/// This capability is not part of the spec yet, and may be removed or changed at any point. +/// +/// Unique identifier for an MCP server using the ACP transport. +/// +/// The value is opaque and generated by the ACP component providing the MCP server. It is +/// used by `mcp/connect` to route connection requests back to the component that declared the +/// server. +#[cfg(feature = "unstable_mcp_over_acp")] +#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, Display, From)] +#[serde(transparent)] +#[from(Arc, String, &'static str)] +#[non_exhaustive] +pub struct McpServerAcpId(pub Arc); + +#[cfg(feature = "unstable_mcp_over_acp")] +impl McpServerAcpId { + #[must_use] + pub fn new(id: impl Into>) -> Self { + Self(id.into()) + } +} + +/// **UNSTABLE** +/// +/// This capability is not part of the spec yet, and may be removed or changed at any point. +/// +/// ACP transport configuration for MCP. +/// +/// The MCP server is provided by an ACP component and communicates over the ACP channel +/// using `mcp/connect`, `mcp/message`, and `mcp/disconnect`. +#[skip_serializing_none] +#[cfg(feature = "unstable_mcp_over_acp")] +#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +#[non_exhaustive] +pub struct McpServerAcp { + /// Human-readable name identifying this MCP server. + pub name: String, + /// Unique identifier for this MCP server, generated by the component providing it. + /// + /// Providers MUST NOT reuse an ID for multiple ACP-transport MCP servers that are visible + /// on the same ACP connection. + pub id: McpServerAcpId, + /// The _meta property is reserved by ACP to allow clients and agents to attach additional + /// metadata to their interactions. Implementations MUST NOT make assumptions about values at + /// these keys. + /// + /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + #[serde(rename = "_meta")] + pub meta: Option, +} + +#[cfg(feature = "unstable_mcp_over_acp")] +impl McpServerAcp { + #[must_use] + pub fn new(name: impl Into, id: impl Into) -> Self { + Self { + name: name.into(), + id: id.into(), + meta: None, + } + } + + /// The _meta property is reserved by ACP to allow clients and agents to attach additional + /// metadata to their interactions. Implementations MUST NOT make assumptions about values at + /// these keys. + /// + /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + #[must_use] + pub fn meta(mut self, meta: impl IntoOption) -> Self { + self.meta = meta.into_option(); + self + } +} + /// Stdio transport configuration for MCP. #[skip_serializing_none] #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] @@ -4427,6 +4514,14 @@ pub struct McpCapabilities { /// Agent supports [`McpServer::Sse`]. #[serde(default)] pub sse: bool, + /// **UNSTABLE** + /// + /// This capability is not part of the spec yet, and may be removed or changed at any point. + /// + /// Agent supports [`McpServer::Acp`]. + #[cfg(feature = "unstable_mcp_over_acp")] + #[serde(default)] + pub acp: bool, /// The _meta property is reserved by ACP to allow clients and agents to attach additional /// metadata to their interactions. Implementations MUST NOT make assumptions about values at /// these keys. @@ -4456,6 +4551,18 @@ impl McpCapabilities { self } + /// **UNSTABLE** + /// + /// This capability is not part of the spec yet, and may be removed or changed at any point. + /// + /// Agent supports [`McpServer::Acp`]. + #[cfg(feature = "unstable_mcp_over_acp")] + #[must_use] + pub fn acp(mut self, acp: bool) -> Self { + self.acp = acp; + self + } + /// The _meta property is reserved by ACP to allow clients and agents to attach additional /// metadata to their interactions. Implementations MUST NOT make assumptions about values at /// these keys. diff --git a/src/v2/conversion.rs b/src/v2/conversion.rs index 0258578a..407d0d41 100644 --- a/src/v2/conversion.rs +++ b/src/v2/conversion.rs @@ -4053,6 +4053,8 @@ impl IntoV1 for super::McpServer { Ok(match self { Self::Http(value) => crate::v1::McpServer::Http(value.into_v1()?), Self::Sse(value) => crate::v1::McpServer::Sse(value.into_v1()?), + #[cfg(feature = "unstable_mcp_over_acp")] + Self::Acp(value) => crate::v1::McpServer::Acp(value.into_v1()?), Self::Stdio(value) => crate::v1::McpServer::Stdio(value.into_v1()?), }) } @@ -4065,6 +4067,8 @@ impl IntoV2 for crate::v1::McpServer { Ok(match self { Self::Http(value) => super::McpServer::Http(value.into_v2()?), Self::Sse(value) => super::McpServer::Sse(value.into_v2()?), + #[cfg(feature = "unstable_mcp_over_acp")] + Self::Acp(value) => super::McpServer::Acp(value.into_v2()?), Self::Stdio(value) => super::McpServer::Stdio(value.into_v2()?), }) } @@ -4146,6 +4150,52 @@ impl IntoV2 for crate::v1::McpServerSse { } } +#[cfg(feature = "unstable_mcp_over_acp")] +impl IntoV1 for super::McpServerAcpId { + type Output = crate::v1::McpServerAcpId; + + fn into_v1(self) -> Result { + Ok(crate::v1::McpServerAcpId(self.0.into_v1()?)) + } +} + +#[cfg(feature = "unstable_mcp_over_acp")] +impl IntoV2 for crate::v1::McpServerAcpId { + type Output = super::McpServerAcpId; + + fn into_v2(self) -> Result { + Ok(super::McpServerAcpId(self.0.into_v2()?)) + } +} + +#[cfg(feature = "unstable_mcp_over_acp")] +impl IntoV1 for super::McpServerAcp { + type Output = crate::v1::McpServerAcp; + + fn into_v1(self) -> Result { + let Self { name, id, meta } = self; + Ok(crate::v1::McpServerAcp { + name: name.into_v1()?, + id: id.into_v1()?, + meta: meta.into_v1()?, + }) + } +} + +#[cfg(feature = "unstable_mcp_over_acp")] +impl IntoV2 for crate::v1::McpServerAcp { + type Output = super::McpServerAcp; + + fn into_v2(self) -> Result { + let Self { name, id, meta } = self; + Ok(super::McpServerAcp { + name: name.into_v2()?, + id: id.into_v2()?, + meta: meta.into_v2()?, + }) + } +} + impl IntoV1 for super::McpServerStdio { type Output = crate::v1::McpServerStdio; @@ -5136,10 +5186,18 @@ impl IntoV1 for super::McpCapabilities { type Output = crate::v1::McpCapabilities; fn into_v1(self) -> Result { - let Self { http, sse, meta } = self; + let Self { + http, + sse, + #[cfg(feature = "unstable_mcp_over_acp")] + acp, + meta, + } = self; Ok(crate::v1::McpCapabilities { http: http.into_v1()?, sse: sse.into_v1()?, + #[cfg(feature = "unstable_mcp_over_acp")] + acp: acp.into_v1()?, meta: meta.into_v1()?, }) } @@ -5149,10 +5207,18 @@ impl IntoV2 for crate::v1::McpCapabilities { type Output = super::McpCapabilities; fn into_v2(self) -> Result { - let Self { http, sse, meta } = self; + let Self { + http, + sse, + #[cfg(feature = "unstable_mcp_over_acp")] + acp, + meta, + } = self; Ok(super::McpCapabilities { http: http.into_v2()?, sse: sse.into_v2()?, + #[cfg(feature = "unstable_mcp_over_acp")] + acp: acp.into_v2()?, meta: meta.into_v2()?, }) }