|
|
""" |
|
|
MCP Client for Secure AI Agents Suite |
|
|
Handles communication with Model Context Protocol servers |
|
|
""" |
|
|
|
|
|
import json |
|
|
import asyncio |
|
|
import aiohttp |
|
|
import logging |
|
|
from typing import Dict, List, Optional, Any |
|
|
|
|
|
|
|
|
class MCPClient: |
|
|
"""Client for communicating with MCP (Model Context Protocol) servers.""" |
|
|
|
|
|
def __init__(self, mcp_server_url: str, config: Dict[str, Any] = None): |
|
|
self.mcp_server_url = mcp_server_url.rstrip('/') |
|
|
self.config = config or {} |
|
|
self.session: Optional[aiohttp.ClientSession] = None |
|
|
self.available_tools: Dict[str, Any] = {} |
|
|
self.logger = logging.getLogger(__name__) |
|
|
|
|
|
async def __aenter__(self): |
|
|
self.session = aiohttp.ClientSession() |
|
|
await self.discover_tools() |
|
|
return self |
|
|
|
|
|
async def __aexit__(self, exc_type, exc_val, exc_tb): |
|
|
if self.session: |
|
|
await self.session.close() |
|
|
|
|
|
async def discover_tools(self): |
|
|
"""Discover available tools from MCP server.""" |
|
|
try: |
|
|
|
|
|
|
|
|
self.available_tools = { |
|
|
"crm_update": { |
|
|
"name": "crm_update", |
|
|
"description": "Update customer information in CRM system", |
|
|
"parameters": { |
|
|
"customer_id": "string", |
|
|
"field": "string", |
|
|
"value": "string" |
|
|
} |
|
|
}, |
|
|
"ticket_create": { |
|
|
"name": "ticket_create", |
|
|
"description": "Create support ticket", |
|
|
"parameters": { |
|
|
"title": "string", |
|
|
"description": "string", |
|
|
"priority": "string", |
|
|
"category": "string" |
|
|
} |
|
|
}, |
|
|
"calendar_schedule": { |
|
|
"name": "calendar_schedule", |
|
|
"description": "Schedule calendar events", |
|
|
"parameters": { |
|
|
"title": "string", |
|
|
"datetime": "string", |
|
|
"attendees": "array", |
|
|
"description": "string" |
|
|
} |
|
|
}, |
|
|
"search_contacts": { |
|
|
"name": "search_contacts", |
|
|
"description": "Search for contacts in CRM", |
|
|
"parameters": { |
|
|
"query": "string", |
|
|
"limit": "integer" |
|
|
} |
|
|
}, |
|
|
"get_calendar_events": { |
|
|
"name": "get_calendar_events", |
|
|
"description": "Get calendar events", |
|
|
"parameters": { |
|
|
"date": "string", |
|
|
"limit": "integer" |
|
|
} |
|
|
} |
|
|
} |
|
|
self.logger.info(f"Discovered {len(self.available_tools)} tools") |
|
|
except Exception as e: |
|
|
self.logger.error(f"Error discovering tools: {e}") |
|
|
|
|
|
async def call_tool(self, tool_name: str, parameters: Dict[str, Any], session_id: str = "default") -> Dict[str, Any]: |
|
|
"""Call a tool on the MCP server.""" |
|
|
if tool_name not in self.available_tools: |
|
|
raise ValueError(f"Tool {tool_name} not available. Available tools: {list(self.available_tools.keys())}") |
|
|
|
|
|
request = { |
|
|
"tool": tool_name, |
|
|
"parameters": parameters, |
|
|
"session_id": session_id |
|
|
} |
|
|
|
|
|
try: |
|
|
|
|
|
|
|
|
result = await self._simulate_tool_call(tool_name, parameters) |
|
|
self.logger.info(f"Tool call successful: {tool_name}") |
|
|
return result |
|
|
except Exception as e: |
|
|
error_msg = f"MCP tool call exception: {str(e)}" |
|
|
self.logger.error(error_msg) |
|
|
return {"error": error_msg} |
|
|
|
|
|
async def _simulate_tool_call(self, tool_name: str, parameters: Dict[str, Any]) -> Dict[str, Any]: |
|
|
"""Simulate MCP tool calls for demo purposes.""" |
|
|
await asyncio.sleep(0.1) |
|
|
|
|
|
if tool_name == "crm_update": |
|
|
return { |
|
|
"success": True, |
|
|
"message": f"Customer {parameters.get('customer_id')} updated successfully", |
|
|
"field": parameters.get("field"), |
|
|
"value": parameters.get("value") |
|
|
} |
|
|
elif tool_name == "ticket_create": |
|
|
ticket_id = f"TKT-{hash(str(parameters)) % 10000:04d}" |
|
|
return { |
|
|
"success": True, |
|
|
"ticket_id": ticket_id, |
|
|
"message": f"Support ticket {ticket_id} created successfully", |
|
|
"title": parameters.get("title"), |
|
|
"priority": parameters.get("priority") |
|
|
} |
|
|
elif tool_name == "calendar_schedule": |
|
|
event_id = f"EVT-{hash(str(parameters)) % 10000:04d}" |
|
|
return { |
|
|
"success": True, |
|
|
"event_id": event_id, |
|
|
"message": f"Calendar event '{parameters.get('title')}' scheduled for {parameters.get('datetime')}", |
|
|
"datetime": parameters.get("datetime"), |
|
|
"attendees": parameters.get("attendees", []) |
|
|
} |
|
|
elif tool_name == "search_contacts": |
|
|
|
|
|
mock_contacts = [ |
|
|
{"id": "001", "name": "John Smith", "email": "john.smith@company.com", "company": "Tech Corp"}, |
|
|
{"id": "002", "name": "Sarah Johnson", "email": "sarah.j@startup.io", "company": "Startup Inc"}, |
|
|
{"id": "003", "name": "Mike Chen", "email": "mchen@enterprise.com", "company": "Enterprise LLC"} |
|
|
] |
|
|
return { |
|
|
"success": True, |
|
|
"contacts": mock_contacts, |
|
|
"count": len(mock_contacts) |
|
|
} |
|
|
elif tool_name == "get_calendar_events": |
|
|
|
|
|
mock_events = [ |
|
|
{"id": "evt001", "title": "Team Meeting", "datetime": "2025-11-29 14:00", "location": "Conference Room A"}, |
|
|
{"id": "evt002", "title": "Client Call", "datetime": "2025-11-29 16:30", "location": "Virtual"} |
|
|
] |
|
|
return { |
|
|
"success": True, |
|
|
"events": mock_events, |
|
|
"count": len(mock_events) |
|
|
} |
|
|
else: |
|
|
return {"success": False, "error": f"Unknown tool: {tool_name}"} |
|
|
|
|
|
def get_available_tools(self) -> List[str]: |
|
|
"""Get list of available tool names.""" |
|
|
return list(self.available_tools.keys()) |
|
|
|
|
|
def get_tool_info(self, tool_name: str) -> Optional[Dict[str, Any]]: |
|
|
"""Get detailed information about a specific tool.""" |
|
|
return self.available_tools.get(tool_name) |
|
|
|
|
|
|
|
|
|
|
|
ENTERPRISE_MCP_CLIENT = None |
|
|
CONSUMER_MCP_CLIENT = None |
|
|
CREATIVE_MCP_CLIENT = None |
|
|
VOICE_MCP_CLIENT = None |
|
|
|
|
|
|
|
|
async def get_enterprise_mcp_client(): |
|
|
"""Get or create enterprise MCP client.""" |
|
|
global ENTERPRISE_MCP_CLIENT |
|
|
if ENTERPRISE_MCP_CLIENT is None: |
|
|
ENTERPRISE_MCP_CLIENT = MCPClient("https://enterprise-mcp.example.com") |
|
|
async with ENTERPRISE_MCP_CLIENT: |
|
|
pass |
|
|
return ENTERPRISE_MCP_CLIENT |
|
|
|
|
|
|
|
|
async def get_consumer_mcp_client(): |
|
|
"""Get or create consumer MCP client.""" |
|
|
global CONSUMER_MCP_CLIENT |
|
|
if CONSUMER_MCP_CLIENT is None: |
|
|
CONSUMER_MCP_CLIENT = MCPClient("https://consumer-mcp.example.com") |
|
|
async with CONSUMER_MCP_CLIENT: |
|
|
pass |
|
|
return CONSUMER_MCP_CLIENT |
|
|
|
|
|
|
|
|
async def get_creative_mcp_client(): |
|
|
"""Get or create creative MCP client.""" |
|
|
global CREATIVE_MCP_CLIENT |
|
|
if CREATIVE_MCP_CLIENT is None: |
|
|
CREATIVE_MCP_CLIENT = MCPClient("https://creative-mcp.example.com") |
|
|
async with CREATIVE_MCP_CLIENT: |
|
|
pass |
|
|
return CREATIVE_MCP_CLIENT |
|
|
|
|
|
|
|
|
async def get_voice_mcp_client(): |
|
|
"""Get or create voice MCP client.""" |
|
|
global VOICE_MCP_CLIENT |
|
|
if VOICE_MCP_CLIENT is None: |
|
|
VOICE_MCP_CLIENT = MCPClient("https://voice-mcp.example.com") |
|
|
async with VOICE_MCP_CLIENT: |
|
|
pass |
|
|
return VOICE_MCP_CLIENT |