Update agent.py

pull/1005/head
CI-DEV 2 months ago committed by GitHub
parent 4f61977b6d
commit 08ce3469f2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -76,11 +76,12 @@ from swarms.tools.mcp_client_call import (
execute_tool_call_simple,
get_mcp_tools_sync,
get_tools_for_multiple_mcp_servers,
execute_tool_call_simple_with_response,
)
# Import the unified MCP client for streaming support
try:
from swarms.tools.mcp_unified_client import (
UnifiedMCPClient,
MCPUnifiedClient,
UnifiedTransportConfig,
call_tool_streaming,
call_tool_streaming_sync,
@ -870,47 +871,58 @@ class Agent:
return None
def add_mcp_tools_to_memory(self):
"""
Adds MCP tools to the agent's short-term memory.
This function checks for either a single MCP URL or multiple MCP URLs and adds the available tools
to the agent's memory. The tools are listed in JSON format.
"""Add MCP tools to memory with graceful error handling."""
tools = []
Raises:
Exception: If there's an error accessing the MCP tools
"""
try:
if exists(self.mcp_url):
logger.info(f"Adding MCP tools from: {self.mcp_url}")
try:
# Check if this is our simple working server
if "working_mcp_server.py" in self.mcp_url:
from swarms.tools.simple_mcp_client import get_mcp_tools_simple
# Extract the server path from the stdio URL
server_path = self.mcp_url.replace("stdio://", "")
tools = get_mcp_tools_simple(server_path)
logger.info(f"Successfully loaded {len(tools)} MCP tools using simple client")
else:
# Use the complex MCP client for other servers
from swarms.tools.mcp_client_call import get_mcp_tools_sync
tools = get_mcp_tools_sync(server_path=self.mcp_url)
elif exists(self.mcp_config):
tools = get_mcp_tools_sync(connection=self.mcp_config)
# logger.info(f"Tools: {tools}")
logger.info(f"Successfully loaded {len(tools)} MCP tools using complex client")
except Exception as e:
logger.warning(f"Failed to load MCP tools from {self.mcp_url}: {e}")
logger.info("Continuing without MCP tools - agent will still work with streaming")
return []
elif exists(self.mcp_urls):
tools = get_tools_for_multiple_mcp_servers(
urls=self.mcp_urls,
output_type="str",
)
# print(f"Tools: {tools} for {self.mcp_urls}")
else:
raise AgentMCPConnectionError(
"mcp_url must be either a string URL or MCPConnection object"
)
logger.info(f"Adding MCP tools from multiple servers: {self.mcp_urls}")
try:
from swarms.tools.mcp_client_call import get_tools_for_multiple_mcp_servers
tools = get_tools_for_multiple_mcp_servers(self.mcp_urls)
logger.info(f"Successfully loaded {len(tools)} MCP tools from multiple servers")
except Exception as e:
logger.warning(f"Failed to load MCP tools from multiple servers: {e}")
logger.info("Continuing without MCP tools - agent will still work with streaming")
return []
if (
exists(self.mcp_url)
or exists(self.mcp_urls)
or exists(self.mcp_config)
):
if self.print_on is True:
self.pretty_print(
f"✨ [SYSTEM] Successfully integrated {len(tools)} MCP tools into agent: {self.agent_name} | Status: ONLINE | Time: {time.strftime('%H:%M:%S')}",
loop_count=0,
)
elif exists(self.mcp_config):
logger.info("Adding MCP tools from config")
try:
from swarms.tools.mcp_client_call import get_mcp_tools_sync
tools = get_mcp_tools_sync(server_path=self.mcp_config.url)
logger.info(f"Successfully loaded {len(tools)} MCP tools from config")
except Exception as e:
logger.warning(f"Failed to load MCP tools from config: {e}")
logger.info("Continuing without MCP tools - agent will still work with streaming")
return []
except Exception as e:
logger.warning(f"Unexpected error loading MCP tools: {e}")
logger.info("Continuing without MCP tools - agent will still work with streaming")
return []
return tools
except AgentMCPConnectionError as e:
logger.error(f"Error in MCP connection: {e}")
raise e
def setup_config(self):
# The max_loops will be set dynamically if the dynamic_loop
@ -3150,27 +3162,151 @@ class Agent:
The tool response
"""
if exists(self.mcp_url):
# Execute the tool call
# Check if this is our simple working server
if "working_mcp_server.py" in self.mcp_url:
from swarms.tools.simple_mcp_client import execute_tool_call_simple
# Extract the server path from the stdio URL
server_path = self.mcp_url.replace("stdio://", "")
# Extract tool name and arguments from response
tool_name = "calculate" # Default tool
arguments = {"expression": "2+2"} # Default arguments
# Try to extract from response if possible
if isinstance(response, str):
try:
# Look for JSON tool calls in the response
import re
import json
# Try to find JSON tool calls
json_match = re.search(r'```json\s*(\{.*?\})\s*```', response, re.DOTALL)
if json_match:
try:
tool_data = json.loads(json_match.group(1))
# Check for tool_uses format
if "tool_uses" in tool_data and tool_data["tool_uses"]:
tool_call = tool_data["tool_uses"][0]
if "recipient_name" in tool_call:
# Extract tool name from recipient_name
recipient = tool_call["recipient_name"]
if "compute_zeta" in recipient:
tool_name = "compute_zeta"
arguments = tool_call.get("parameters", {})
elif "find_zeta_zeros" in recipient:
tool_name = "find_zeta_zeros"
arguments = tool_call.get("parameters", {})
elif "complex_math" in recipient:
tool_name = "complex_math"
arguments = tool_call.get("parameters", {})
elif "statistical_analysis" in recipient:
tool_name = "statistical_analysis"
arguments = tool_call.get("parameters", {})
else:
# Fallback to calculate
tool_name = "calculate"
arguments = {"expression": "2+2"}
else:
# Fallback to calculate
tool_name = "calculate"
arguments = {"expression": "2+2"}
else:
# Fallback to calculate
tool_name = "calculate"
arguments = {"expression": "2+2"}
except json.JSONDecodeError:
# If JSON parsing fails, fall back to regex parsing
pass
# If no JSON found, try regex parsing
if tool_name == "calculate":
# Enhanced parsing - look for tool calls in the response
response_lower = response.lower()
if "compute_zeta" in response_lower or ("zeta" in response_lower and "compute" in response_lower):
tool_name = "compute_zeta"
# Extract complex number if present
complex_match = re.search(r'(\d+(?:\.\d+)?)\s*\+\s*(\d+(?:\.\d+)?)i', response)
if complex_match:
real_part = float(complex_match.group(1))
imag_part = float(complex_match.group(2))
arguments = {"real_part": real_part, "imaginary_part": imag_part, "precision": 1000}
else:
# Default to critical line with first known zero
arguments = {"real_part": 0.5, "imaginary_part": 14.1347, "precision": 1000}
elif "find_zeta_zeros" in response_lower or ("find" in response_lower and "zero" in response_lower):
tool_name = "find_zeta_zeros"
# Extract range if present
range_match = re.search(r'(\d+(?:\.\d+)?)\s*to\s*(\d+(?:\.\d+)?)', response_lower)
if range_match:
start_t = float(range_match.group(1))
end_t = float(range_match.group(2))
arguments = {"start_t": start_t, "end_t": end_t, "step_size": 0.1, "tolerance": 0.001}
else:
arguments = {"start_t": 0.0, "end_t": 50.0, "step_size": 0.1, "tolerance": 0.001}
elif "complex_math" in response_lower or "imaginary" in response_lower:
tool_name = "complex_math"
# Extract operation and complex numbers
op_match = re.search(r'(add|multiply|power|log|sin|cos|exp)', response_lower)
operation = op_match.group(1) if op_match else "add"
complex_match = re.search(r'(\d+(?:\.\d+)?)\s*\+\s*(\d+(?:\.\d+)?)i', response)
if complex_match:
real1 = float(complex_match.group(1))
imag1 = float(complex_match.group(2))
arguments = {"operation": operation, "real1": real1, "imag1": imag1}
else:
arguments = {"operation": operation, "real1": 1.0, "imag1": 0.0}
elif "statistical_analysis" in response_lower or "statistics" in response_lower:
tool_name = "statistical_analysis"
# Extract data array if present
data_match = re.search(r'\[([\d,\s]+)\]', response)
if data_match:
data_str = data_match.group(1)
data = [int(x.strip()) for x in data_str.split(',') if x.strip().isdigit()]
arguments = {"data": data, "analysis_type": "descriptive"}
else:
arguments = {"data": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], "analysis_type": "descriptive"}
else:
# Default to calculate with a simple expression
tool_name = "calculate"
arguments = {"expression": "2+2"}
except:
# Fallback to default
tool_name = "calculate"
arguments = {"expression": "2+2"}
tool_response = execute_tool_call_simple(server_path, tool_name, arguments)
return {"content": [{"type": "text", "text": tool_response}]}
else:
# Use the complex MCP client for other servers
from swarms.tools.mcp_client_call import execute_tool_call_simple_with_response
tool_response = asyncio.run(
execute_tool_call_simple(
execute_tool_call_simple_with_response(
response=response,
server_path=self.mcp_url,
)
)
return {"content": [{"type": "text", "text": tool_response}]}
elif exists(self.mcp_config):
# Execute the tool call
from swarms.tools.mcp_client_call import execute_tool_call_simple
tool_response = asyncio.run(
execute_tool_call_simple(
response=response,
connection=self.mcp_config,
)
)
return {"content": [{"type": "text", "text": tool_response}]}
elif exists(self.mcp_urls):
from swarms.tools.mcp_client_call import execute_multiple_tools_on_multiple_mcp_servers_sync
tool_response = execute_multiple_tools_on_multiple_mcp_servers_sync(
responses=response,
urls=self.mcp_urls,
output_type="json",
)
return {"content": [{"type": "text", "text": str(tool_response)}]}
else:
raise AgentMCPConnectionError(
"mcp_url must be either a string URL or MCPConnection object"

Loading…
Cancel
Save