agent-mcp 0.1.3__py3-none-any.whl → 0.1.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agent_mcp/__init__.py +66 -12
- agent_mcp/a2a_protocol.py +316 -0
- agent_mcp/agent_lightning_library.py +214 -0
- agent_mcp/camel_mcp_adapter.py +521 -0
- agent_mcp/claude_mcp_adapter.py +195 -0
- agent_mcp/cli.py +47 -0
- agent_mcp/google_ai_mcp_adapter.py +183 -0
- agent_mcp/heterogeneous_group_chat.py +412 -38
- agent_mcp/langchain_mcp_adapter.py +176 -43
- agent_mcp/llamaindex_mcp_adapter.py +410 -0
- agent_mcp/mcp_agent.py +26 -0
- agent_mcp/mcp_transport.py +11 -5
- agent_mcp/microsoft_agent_framework.py +591 -0
- agent_mcp/missing_frameworks.py +435 -0
- agent_mcp/openapi_protocol.py +616 -0
- agent_mcp/payments.py +804 -0
- agent_mcp/pydantic_ai_mcp_adapter.py +628 -0
- agent_mcp/registry.py +768 -0
- agent_mcp/security.py +864 -0
- {agent_mcp-0.1.3.dist-info → agent_mcp-0.1.5.dist-info}/METADATA +173 -49
- agent_mcp-0.1.5.dist-info/RECORD +62 -0
- {agent_mcp-0.1.3.dist-info → agent_mcp-0.1.5.dist-info}/WHEEL +1 -1
- agent_mcp-0.1.5.dist-info/entry_points.txt +4 -0
- agent_mcp-0.1.5.dist-info/top_level.txt +3 -0
- demos/__init__.py +1 -0
- demos/basic/__init__.py +1 -0
- demos/basic/framework_examples.py +108 -0
- demos/basic/langchain_camel_demo.py +272 -0
- demos/basic/simple_chat.py +355 -0
- demos/basic/simple_integration_example.py +51 -0
- demos/collaboration/collaborative_task_example.py +437 -0
- demos/collaboration/group_chat_example.py +130 -0
- demos/collaboration/simplified_crewai_example.py +39 -0
- demos/comprehensive_framework_demo.py +202 -0
- demos/langgraph/autonomous_langgraph_network.py +808 -0
- demos/langgraph/langgraph_agent_network.py +415 -0
- demos/langgraph/langgraph_collaborative_task.py +619 -0
- demos/langgraph/langgraph_example.py +227 -0
- demos/langgraph/run_langgraph_examples.py +213 -0
- demos/network/agent_network_example.py +381 -0
- demos/network/email_agent.py +130 -0
- demos/network/email_agent_demo.py +46 -0
- demos/network/heterogeneous_network_example.py +216 -0
- demos/network/multi_framework_example.py +199 -0
- demos/utils/check_imports.py +49 -0
- demos/workflows/autonomous_agent_workflow.py +248 -0
- demos/workflows/mcp_features_demo.py +353 -0
- demos/workflows/run_agent_collaboration_demo.py +63 -0
- demos/workflows/run_agent_collaboration_with_logs.py +396 -0
- demos/workflows/show_agent_interactions.py +107 -0
- demos/workflows/simplified_autonomous_demo.py +74 -0
- functions/main.py +144 -0
- functions/mcp_network_server.py +513 -0
- functions/utils.py +47 -0
- agent_mcp-0.1.3.dist-info/RECORD +0 -18
- agent_mcp-0.1.3.dist-info/entry_points.txt +0 -2
- agent_mcp-0.1.3.dist-info/top_level.txt +0 -1
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
"""
|
|
2
|
+
LangGraph Agent Network Example using MCPNode.
|
|
3
|
+
|
|
4
|
+
This example demonstrates a network of agents built with LangGraph and the MCP protocol,
|
|
5
|
+
showing how to create a flexible agent network where multiple specialized agents can
|
|
6
|
+
collaborate and share context through a coordinator.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import os
|
|
10
|
+
import json
|
|
11
|
+
import uuid
|
|
12
|
+
from typing import Dict, List, Any, Optional, cast, Callable
|
|
13
|
+
|
|
14
|
+
from langchain_core.messages import HumanMessage, AIMessage, SystemMessage
|
|
15
|
+
from langchain_core.tools import tool
|
|
16
|
+
import langgraph.graph
|
|
17
|
+
from langgraph.graph import END, StateGraph
|
|
18
|
+
from langgraph.prebuilt import ToolNode
|
|
19
|
+
from openai import OpenAI
|
|
20
|
+
|
|
21
|
+
# Import our MCP implementation for LangGraph
|
|
22
|
+
from agent_mcp.mcp_langgraph import MCPNode, MCPReactAgent, create_mcp_langgraph
|
|
23
|
+
|
|
24
|
+
# Initialize OpenAI client
|
|
25
|
+
OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY")
|
|
26
|
+
openai = OpenAI(api_key=OPENAI_API_KEY)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def get_llm():
|
|
30
|
+
"""Get the OpenAI LLM wrapper that implements the langchain interface."""
|
|
31
|
+
from langchain_openai import ChatOpenAI
|
|
32
|
+
|
|
33
|
+
# Initialize with the newest model (gpt-4) which was released after your knowledge cutoff
|
|
34
|
+
return ChatOpenAI(model="gpt-4", temperature=0.7)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class LangGraphAgentNetwork:
|
|
38
|
+
"""A network of LangGraph agents using MCP for communication and context sharing."""
|
|
39
|
+
|
|
40
|
+
def __init__(self):
|
|
41
|
+
"""Initialize the agent network."""
|
|
42
|
+
self.llm = get_llm()
|
|
43
|
+
self.agents = {}
|
|
44
|
+
self.network_id = str(uuid.uuid4())
|
|
45
|
+
self.shared_workspace = {}
|
|
46
|
+
self.message_history = []
|
|
47
|
+
|
|
48
|
+
# Create the agent network
|
|
49
|
+
self.create_network()
|
|
50
|
+
|
|
51
|
+
def create_network(self):
|
|
52
|
+
"""Create all agents in the network and connect them."""
|
|
53
|
+
# Create the coordinator agent
|
|
54
|
+
coordinator = MCPReactAgent(
|
|
55
|
+
name="Coordinator",
|
|
56
|
+
system_message=(
|
|
57
|
+
"You are the Coordinator agent responsible for managing communication "
|
|
58
|
+
"and task assignment across the network. You should help users interact "
|
|
59
|
+
"with specialized agents and facilitate collaboration."
|
|
60
|
+
)
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
# Create specialized agents
|
|
64
|
+
researcher = MCPReactAgent(
|
|
65
|
+
name="Researcher",
|
|
66
|
+
system_message=(
|
|
67
|
+
"You are the Researcher agent specialized in gathering and synthesizing "
|
|
68
|
+
"information. You excel at finding relevant data and organizing it into "
|
|
69
|
+
"coherent summaries."
|
|
70
|
+
)
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
analyst = MCPReactAgent(
|
|
74
|
+
name="Analyst",
|
|
75
|
+
system_message=(
|
|
76
|
+
"You are the Analyst agent specialized in data analysis and interpretation. "
|
|
77
|
+
"You can identify patterns, extract insights, and explain complex data in "
|
|
78
|
+
"simple terms."
|
|
79
|
+
)
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
planner = MCPReactAgent(
|
|
83
|
+
name="Planner",
|
|
84
|
+
system_message=(
|
|
85
|
+
"You are the Planner agent specialized in strategic planning and task "
|
|
86
|
+
"decomposition. You can break down complex problems into actionable steps."
|
|
87
|
+
)
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
creative = MCPReactAgent(
|
|
91
|
+
name="Creative",
|
|
92
|
+
system_message=(
|
|
93
|
+
"You are the Creative agent specialized in generating innovative ideas "
|
|
94
|
+
"and creative content. You can think outside the box and provide unique "
|
|
95
|
+
"perspectives on problems."
|
|
96
|
+
)
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
# Add them to our agent dictionary
|
|
100
|
+
self.agents = {
|
|
101
|
+
"coordinator": coordinator,
|
|
102
|
+
"researcher": researcher,
|
|
103
|
+
"analyst": analyst,
|
|
104
|
+
"planner": planner,
|
|
105
|
+
"creative": creative
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
# Register custom tools for all agents
|
|
109
|
+
self._register_network_tools()
|
|
110
|
+
|
|
111
|
+
# Connect the agents (register each agent as a tool for others)
|
|
112
|
+
self._connect_agents()
|
|
113
|
+
|
|
114
|
+
# Share the workspace with all agents
|
|
115
|
+
self._share_workspace()
|
|
116
|
+
|
|
117
|
+
def _register_network_tools(self):
|
|
118
|
+
"""Register network-specific tools for all agents."""
|
|
119
|
+
# Register tools for each agent
|
|
120
|
+
for agent_id, agent in self.agents.items():
|
|
121
|
+
# Tool to update the shared workspace
|
|
122
|
+
def workspace_update(section: str, key: str, value: Any, agent_id=agent_id):
|
|
123
|
+
"""Update a section of the shared workspace."""
|
|
124
|
+
self.update_workspace(section, key, value, from_agent=agent_id)
|
|
125
|
+
return json.dumps({
|
|
126
|
+
"status": "success",
|
|
127
|
+
"message": f"Updated workspace: {section}/{key}"
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
# Tool to read from the shared workspace
|
|
131
|
+
def workspace_get(section: str, key: Optional[str] = None, agent_id=agent_id):
|
|
132
|
+
"""Get data from the shared workspace."""
|
|
133
|
+
if section not in self.shared_workspace:
|
|
134
|
+
return json.dumps({
|
|
135
|
+
"status": "error",
|
|
136
|
+
"message": f"Section '{section}' not found in workspace"
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
if key is None:
|
|
140
|
+
return json.dumps({
|
|
141
|
+
"status": "success",
|
|
142
|
+
"data": self.shared_workspace[section]
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
if key not in self.shared_workspace[section]:
|
|
146
|
+
return json.dumps({
|
|
147
|
+
"status": "error",
|
|
148
|
+
"message": f"Key '{key}' not found in section '{section}'"
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
return json.dumps({
|
|
152
|
+
"status": "success",
|
|
153
|
+
"data": self.shared_workspace[section][key]
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
# Tool to send a message to the network
|
|
157
|
+
def send_message(message: str, agent_id=agent_id):
|
|
158
|
+
"""Send a message to all agents in the network."""
|
|
159
|
+
self.add_message(agent_id, message)
|
|
160
|
+
return json.dumps({
|
|
161
|
+
"status": "success",
|
|
162
|
+
"message": "Message sent to the network"
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
# Tool to list all agents in the network
|
|
166
|
+
def list_agents(agent_id=agent_id):
|
|
167
|
+
"""List all agents in the network."""
|
|
168
|
+
agents_list = [
|
|
169
|
+
{"id": aid, "name": a.name}
|
|
170
|
+
for aid, a in self.agents.items()
|
|
171
|
+
]
|
|
172
|
+
return json.dumps({
|
|
173
|
+
"status": "success",
|
|
174
|
+
"agents": agents_list
|
|
175
|
+
})
|
|
176
|
+
|
|
177
|
+
# Register the tools with the agent
|
|
178
|
+
agent.register_custom_tool(
|
|
179
|
+
"workspace_update",
|
|
180
|
+
"Update a section of the shared workspace",
|
|
181
|
+
workspace_update
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
agent.register_custom_tool(
|
|
185
|
+
"workspace_get",
|
|
186
|
+
"Get data from the shared workspace",
|
|
187
|
+
workspace_get
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
agent.register_custom_tool(
|
|
191
|
+
"send_message",
|
|
192
|
+
"Send a message to all agents in the network",
|
|
193
|
+
send_message
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
agent.register_custom_tool(
|
|
197
|
+
"list_agents",
|
|
198
|
+
"List all agents in the network",
|
|
199
|
+
list_agents
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
def _connect_agents(self):
|
|
203
|
+
"""Register each agent as a tool for the other agents."""
|
|
204
|
+
for agent_id, agent in self.agents.items():
|
|
205
|
+
# For each agent, create tools to call other agents
|
|
206
|
+
for target_id, target_agent in self.agents.items():
|
|
207
|
+
if agent_id == target_id:
|
|
208
|
+
continue # Skip self-registration
|
|
209
|
+
|
|
210
|
+
# Create a function to call the target agent
|
|
211
|
+
def call_agent(message: str, target_id=target_id):
|
|
212
|
+
"""Call another agent with a message and get their response."""
|
|
213
|
+
# In a real implementation, this would call the agent's LLM
|
|
214
|
+
target_agent_name = self.agents[target_id].name
|
|
215
|
+
|
|
216
|
+
# For simulation purposes, we'll return a simple acknowledgment
|
|
217
|
+
return json.dumps({
|
|
218
|
+
"status": "success",
|
|
219
|
+
"message": f"Message sent to {target_agent_name}",
|
|
220
|
+
"request_id": str(uuid.uuid4())
|
|
221
|
+
})
|
|
222
|
+
|
|
223
|
+
# Register the tool
|
|
224
|
+
agent.register_custom_tool(
|
|
225
|
+
f"call_{target_id}",
|
|
226
|
+
f"Send a message to the {target_id} agent and get their response",
|
|
227
|
+
call_agent
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
def _share_workspace(self):
|
|
231
|
+
"""Share the workspace with all agents."""
|
|
232
|
+
# Initialize the shared workspace with empty sections
|
|
233
|
+
self.shared_workspace = {
|
|
234
|
+
"research": {},
|
|
235
|
+
"analysis": {},
|
|
236
|
+
"planning": {},
|
|
237
|
+
"creative": {},
|
|
238
|
+
"summary": {}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
# Update each agent's context with the network ID
|
|
242
|
+
for agent_id, agent in self.agents.items():
|
|
243
|
+
agent.update_context("network_id", self.network_id)
|
|
244
|
+
agent.update_context("agent_id", agent_id)
|
|
245
|
+
agent.update_context("agent_role", agent_id)
|
|
246
|
+
|
|
247
|
+
def update_workspace(self, section: str, key: str, value: Any, from_agent: str) -> None:
|
|
248
|
+
"""Update a section of the workspace and share with all agents."""
|
|
249
|
+
if section not in self.shared_workspace:
|
|
250
|
+
self.shared_workspace[section] = {}
|
|
251
|
+
|
|
252
|
+
self.shared_workspace[section][key] = value
|
|
253
|
+
|
|
254
|
+
# Add a message to the history
|
|
255
|
+
self.add_message(
|
|
256
|
+
from_agent,
|
|
257
|
+
f"Updated workspace: {section}/{key} with new information"
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
def add_message(self, from_agent: str, message: str) -> None:
|
|
261
|
+
"""Add a message to the network communication log."""
|
|
262
|
+
agent_name = self.agents[from_agent].name
|
|
263
|
+
self.message_history.append({
|
|
264
|
+
"from": agent_name,
|
|
265
|
+
"agent_id": from_agent,
|
|
266
|
+
"message": message,
|
|
267
|
+
"timestamp": "now" # In a real implementation, use actual timestamps
|
|
268
|
+
})
|
|
269
|
+
|
|
270
|
+
def set_topic(self, topic: str) -> None:
|
|
271
|
+
"""Set a topic for discussion in the network."""
|
|
272
|
+
# Update the workspace with the new topic
|
|
273
|
+
self.update_workspace("summary", "current_topic", topic, "coordinator")
|
|
274
|
+
|
|
275
|
+
# Update all agents' context with the topic
|
|
276
|
+
for agent_id, agent in self.agents.items():
|
|
277
|
+
agent.update_context("current_topic", topic)
|
|
278
|
+
|
|
279
|
+
def interact_with_agent(self, agent_id: str) -> None:
|
|
280
|
+
"""Allow the user to interact with a specific agent."""
|
|
281
|
+
if agent_id not in self.agents:
|
|
282
|
+
print(f"Agent '{agent_id}' not found in the network.")
|
|
283
|
+
return
|
|
284
|
+
|
|
285
|
+
agent = self.agents[agent_id]
|
|
286
|
+
agent_name = agent.name
|
|
287
|
+
|
|
288
|
+
print(f"\n=== Interacting with {agent_name} Agent ===")
|
|
289
|
+
|
|
290
|
+
# Create a graph with just this agent
|
|
291
|
+
agent_node = agent.create_agent(self.llm)
|
|
292
|
+
|
|
293
|
+
# Create a simple graph with just this agent
|
|
294
|
+
graph = create_mcp_langgraph(
|
|
295
|
+
self.llm,
|
|
296
|
+
name=f"{agent_name}Graph",
|
|
297
|
+
system_message=agent.get_context("system_message")
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
# Start the interaction loop
|
|
301
|
+
print(f"You are now chatting with the {agent_name} Agent. Type 'exit' to end.")
|
|
302
|
+
|
|
303
|
+
conversation_history = []
|
|
304
|
+
|
|
305
|
+
while True:
|
|
306
|
+
# Get user input
|
|
307
|
+
user_input = input(f"\nYou to {agent_name}: ")
|
|
308
|
+
|
|
309
|
+
if user_input.lower() == "exit":
|
|
310
|
+
print(f"Ending conversation with {agent_name}.")
|
|
311
|
+
break
|
|
312
|
+
|
|
313
|
+
# Add to conversation history
|
|
314
|
+
conversation_history.append(HumanMessage(content=user_input))
|
|
315
|
+
|
|
316
|
+
# Create a state with the messages
|
|
317
|
+
state = {"messages": conversation_history}
|
|
318
|
+
|
|
319
|
+
# Run the graph
|
|
320
|
+
result = graph.invoke(state)
|
|
321
|
+
|
|
322
|
+
# Get the AI response
|
|
323
|
+
messages = result.get("messages", [])
|
|
324
|
+
last_ai_message = next((msg for msg in reversed(messages) if isinstance(msg, AIMessage)), None)
|
|
325
|
+
|
|
326
|
+
if last_ai_message:
|
|
327
|
+
print(f"{agent_name}: {last_ai_message.content}")
|
|
328
|
+
conversation_history.append(last_ai_message)
|
|
329
|
+
else:
|
|
330
|
+
print(f"{agent_name}: I'm not sure how to respond to that.")
|
|
331
|
+
|
|
332
|
+
def list_agents(self) -> None:
|
|
333
|
+
"""List all agents in the network with their specialties."""
|
|
334
|
+
print("\n=== Agents in the Network ===")
|
|
335
|
+
for agent_id, agent in self.agents.items():
|
|
336
|
+
agent_name = agent.name
|
|
337
|
+
print(f"- {agent_name} ({agent_id})")
|
|
338
|
+
|
|
339
|
+
def show_workspace(self) -> None:
|
|
340
|
+
"""Show the current state of the shared workspace."""
|
|
341
|
+
print("\n=== Shared Workspace ===")
|
|
342
|
+
for section, data in self.shared_workspace.items():
|
|
343
|
+
print(f"\n{section.upper()}:")
|
|
344
|
+
if not data:
|
|
345
|
+
print(" No data yet")
|
|
346
|
+
else:
|
|
347
|
+
for key, value in data.items():
|
|
348
|
+
if isinstance(value, dict) or isinstance(value, list):
|
|
349
|
+
print(f" {key}: {json.dumps(value)[:100]}...")
|
|
350
|
+
else:
|
|
351
|
+
print(f" {key}: {value}")
|
|
352
|
+
|
|
353
|
+
def show_messages(self) -> None:
|
|
354
|
+
"""Show the network message history."""
|
|
355
|
+
print("\n=== Network Messages ===")
|
|
356
|
+
if not self.message_history:
|
|
357
|
+
print("No messages yet")
|
|
358
|
+
else:
|
|
359
|
+
for msg in self.message_history[-10:]: # Show last 10 messages
|
|
360
|
+
print(f"{msg['from']}: {msg['message']}")
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
def main():
|
|
364
|
+
"""Run the agent network example."""
|
|
365
|
+
print("=== LangGraph Agent Network Example ===")
|
|
366
|
+
print("This example demonstrates a network of specialized agents built with LangGraph.")
|
|
367
|
+
print("The agents can communicate with each other and share context using the MCP protocol.")
|
|
368
|
+
|
|
369
|
+
# Create the agent network
|
|
370
|
+
network = LangGraphAgentNetwork()
|
|
371
|
+
|
|
372
|
+
# Main interaction loop
|
|
373
|
+
while True:
|
|
374
|
+
print("\n=== Agent Network Menu ===")
|
|
375
|
+
print("1. List all agents")
|
|
376
|
+
print("2. Chat with an agent")
|
|
377
|
+
print("3. Set discussion topic")
|
|
378
|
+
print("4. Show workspace")
|
|
379
|
+
print("5. Show recent messages")
|
|
380
|
+
print("6. Exit")
|
|
381
|
+
|
|
382
|
+
choice = input("\nEnter your choice (1-6): ")
|
|
383
|
+
|
|
384
|
+
if choice == "1":
|
|
385
|
+
network.list_agents()
|
|
386
|
+
|
|
387
|
+
elif choice == "2":
|
|
388
|
+
network.list_agents()
|
|
389
|
+
agent_id = input("\nEnter agent ID to chat with: ")
|
|
390
|
+
if agent_id in network.agents:
|
|
391
|
+
network.interact_with_agent(agent_id)
|
|
392
|
+
else:
|
|
393
|
+
print(f"Agent '{agent_id}' not found.")
|
|
394
|
+
|
|
395
|
+
elif choice == "3":
|
|
396
|
+
topic = input("Enter a topic for discussion: ")
|
|
397
|
+
network.set_topic(topic)
|
|
398
|
+
print(f"Topic set to: {topic}")
|
|
399
|
+
|
|
400
|
+
elif choice == "4":
|
|
401
|
+
network.show_workspace()
|
|
402
|
+
|
|
403
|
+
elif choice == "5":
|
|
404
|
+
network.show_messages()
|
|
405
|
+
|
|
406
|
+
elif choice == "6":
|
|
407
|
+
print("Exiting agent network example.")
|
|
408
|
+
break
|
|
409
|
+
|
|
410
|
+
else:
|
|
411
|
+
print("Invalid choice. Please enter a number from 1 to 6.")
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
if __name__ == "__main__":
|
|
415
|
+
main()
|