1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
//! # A2A-MCP Integration
//!
//! This crate provides **bidirectional integration** between the Agent-to-Agent (A2A) protocol
//! and the Model Context Protocol (MCP), enabling seamless communication between these protocols.
//!
//! ## Core Features
//!
//! ### 1. A2A Agents → MCP Tools (`AgentToMcpBridge`)
//!
//! Expose A2A agent skills as callable MCP tools, allowing MCP clients (like Claude Desktop)
//! to invoke A2A agent capabilities.
//!
//! ```no_run
//! use a2a_mcp::AgentToMcpBridge;
//! use a2a_rs::adapter::transport::http::HttpClient;
//! use a2a_rs::domain::AgentCard;
//! use rmcp::{transport::stdio, ServiceExt};
//!
//! #[tokio::main]
//! async fn main() -> anyhow::Result<()> {
//! // Point an A2A client at the agent's HTTP endpoint.
//! let client = HttpClient::new("https://my-agent.example.com".to_string());
//!
//! // The agent card describes the agent's skills. In a real client
//! // you'll fetch it from `/.well-known/agent-card.json`; this is a
//! // stand-in to keep the example self-contained.
//! let agent_card: AgentCard = AgentCard::builder()
//! .name("My Agent".to_string())
//! .description("Does things".to_string())
//! .url("https://my-agent.example.com".to_string())
//! .version("0.1.0".to_string())
//! .capabilities(Default::default())
//! .default_input_modes(vec!["text".to_string()])
//! .default_output_modes(vec!["text".to_string()])
//! .skills(vec![])
//! .build();
//!
//! // MCP tool names are namespaced by agent_card.url.
//! let bridge = AgentToMcpBridge::new(client, agent_card);
//!
//! // Serve as an MCP server over stdio.
//! bridge.serve(stdio()).await?.waiting().await?;
//! Ok(())
//! }
//! ```
//!
//! ### 2. MCP Tools → A2A Agents (`McpToA2ABridge`)
//!
//! Augment A2A agents with MCP tool capabilities, allowing agents to call external MCP tools
//! as part of their processing.
//!
//! ```no_run
//! use a2a_mcp::{create_tool_call_message, McpToA2ABridge};
//! use a2a_rs::domain::{error::A2AError, Message, Task};
//! use a2a_rs::port::AsyncMessageHandler;
//! use async_trait::async_trait;
//! use rmcp::{transport::stdio, ServiceExt};
//!
//! // Your existing A2A handler — the bridge wraps it so non-tool-call
//! // messages keep flowing through your normal business logic.
//! #[derive(Clone)]
//! struct MyHandler;
//!
//! #[async_trait]
//! impl AsyncMessageHandler for MyHandler {
//! async fn process_message(
//! &self,
//! _task_id: &str,
//! _message: &Message,
//! _session_id: Option<&str>,
//! ) -> Result<Task, A2AError> {
//! unimplemented!("your business logic here")
//! }
//! }
//!
//! #[tokio::main]
//! async fn main() -> anyhow::Result<()> {
//! // Connect to an MCP server. In production you'll typically use
//! // `rmcp::transport::TokioChildProcess` to spawn one; stdio works
//! // when this process is itself the MCP client end of a pipe.
//! let mcp_client = ().serve(stdio()).await?;
//!
//! // Wrap your handler so messages carrying an `a2a_rs_tool_call`
//! // metadata envelope are routed to the MCP server.
//! let bridge = McpToA2ABridge::new(mcp_client.peer().clone(), MyHandler).await?;
//!
//! // Build a tool-call message. The envelope rides in metadata, not text:
//! // metadata["a2a_rs_tool_call"] = { "name": "...", "arguments": {...} }
//! let tool_msg = create_tool_call_message("add", serde_json::json!({"a": 5, "b": 7}));
//! let _result = bridge.process_message("task-1", &tool_msg, None).await?;
//! Ok(())
//! }
//! ```
//!
//! ## Tool-call wire format
//!
//! `McpToA2ABridge` does not inspect message text. To trigger a tool call,
//! attach an [`McpToolCall`] envelope to `Message.metadata` under the
//! [`MCP_TOOL_CALL_METADATA_KEY`] key (`"a2a_rs_tool_call"`):
//!
//! ```text
//! Message {
//! role: User,
//! metadata: {
//! "a2a_rs_tool_call": { "name": "calculator_add", "arguments": {"a":5,"b":3} }
//! },
//! ...
//! }
//! ```
//!
//! Messages without this metadata key are forwarded unchanged to the inner
//! `AsyncMessageHandler`. Use [`create_tool_call_message`] or
//! [`attach_tool_call`] to construct one without touching the constant by hand.
//!
//! ## Architecture
//!
//! ```text
//! ┌─────────────────────────────────────────────────────────────┐
//! │ a2a-mcp Crate │
//! ├──────────────────────┬──────────────────────────────────────┤
//! │ Direction 1: │ Direction 2: │
//! │ A2A → MCP │ MCP → A2A │
//! ├──────────────────────┼──────────────────────────────────────┤
//! │ AgentToMcpBridge │ McpToA2ABridge │
//! │ - Wraps A2A agent │ - Wraps MCP ServerHandler │
//! │ - Implements │ - Implements AsyncMessageHandler │
//! │ ServerHandler │ - Calls MCP tools from A2A tasks │
//! │ - Maps skills to │ - Augments agents with MCP tools │
//! │ MCP tools │ │
//! └──────────────────────┴──────────────────────────────────────┘
//! ```
//!
//! ## Protocol Converters
//!
//! The crate provides transparent conversion between A2A and MCP types:
//!
//! - **Messages**: `A2A Message` ↔ `MCP Content`
//! - **Skills/Tools**: `A2A AgentSkill` ↔ `MCP Tool`
//! - **Results**: `A2A Task` ↔ `MCP CallToolResult`
// Re-export key types
pub use ;
pub use ;
pub use ;
pub use ;
/// Current crate version
pub const VERSION: &str = env!;