A2A and MCP
Let's use a simple example to explain the A2A protocol, MCP, their relationship, and how to use them.
Imagine: A Smart Team and Their Tools
Suppose you are the boss of a company with many smart "employees" (AI Agents), each with their own strengths, such as:
- Secretary Agent: Schedules meetings and manages calendars.
- Sales Agent: Communicates with clients and recommends products.
- Data Analyst Agent: Analyzes sales data and generates reports.
These Agents are very smart, but at first, they are independent and don't know what each other can do or how to collaborate. They also need to use some "tools" to get their work done, such as:
- Calendar App: For scheduling meetings.
- CRM System: For recording customer information.
- Database: For storing sales data.
- PPT Software: For generating reports.
A2A Protocol: The "Common Language" and "Collaboration Rules" Between Agents
A2A (Agent-to-Agent) protocol is like giving these smart employees a set of "common language" and "collaboration rules".
Before A2A, if the Secretary Agent wanted the Sales Agent to contact a client, they might have to agree on a "code word" or develop a custom interface for this cooperation. It's like different countries having different languages—communication requires a translator or learning a new language for each exchange.
With A2A, it's as if all Agents are trained in an "international common language" (like English) and a set of "teamwork norms".
- Agent Card: Each Agent has a "business card" or "role description" that clearly states its name, what it can do (e.g., "I can schedule meetings," "I can analyze data"), and how to contact it. This "card" is the Agent Card, allowing other Agents to quickly discover and understand its capabilities.
- Standardized Communication: A2A specifies how Agents send requests, reply, report task progress, share files, etc. It's like team members using unified meeting procedures, report templates, and file sharing methods, making collaboration smooth and efficient.
In short, the A2A protocol is a standard that allows different AI Agents to discover, understand, and collaborate with each other.
How to use the A2A protocol?
If you want to develop Agents that can collaborate, you can:
- Define an Agent Card: Create an Agent Card for your Agent, clearly stating its capabilities and interfaces.
- Follow the A2A specification: Make your Agent send and receive information according to the A2A protocol's format and process.
- Use SDKs: Many platforms provide A2A SDKs to make it easier to implement Agent-to-Agent communication.
MCP: The "Unified Interface" for Agents to Access "External Tools"
MCP (Model Context Protocol) is like giving each smart employee a "universal adapter" so they can easily connect to and use various "external tools" (like calendars, CRM, databases).
Before MCP, the Secretary Agent might need to write custom code to connect to the calendar app, and the Sales Agent would need a completely different code for the CRM system. It's like different appliances needing different plugs—very inconvenient.
With MCP, it's as if all Agents have a "USB-C port":
- Unified Interface: No matter if the external tool is a calendar, CRM, or database, Agents can call them in a unified way (e.g., JSON-RPC) via MCP.
- Context Provision: MCP can also help Agents obtain and understand the "context information" needed to use tools, such as "what time is it now," "which customer's data to query," etc.
In short, MCP allows AI Agents to use various external tools and data in a standardized, more convenient, and smarter way.
How to use MCP?
If you want your Agent to use external tools, you can:
- Create an MCP Server: Wrap your external tool's functions as MCP-understandable interfaces.
- Define Tool Capabilities: In the MCP Server, define what the tool can do, what parameters it needs, and what results it returns.
- Agent calls MCP Server: Your Agent calls the MCP Server via the MCP protocol, thus indirectly using the external tool.
The Relationship Between A2A and MCP: Close Cooperation to Complete Tasks
A2A and MCP are complementary, not competitors. They are like an excellent team:
- A2A handles "internal team collaboration": Agents communicate, assign tasks, and share progress.
- MCP handles "external interactions": Each Agent uses MCP to access various external tools, get data, or perform actions.
Imagine a scenario:
The boss (user) tells the Secretary Agent: "Please schedule a meeting next Tuesday at 2 PM for the new product launch, and invite the Sales Agent and Data Analyst Agent."
- Secretary Agent (A2A client) receives the task.
- It decides a meeting needs to be scheduled, so it calls its MCP to connect to the calendar app (an external tool).
- The Secretary Agent uses the A2A protocol to send meeting invitations to the Sales Agent and Data Analyst Agent (Agent-to-Agent communication).
- The Sales Agent and Data Analyst Agent receive the invitation and use their own MCP to check their calendars, then reply to the Secretary Agent (also via A2A).
- During the meeting, the boss may ask the Sales Agent: "How are the new product sales going?"
- The Sales Agent uses its MCP to connect to the CRM system and get customer data.
- If the Sales Agent finds the data insufficient, it uses the A2A protocol to send the data to the Data Analyst Agent for a detailed sales report.
- The Data Analyst Agent receives the data, uses its MCP to get more info from the database, and uses PPT software to generate a report.
- Finally, the Data Analyst Agent sends the report back to the Sales Agent via A2A, and the Sales Agent reports to the boss.
In summary:
- A2A protocol enables AI Agents to "talk" and "collaborate" with each other to accomplish complex tasks.
- MCP enables AI Agents to easily "use" various "tools", expanding their capabilities.
- Together, they build a powerful AI ecosystem, allowing different Agents to work together like a high-efficiency team, using various tools to solve problems.
Now, let's build a simple Python app to simulate how an AI Agent collaborates with others via A2A and uses external tools via MCP.
Scenario: Smart Meeting Assistant
Let's create a "Smart Meeting Assistant" app. In this app, we have two Agents:
- MeetingSchedulerAgent: Schedules meetings and uses a "calendar tool."
- ParticipantNotifierAgent: Notifies participants about meeting info.
A2A Protocol in Action
- Agent Discovery and Communication: The MeetingSchedulerAgent needs to know how to notify participants, so it "discovers" and calls the ParticipantNotifierAgent's capability.
- Standardized Message Passing: Agents exchange meeting info and notification requests using a simple, standardized message format.
MCP in Action
- Tool Wrapping: We'll simulate a "calendar tool" that the MeetingSchedulerAgent calls via MCP (e.g., "add event").
- Unified Interface: No matter how many external tools there are in the future, Agents can call them via similar MCP interfaces.
Example App Code
We'll use Python classes to simulate the concepts of Agent and MCP.
import json
import uuid
# --- Simulate A2A Protocol ---
class AgentCard:
"""
Simulate an A2A Agent Card, describing the Agent's capabilities.
"""
def __init__(self, agent_id, name, capabilities):
self.agent_id = agent_id
self.name = name
self.capabilities = capabilities # List of what the Agent can do
def to_json(self):
return json.dumps({
"agent_id": self.agent_id,
"name": self.name,
"capabilities": self.capabilities
}, indent=2)
class A2AMessage:
"""
Simulate an A2A message structure for Agent-to-Agent communication.
"""
def __init__(self, sender_id, receiver_id, message_type, payload):
self.message_id = str(uuid.uuid4())
self.sender_id = sender_id
self.receiver_id = receiver_id
self.message_type = message_type # e.g., 'request_schedule_meeting', 'notify_participants'
self.payload = payload # Message content
def to_json(self):
return json.dumps({
"message_id": self.message_id,
"sender_id": self.sender_id,
"receiver_id": self.receiver_id,
"message_type": self.message_type,
"payload": self.payload
}, indent=2)
# --- Simulate MCP Protocol ---
class ExternalTool:
"""
Simulate an external tool, e.g., a simple calendar app.
"""
def __init__(self, name):
self.name = name
self.calendar_events = []
def add_event(self, event_details):
print(f" [{self.name} Tool]: Received request, adding event: {event_details['title']}")
self.calendar_events.append(event_details)
print(f" [{self.name} Tool]: Event '{event_details['title']}' added.")
return {"status": "success", "event_id": str(uuid.uuid4())}
def get_events(self):
return self.calendar_events
class MCPServer:
"""
Simulate an MCP Server, exposing external tool capabilities to Agents.
"""
def __init__(self, tool):
self.tool = tool
self.available_functions = {
"add_calendar_event": self.tool.add_event,
"get_calendar_events": self.tool.get_events
}
def call_function(self, function_name, *args, **kwargs):
if function_name in self.available_functions:
print(f" [MCP Server]: Agent is calling tool function via MCP: {function_name}")
return self.available_functions[function_name](*args, **kwargs)
else:
print(f" [MCP Server]: Error: Unknown tool function '{function_name}'")
return {"status": "error", "message": "Unknown function"}
# --- Simulate Agents ---
class BaseAgent:
"""
Base class for Agents, includes Agent ID and Agent Card.
"""
def __init__(self, name, capabilities):
self.agent_id = str(uuid.uuid4())
self.name = name
self.card = AgentCard(self.agent_id, self.name, capabilities)
self.known_agents = {} # For storing known Agents (A2A discovery)
self.mcp_servers = {} # For storing MCP Server instances (MCP connections)
def register_mcp_server(self, tool_name, mcp_server):
"""Register an MCP Server to connect to an external tool"""
self.mcp_servers[tool_name] = mcp_server
print(f"Agent '{self.name}' connected to MCP Server for tool '{tool_name}'.")
def discover_agent(self, agent_card):
"""Simulate Agent discovering another Agent"""
self.known_agents[agent_card.agent_id] = agent_card
print(f"Agent '{self.name}' discovered Agent '{agent_card.name}'.")
def send_a2a_message(self, receiver_agent_id, message_type, payload):
"""Send an A2A message"""
if receiver_agent_id not in self.known_agents:
print(f"Error: Agent '{self.name}' does not know Agent ID: {receiver_agent_id}")
return None
message = A2AMessage(self.agent_id, receiver_agent_id, message_type, payload)
print(f"\n--- Agent '{self.name}' sends A2A message to '{self.known_agents[receiver_agent_id].name}' ---")
print(message.to_json())
return message
def receive_a2a_message(self, message):
"""Receive an A2A message (to be implemented by subclasses)"""
print(f"\n--- Agent '{self.name}' received A2A message ---")
print(message.to_json())
return f"Agent '{self.name}' processed message: {message.message_type}"
class MeetingSchedulerAgent(BaseAgent):
"""
Meeting Scheduler Agent, responsible for scheduling meetings and calling the calendar tool (via MCP).
"""
def __init__(self):
super().__init__("MeetingSchedulerAgent", ["schedule_meeting", "use_calendar_tool"])
def schedule_meeting(self, meeting_details, participants_agent_id):
print(f"\n### MeetingSchedulerAgent: Scheduling meeting '{meeting_details['title']}' ###")
# 1. Add event to calendar tool via MCP
if "calendar_tool" in self.mcp_servers:
print(f"MeetingSchedulerAgent: Calling 'calendar_tool' via MCP...")
mcp_server = self.mcp_servers["calendar_tool"]
response = mcp_server.call_function("add_calendar_event", meeting_details)
if response["status"] == "success":
print(f"MeetingSchedulerAgent: Event added successfully. Event ID: {response['event_id']}")
meeting_details["event_id"] = response["event_id"]
else:
print(f"MeetingSchedulerAgent: Failed to add event: {response['message']}")
return False
else:
print("MeetingSchedulerAgent: Not connected to calendar tool's MCP Server.")
return False
# 2. Notify ParticipantNotifierAgent via A2A
if participants_agent_id in self.known_agents:
print(f"MeetingSchedulerAgent: Notifying ParticipantNotifierAgent via A2A...")
notification_payload = {
"meeting_title": meeting_details["title"],
"time": meeting_details["time"],
"participants": meeting_details["participants"]
}
message = self.send_a2a_message(
participants_agent_id,
"notify_meeting_participants",
notification_payload
)
# In a real app, a message queue or Agent service would handle this
# Here we directly simulate the receiver processing
if message:
print(f"MeetingSchedulerAgent: Received reply from {self.known_agents[participants_agent_id].name}: {self.known_agents[participants_agent_id].receive_a2a_message(message)}")
return True
else:
print("MeetingSchedulerAgent: Cannot find ParticipantNotifierAgent.")
return False
def receive_a2a_message(self, message):
super().receive_a2a_message(message)
if message.message_type == "meeting_details_request":
print(f"MeetingSchedulerAgent: Received meeting details request, but not supported.")
return {"status": "unsupported", "message": "Cannot provide meeting details on request."}
else:
return {"status": "success", "message": "Message received and acknowledged."}
class ParticipantNotifierAgent(BaseAgent):
"""
Participant Notifier Agent, responsible for receiving meeting info and "notifying" participants.
"""
def __init__(self):
super().__init__("ParticipantNotifierAgent", ["notify_participants"])
def receive_a2a_message(self, message):
super().receive_a2a_message(message)
if message.message_type == "notify_meeting_participants":
meeting_title = message.payload["meeting_title"]
time = message.payload["time"]
participants = message.payload["participants"]
print(f"ParticipantNotifierAgent: Received meeting notification request:")
print(f" Meeting: '{meeting_title}'")
print(f" Time: {time}")
print(f" Participants: {', '.join(participants)}")
print(f"ParticipantNotifierAgent: Simulating sending notifications to participants...")
return {"status": "success", "message": "Participants notified."}
else:
print(f"ParticipantNotifierAgent: Unknown message type: {message.message_type}")
return {"status": "error", "message": "Unknown message type."}
# --- Run the App ---
def run_application():
print("--- Initializing AI Agents and Tools ---")
# 1. Instantiate external tool (calendar)
calendar_tool = ExternalTool("MyCalendar")
# 2. Instantiate MCP Server, connect to calendar tool
calendar_mcp_server = MCPServer(calendar_tool)
# 3. Instantiate Agents
meeting_scheduler = MeetingSchedulerAgent()
participant_notifier = ParticipantNotifierAgent()
# 4. Agent connects to MCP Server (MeetingSchedulerAgent can use calendar)
meeting_scheduler.register_mcp_server("calendar_tool", calendar_mcp_server)
# 5. Agents discover each other (simulate A2A discovery)
meeting_scheduler.discover_agent(participant_notifier.card)
participant_notifier.discover_agent(meeting_scheduler.card) # Discovery is bidirectional, though not needed here
print("\n--- Starting Task Execution ---")
# MeetingSchedulerAgent receives a meeting scheduling request
meeting_details = {
"title": "Quarterly Product Review Meeting",
"time": "June 20, 2025, 3:00 PM",
"participants": ["Alice", "Bob", "Charlie", "David"]
}
# MeetingSchedulerAgent schedules the meeting and notifies participants
success = meeting_scheduler.schedule_meeting(
meeting_details,
participant_notifier.agent_id
)
if success:
print("\n--- Task Completed ---")
print("Meeting scheduled and participants notified.")
print("\n--- View Events in Calendar Tool ---")
print(f"Events in calendar: {calendar_tool.get_events()}")
else:
print("\n--- Task Failed ---")
if __name__ == "__main__":
run_application()
Code Explanation: How A2A and MCP Are Reflected
1. A2A Protocol in Action
AgentCard
class:- This is the "business card" or "role description." Each Agent has one, describing its
agent_id
,name
, andcapabilities
. - In
run_application
,meeting_scheduler.discover_agent(participant_notifier.card)
simulates Agents "discovering" each other and learning about each other's capabilities.
- This is the "business card" or "role description." Each Agent has one, describing its
A2AMessage
class:- Defines the standard format for Agent-to-Agent communication, including
sender_id
,receiver_id
,message_type
(e.g., "request_schedule_meeting", "notify_participants"), andpayload
(message content). MeetingSchedulerAgent
usesself.send_a2a_message()
to notifyParticipantNotifierAgent
.ParticipantNotifierAgent
usesreceive_a2a_message()
to receive and process messages from other Agents.
- Defines the standard format for Agent-to-Agent communication, including
- Agent Collaboration:
MeetingSchedulerAgent
does not notify participants directly, but sends this task via A2A message toParticipantNotifierAgent
, demonstrating division of labor and collaboration between Agents.
2. MCP Protocol in Action
ExternalTool
class:- Simulates a real external tool, here a simplified
calendar
. It has its own logic (add_event
,get_events
).
- Simulates a real external tool, here a simplified
MCPServer
class:- The core of MCP. It acts as a "middle layer," wrapping the concrete functions of
ExternalTool
(add_event
,get_events
) as "services" (available_functions
dict) that Agents can call via a unified interface. - Agents do not interact directly with the
ExternalTool
's methods, but call them viaMCPServer.call_function()
, providing a unified tool access interface.
- The core of MCP. It acts as a "middle layer," wrapping the concrete functions of
- Agent-MCP Connection:
MeetingSchedulerAgent
callsself.register_mcp_server("calendar_tool", calendar_mcp_server)
to "connect" to the calendar tool's MCP Server. This means the Agent now knows how to use the calendar tool via MCP.- In
MeetingSchedulerAgent.schedule_meeting
,mcp_server.call_function("add_calendar_event", meeting_details)
actually calls the calendar tool.
How to Run This App
- Save the above Python code as a
.py
file, e.g.,ai_collaboration_app.py
. - Open your terminal or command prompt.
- Navigate to the directory where you saved the file.
- Run:
python ai_collaboration_app.py
What You'll See
You will see a series of logs showing:
- Initialization of Agents and Tools: Which Agents were created, which MCP Servers were connected.
- Agent Discovery: Agents "know" about each other's existence and capabilities.
- Task Execution:
MeetingSchedulerAgent
first uses MCP to call the calendar tool'sadd_event
function to schedule the meeting.- Then,
MeetingSchedulerAgent
uses the A2A protocol to send a message toParticipantNotifierAgent
. ParticipantNotifierAgent
receives and processes the A2A message, simulating notification of participants.
- Final Result: Confirmation that the meeting was scheduled and participants notified.
Through this simple app, you should have a more intuitive understanding of how the A2A protocol enables collaboration and communication between AI Agents, and how MCP provides standardized, unified access to external tools for AI Agents. Together, they lay the foundation for building smarter and more complex AI systems.