A2A and MCP
Imagine: A Smart Team and Their Tools
Let's use an easy-to-understand example to explain the A2A protocol and MCP, their relationship, and how to use them.
Imagine you're the boss of a company. Your company has many smart "employees" (AI Agents), each with their own specialty, like:
- Secretary Agent: Handles scheduling meetings and managing calendars.
- Sales Agent: Communicates with clients and recommends products.
- Data Analysis Agent: Analyzes sales data and generates reports.
These Agents are very intelligent, but initially, they work independently. They don't know what each other can do or how to collaborate. At the same time, they also need to use some "tools" to get their work done, such as:
- Calendar application: For scheduling meetings.
- CRM system: For recording customer information.
- Database: For storing sales data.
- PPT creation software: For generating reports.
A2A Protocol: The "Common Language" and "Collaboration Rules" for Agents
The A2A (Agent-to-Agent) protocol is like setting up a "common language" and "collaboration rules" for these smart employees.
Before the A2A protocol, if the Secretary Agent wanted the Sales Agent to contact a client, they might have to agree on a "secret code" or develop a specific interface just for that collaboration. This is like different countries having different languages; to communicate, you need a translator, or you have to learn a new language for every specific interaction.
With the A2A protocol, it's like training all Agents in an "international common language" (like English) and a set of "team collaboration guidelines."
- Agent Card: Each Agent will have a "business card" or "job description" clearly stating its name, what it can do (e.g., "I can schedule meetings," "I can analyze data"), and how to contact it. This "business card" is the Agent Card, and it allows other Agents to quickly discover and understand its capabilities.
- Standardized Communication: A2A specifies how Agents send requests, reply, convey task progress, share files, and so on. This is like team members using a uniform meeting process, report templates, and file-sharing methods, making collaboration smooth and efficient.
In short, the A2A protocol allows different AI Agents to discover, understand, and work together in a standardized way.
How to use the A2A protocol?
If you're developing Agents and want them to collaborate, you can:
- Define Agent Cards: Create an Agent Card for your Agent, clearly outlining its capabilities and interfaces.
- Follow A2A specifications: Ensure your Agent sends and receives information according to the format and processes specified by the A2A protocol when communicating with other Agents.
- Use an SDK (Software Development Kit): Many platforms provide A2A SDKs to make it easier to implement communication between Agents.
MCP: The "Unified Interface" for Agents to Access "External Tools"
The MCP (Model Context Protocol) is like equipping each smart employee with a "universal plug", allowing them to easily connect to and use various "external tools" (like calendars, CRMs, databases).
Before MCP, the Secretary Agent might need to write specific code to connect to a calendar application, and the Sales Agent would need completely different code for the CRM system. This is like different electronic devices requiring different plugs, which is very inconvenient.
With MCP, it's like providing all Agents with a "USB-C port":
- Unified Interface: Regardless of whether the external tool is a calendar app, CRM system, or database, the Agent can call them through a unified method provided by MCP (e.g., JSON-RPC).
- Context Provisioning: MCP also helps Agents obtain and understand the "contextual information" needed to use tools, such as "what time it is now" or "which customer's data to query."
In short, MCP allows AI Agents to use various external tools and data more conveniently and intelligently in a standardized way.
How to use MCP?
If you want your Agent to use external tools, you can:
- Create an MCP Server: Create an MCP Server for your external tool, which will wrap the tool's functions into an interface that MCP can understand.
- 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 this MCP Server via the MCP protocol, thereby indirectly using the external tool.
The Relationship Between A2A Protocol and MCP: Close Collaboration for Task Completion
A2A and MCP are not in competition; they are complementary. They function like an excellent team:
- A2A handles "internal team collaboration": Agents communicate with each other, assign tasks, and share progress.
- MCP handles "external interaction": Each Agent uses MCP to access various external tools, retrieve data, or perform operations.
Imagine a scenario:
The boss (user) tells the Secretary Agent: "Please schedule a meeting for next Tuesday at 2 PM about the new product launch, and invite the Sales Agent and Data Analysis Agent."
- The Secretary Agent (A2A client) receives the task.
- It decides it needs to schedule a meeting, so it calls its MCP to connect to the calendar application (an external tool).
- The Secretary Agent will send meeting invitations to the Sales Agent and Data Analysis Agent via the A2A protocol (this is Agent-to-Agent communication).
- Upon receiving the invitation, the Sales Agent and Data Analysis Agent will use their MCP to check their calendars and reply to the Secretary Agent (also via the A2A protocol).
- During the meeting, the boss might ask the Sales Agent: "How are the recent sales of the new product?"
- The Sales Agent will use its MCP to connect to the CRM system and retrieve customer data.
- The Sales Agent might find the data isn't detailed enough, so it will send the data to the Data Analysis Agent via the A2A protocol to generate a detailed sales report.
- Upon receiving the data, the Data Analysis Agent will use its MCP to call the database for more information and use PPT creation software to generate the report.
- Finally, the Data Analysis Agent sends the report back to the Sales Agent via the A2A protocol, and the Sales Agent then reports to the boss.
In summary:
- The A2A protocol allows AI Agents to "talk" and "collaborate" with each other, enabling more complex tasks.
- MCP allows AI Agents to conveniently "use" various "tools," expanding their capabilities.
- Together, they build a powerful AI ecosystem where different Agents can work like a highly efficient team, collaboratively using various tools to solve problems.
Okay, let's build a simple Python application to demonstrate how an AI Agent can use the A2A protocol to collaborate with other Agents and how to use external tools via MCP.
Scenario: Smart Meeting Assistant
We'll create a "Smart Meeting Assistant" application. In this app, we'll have two Agents:
- Meeting Scheduler Agent: Responsible for scheduling meetings and will use a "calendar tool."
- Participant Notifier Agent: Responsible for notifying attendees about meeting information.
A2A Protocol in Action
- Agent Discovery and Communication: The Meeting Scheduler Agent needs to know how to notify participants, so it will "discover" and invoke the Participant Notifier Agent's capabilities.
- Standardized Message Passing: Agents will exchange meeting information and notification requests following a simple message format.
MCP in Action
- Tool Encapsulation: We'll simulate a "calendar tool." The Meeting Scheduler Agent will "call" this calendar tool's functions (like "add event") via MCP.
- Unified Interface: Regardless of how many external tools there are in the future, Agents can call them through similar MCP interfaces.
Small Application Code Example
We'll use Python classes to simulate the Agent and MCP concepts.
import json
import uuid
# --- Simulate A2A Protocol Components ---
class AgentCard:
"""
Simulates an A2A Agent Card, describing an Agent's capabilities.
"""
def __init__(self, agent_id, name, capabilities):
self.agent_id = agent_id
self.name = name
self.capabilities = capabilities # List describing 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:
"""
Simulates the A2A message structure for communication between Agents.
"""
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 Components ---
class ExternalTool:
"""
Simulates an external tool, such as a simplified calendar application.
"""
def __init__(self, name):
self.name = name
self.calendar_events = []
def add_event(self, event_details):
print(f" [{self.name} Tool]: Request received, 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:
"""
Simulates an MCP Server, responsible for 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, containing 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 = {} # Stores information about known Agents (A2A discovery)
self.mcp_servers = {} # Stores MCP Server instances (MCP connection)
def register_mcp_server(self, tool_name, mcp_server):
"""Registers an MCP Server, connecting 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):
"""Simulates an 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):
"""Sends an A2A message."""
if receiver_agent_id not in self.known_agents:
print(f"Error: Agent '{self.name}' unknown Agent ID: {receiver_agent_id}")
return None
message = A2AMessage(self.agent_id, receiver_agent_id, message_type, payload)
print(f"\n--- Agent '{self.name}' sending A2A message to '{self.known_agents[receiver_agent_id].name}' ---")
print(message.to_json())
return message
def receive_a2a_message(self, message):
"""Receives an A2A message (an abstract method 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. Call the calendar tool via MCP to add an event
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 successfully added. Event ID: {response['event_id']}")
meeting_details["event_id"] = response["event_id"]
else:
print(f"MeetingSchedulerAgent: Event addition failed: {response['message']}")
return False
else:
print("MeetingSchedulerAgent: Not connected to calendar tool's MCP Server.")
return False
# 2. Notify the Participant Notifier Agent via A2A protocol
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 application, there would be a message queue or Agent service to handle reception
# 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: Could not find Participant Notifier Agent.")
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 currently 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 information 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: Received unknown message type: {message.message_type}")
return {"status": "error", "message": "Unknown message type."}
# --- Run the Small Application ---
def run_application():
print("--- Initializing AI Agents and Tools ---")
# 1. Instantiate the external tool (Calendar)
calendar_tool = ExternalTool("MyCalendar")
# 2. Instantiate the MCP Server, connecting the calendar tool
calendar_mcp_server = MCPServer(calendar_tool)
# 3. Instantiate Agents
meeting_scheduler = MeetingSchedulerAgent()
participant_notifier = ParticipantNotifierAgent()
# 4. Agents connect to MCP Servers (allowing MeetingSchedulerAgent to use the calendar)
meeting_scheduler.register_mcp_server("calendar_tool", calendar_mcp_server)
# 5. Agents discover each other (simulating A2A protocol's discovery mechanism)
meeting_scheduler.discover_agent(participant_notifier.card)
participant_notifier.discover_agent(meeting_scheduler.card) # Though in this example the notifier doesn't need to call the scheduler, discovery is bidirectional.
print("\n--- Starting Task Execution ---")
# Meeting Scheduler Agent receives a request to schedule a meeting
meeting_details = {
"title": "Quarterly Product Review",
"time": "2025-06-20 03:00 PM",
"participants": ["Alice", "Bob", "Charlie", "David"]
}
# Meeting Scheduler Agent starts scheduling the meeting and notifying 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--- Viewing 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 and A2A / MCP Demonstration
1. A2A Protocol Demonstration
AgentCard
Class:- This is what we called the "business card" or "job description." Each Agent has one, describing its
agent_id
,name
, andcapabilities
(what it can do). - In the
run_application
function,meeting_scheduler.discover_agent(participant_notifier.card)
simulates the process of Agents "discovering" each other and understanding their respective capabilities.
- This is what we called the "business card" or "job description." Each Agent has one, describing its
A2AMessage
Class:- Defines the standard format for inter-Agent communication, including
sender_id
(sender),receiver_id
(receiver),message_type
(e.g., "request schedule meeting," "notify participants"), andpayload
(message content). - The
MeetingSchedulerAgent
sends notifications to theParticipantNotifierAgent
by callingself.send_a2a_message()
. - The
ParticipantNotifierAgent
receives and processes messages from other Agents through itsreceive_a2a_message()
method.
- Defines the standard format for inter-Agent communication, including
- Agent Collaboration:
- The
MeetingSchedulerAgent
doesn't directly notify participants. Instead, it sends this task as an A2A message to theParticipantNotifierAgent
, demonstrating the division of labor among Agents.
- The
2. MCP Protocol Demonstration
ExternalTool
Class:- Simulates a real external tool, in this case, a simplified
calendar
. It has its own internal logic (add_event
,get_events
).
- Simulates a real external tool, in this case, a simplified
MCPServer
Class:- This is the core of MCP. It acts as an "intermediary layer," wrapping the specific functions of the
ExternalTool
(add_event
,get_events
) into "services" (available_functions
dictionary) that Agents can call via a unified interface. - Agents do not directly interact with the specific methods of the
ExternalTool
. Instead, they call them through theMCPServer.call_function()
method. This provides a unified tool access interface.
- This is the core of MCP. It acts as an "intermediary layer," wrapping the specific functions of the
- Agent and MCP Connection:
- The
MeetingSchedulerAgent
connects to the calendar tool's MCP Server by callingself.register_mcp_server("calendar_tool", calendar_mcp_server)
. This means the Agent now knows how to use the calendar tool via MCP. - Within the
MeetingSchedulerAgent.schedule_meeting
method, the actual call to the calendar tool is made viamcp_server.call_function("add_calendar_event", meeting_details)
.
- The
How to Run This Small Application
- Save the Python code above into a
.py
file, for example,ai_collaboration_app.py
. - Open your terminal or command prompt.
- Navigate to the directory where you saved the file.
- Run the command:
python ai_collaboration_app.py
Explanation of Run Results
You'll see a series of logs printed by the program, clearly demonstrating:
- Agent and Tool Initialization: Which Agents were created and which MCP Servers were connected.
- Agent Discovery Process: Each Agent "learns" about the existence and capabilities of the others.
- Task Execution Process:
- The
MeetingSchedulerAgent
first calls theadd_event
function of the "calendar tool" via MCP to schedule the meeting. - Then, the
MeetingSchedulerAgent
sends a message to theParticipantNotifierAgent
via the A2A protocol. - The
ParticipantNotifierAgent
receives and processes this A2A message, simulating the notification of participants.
- The
- Final Result: Confirmation that the meeting has been scheduled and participants notified.
Through this small application, you should gain a more intuitive understanding of how the A2A protocol facilitates collaboration and communication between AI Agents, and how MCP provides AI Agents with a standardized, unified ability to access external tools. Together, they lay the foundation for building more intelligent and complex AI systems.