Skip to content

Commit 57c9eb1

Browse files
Copilotphrocker
andcommitted
Integrate MCP client with python-agent framework
Co-authored-by: phrocker <[email protected]>
1 parent a35f952 commit 57c9eb1

File tree

11 files changed

+569
-248
lines changed

11 files changed

+569
-248
lines changed
4.8 KB
Binary file not shown.

examples/mcp-client-example.py

Lines changed: 74 additions & 234 deletions
Original file line numberDiff line numberDiff line change
@@ -1,264 +1,104 @@
11
#!/usr/bin/env python3
22
"""
3-
Example MCP client integration with Sentrius MCP Proxy
3+
Example MCP client integration with Sentrius Python Agent
44
5-
This example shows how to connect to the Sentrius MCP proxy and use it
6-
with the existing Python agent framework.
5+
This example demonstrates how to use the integrated MCP functionality
6+
within the existing Sentrius Python agent framework.
77
"""
88

9+
import sys
910
import json
10-
import asyncio
11-
import websockets
12-
import requests
13-
from typing import Dict, Any, Optional
1411
import logging
12+
from pathlib import Path
13+
14+
# Add the python-agent directory to the path
15+
python_agent_dir = Path(__file__).parent.parent / "python-agent"
16+
sys.path.insert(0, str(python_agent_dir))
17+
18+
from utils.config_manager import ConfigManager
19+
from agents.mcp.mcp_agent import MCPAgent
1520

1621
logging.basicConfig(level=logging.INFO)
1722
logger = logging.getLogger(__name__)
1823

19-
class SentriusMCPClient:
24+
25+
def main():
2026
"""
21-
Client for communicating with Sentrius MCP Proxy
27+
Example usage of the integrated MCP agent
2228
"""
23-
24-
def __init__(self, base_url: str, jwt_token: str, user_id: str):
25-
self.base_url = base_url.rstrip('/')
26-
self.jwt_token = jwt_token
27-
self.user_id = user_id
28-
self.session = requests.Session()
29-
self.session.headers.update({
30-
'Authorization': f'Bearer {jwt_token}',
31-
'Content-Type': 'application/json'
32-
})
29+
try:
30+
# Initialize configuration manager
31+
config_path = python_agent_dir / "application.properties"
32+
config_manager = ConfigManager(str(config_path))
3333

34-
def send_mcp_request(self, method: str, params: Dict[str, Any] = None,
35-
communication_id: str = None) -> Dict[str, Any]:
36-
"""
37-
Send MCP request via HTTP
38-
"""
39-
if communication_id is None:
40-
communication_id = f"mcp-{method}-{id(self)}"
41-
42-
request_data = {
43-
"jsonrpc": "2.0",
44-
"id": f"{method}-{id(self)}",
45-
"method": method,
46-
"params": params or {}
47-
}
34+
# Create MCP agent using the integrated framework
35+
logger.info("Creating MCP agent with Sentrius integration...")
36+
mcp_agent = MCPAgent(config_manager)
4837

49-
headers = dict(self.session.headers)
50-
headers['communication_id'] = communication_id
38+
print("=== MCP Agent Examples ===\n")
5139

52-
url = f"{self.base_url}/api/v1/mcp/"
40+
# Example 1: Initialize and get capabilities
41+
print("1. Initializing MCP agent...")
42+
init_result = mcp_agent.execute_task()
43+
print(f"Initialization result: {json.dumps(init_result, indent=2)}\n")
5344

54-
try:
55-
response = self.session.post(url, json=request_data, headers=headers)
56-
response.raise_for_status()
57-
return response.json()
58-
except requests.RequestException as e:
59-
logger.error(f"MCP request failed: {e}")
60-
raise
61-
62-
async def connect_websocket(self) -> 'MCPWebSocketClient':
63-
"""
64-
Create WebSocket connection for real-time MCP communication
65-
"""
66-
ws_url = self.base_url.replace('http://', 'ws://').replace('https://', 'wss://')
67-
ws_url += f"/api/v1/mcp/ws?token=Bearer%20{self.jwt_token}&communication_id=ws-{id(self)}&user_id={self.user_id}"
45+
# Example 2: Ping test
46+
print("2. Testing connectivity...")
47+
ping_result = mcp_agent.execute_task({"operation": "ping"})
48+
print(f"Ping result: {json.dumps(ping_result, indent=2)}\n")
6849

69-
websocket = await websockets.connect(ws_url)
70-
return MCPWebSocketClient(websocket)
71-
72-
def get_capabilities(self) -> Dict[str, Any]:
73-
"""
74-
Get MCP proxy capabilities
75-
"""
76-
url = f"{self.base_url}/api/v1/mcp/capabilities"
77-
response = self.session.get(url)
78-
response.raise_for_status()
79-
return response.json()
80-
81-
def initialize(self) -> Dict[str, Any]:
82-
"""
83-
Initialize MCP session
84-
"""
85-
return self.send_mcp_request("initialize")
86-
87-
def ping(self) -> Dict[str, Any]:
88-
"""
89-
Send ping for connectivity check
90-
"""
91-
return self.send_mcp_request("ping")
92-
93-
def list_tools(self) -> Dict[str, Any]:
94-
"""
95-
List available tools
96-
"""
97-
return self.send_mcp_request("tools/list")
98-
99-
def call_tool(self, tool_name: str, arguments: Dict[str, Any]) -> Dict[str, Any]:
100-
"""
101-
Execute a tool
102-
"""
103-
params = {
104-
"name": tool_name,
105-
"arguments": arguments
106-
}
107-
return self.send_mcp_request("tools/call", params)
108-
109-
def list_resources(self) -> Dict[str, Any]:
110-
"""
111-
List available resources
112-
"""
113-
return self.send_mcp_request("resources/list")
114-
115-
def read_resource(self, uri: str) -> Dict[str, Any]:
116-
"""
117-
Read a specific resource
118-
"""
119-
params = {"uri": uri}
120-
return self.send_mcp_request("resources/read", params)
121-
122-
def list_prompts(self) -> Dict[str, Any]:
123-
"""
124-
List available prompts
125-
"""
126-
return self.send_mcp_request("prompts/list")
127-
128-
def get_prompt(self, name: str, arguments: Dict[str, Any] = None) -> Dict[str, Any]:
129-
"""
130-
Get a specific prompt
131-
"""
132-
params = {"name": name}
133-
if arguments:
134-
params["arguments"] = arguments
135-
return self.send_mcp_request("prompts/get", params)
136-
137-
138-
class MCPWebSocketClient:
139-
"""
140-
WebSocket client for real-time MCP communication
141-
"""
142-
143-
def __init__(self, websocket):
144-
self.websocket = websocket
145-
self.request_id_counter = 0
146-
147-
async def send_request(self, method: str, params: Dict[str, Any] = None) -> Dict[str, Any]:
148-
"""
149-
Send MCP request via WebSocket
150-
"""
151-
self.request_id_counter += 1
152-
request_id = f"{method}-{self.request_id_counter}"
50+
# Example 3: List available tools
51+
print("3. Listing available tools...")
52+
tools_result = mcp_agent.execute_task({"operation": "list_tools"})
53+
print(f"Tools result: {json.dumps(tools_result, indent=2)}\n")
15354

154-
request_data = {
155-
"jsonrpc": "2.0",
156-
"id": request_id,
157-
"method": method,
158-
"params": params or {}
159-
}
55+
# Example 4: Execute a secure command (if available)
56+
print("4. Executing secure command...")
57+
command_result = mcp_agent.execute_secure_command("ls -la")
58+
print(f"Command result: {json.dumps(command_result, indent=2)}\n")
16059

161-
await self.websocket.send(json.dumps(request_data))
60+
# Example 5: List resources
61+
print("5. Listing available resources...")
62+
resources_result = mcp_agent.execute_task({"operation": "list_resources"})
63+
print(f"Resources result: {json.dumps(resources_result, indent=2)}\n")
16264

163-
# Wait for response
164-
response_text = await self.websocket.recv()
165-
return json.loads(response_text)
166-
167-
async def close(self):
168-
"""
169-
Close WebSocket connection
170-
"""
171-
await self.websocket.close()
172-
173-
174-
# Example usage with Python agents
175-
class SentriusMCPAgent:
176-
"""
177-
Example agent that uses Sentrius MCP proxy
178-
"""
179-
180-
def __init__(self, base_url: str, jwt_token: str, user_id: str):
181-
self.mcp_client = SentriusMCPClient(base_url, jwt_token, user_id)
65+
# Example 6: List prompts
66+
print("6. Listing available prompts...")
67+
prompts_result = mcp_agent.execute_task({"operation": "list_prompts"})
68+
print(f"Prompts result: {json.dumps(prompts_result, indent=2)}\n")
18269

183-
def execute_secure_command(self, command: str) -> str:
184-
"""
185-
Execute a secure command using MCP tools
186-
"""
187-
try:
188-
# Initialize if needed
189-
init_response = self.mcp_client.initialize()
190-
logger.info(f"MCP initialized: {init_response}")
191-
192-
# List available tools
193-
tools_response = self.mcp_client.list_tools()
194-
logger.info(f"Available tools: {tools_response}")
195-
196-
# Execute the secure command tool
197-
result = self.mcp_client.call_tool("secure_command", {"command": command})
198-
199-
if result.get("error"):
200-
raise Exception(f"Tool execution failed: {result['error']}")
201-
202-
return result.get("result", {}).get("content", "No result")
203-
204-
except Exception as e:
205-
logger.error(f"MCP command execution failed: {e}")
206-
raise
207-
208-
async def real_time_interaction(self):
209-
"""
210-
Example of real-time MCP interaction via WebSocket
211-
"""
212-
ws_client = await self.mcp_client.connect_websocket()
70+
# Example 7: WebSocket communication example
71+
print("7. Testing WebSocket communication...")
72+
ws_result = mcp_agent.execute_task({"operation": "websocket_example"})
73+
print(f"WebSocket result: {json.dumps(ws_result, indent=2)}\n")
74+
75+
# Show agent information
76+
agent_info = mcp_agent.get_agent_info()
77+
print(f"Agent info: {json.dumps(agent_info, indent=2)}")
78+
79+
print("\n=== MCP Agent Examples Completed ===")
21380

214-
try:
215-
# Send ping
216-
ping_response = await ws_client.send_request("ping")
217-
logger.info(f"Ping response: {ping_response}")
218-
219-
# List tools
220-
tools_response = await ws_client.send_request("tools/list")
221-
logger.info(f"Tools: {tools_response}")
222-
223-
finally:
224-
await ws_client.close()
81+
except Exception as e:
82+
logger.error(f"Example execution failed: {e}")
83+
print(f"Error: {e}")
84+
return 1
85+
86+
return 0
22587

22688

227-
def main():
89+
def run_with_python_agent_main():
22890
"""
229-
Example usage
91+
Example of how to run the MCP agent using the main.py interface
23092
"""
231-
# Configuration - replace with actual values
232-
BASE_URL = "http://localhost:8080"
233-
JWT_TOKEN = "your-jwt-token-here"
234-
USER_ID = "your-user-id"
235-
236-
# Create agent
237-
agent = SentriusMCPAgent(BASE_URL, JWT_TOKEN, USER_ID)
238-
239-
try:
240-
# Test HTTP endpoint
241-
print("Testing HTTP MCP communication...")
242-
243-
# Get capabilities
244-
capabilities = agent.mcp_client.get_capabilities()
245-
print(f"Capabilities: {json.dumps(capabilities, indent=2)}")
246-
247-
# Test ping
248-
ping_result = agent.mcp_client.ping()
249-
print(f"Ping result: {json.dumps(ping_result, indent=2)}")
250-
251-
# Execute a secure command
252-
command_result = agent.execute_secure_command("ls -la")
253-
print(f"Command result: {command_result}")
254-
255-
# Test WebSocket communication
256-
print("\nTesting WebSocket MCP communication...")
257-
asyncio.run(agent.real_time_interaction())
258-
259-
except Exception as e:
260-
logger.error(f"Example failed: {e}")
93+
print("\n=== Running via python-agent main.py ===")
94+
print("You can also run the MCP agent directly using:")
95+
print(f"cd {python_agent_dir}")
96+
print("python main.py mcp --task-data '{\"operation\": \"ping\"}'")
97+
print("python main.py mcp --task-data '{\"operation\": \"list_tools\"}'")
98+
print("python main.py mcp --task-data '{\"operation\": \"call_tool\", \"tool_name\": \"secure_command\", \"arguments\": {\"command\": \"ls -la\"}}'")
26199

262100

263101
if __name__ == "__main__":
264-
main()
102+
exit_code = main()
103+
run_with_python_agent_main()
104+
sys.exit(exit_code)

python-agent/agents/base.py

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,23 @@ def __init__(self, config_manager, name: Optional[str] = None):
2424
keycloak_config = config_manager.get_keycloak_config()
2525

2626
# Create SentriusAgentConfig from the loaded configuration
27+
from services.config import KeycloakConfig, AgentConfig, LLMConfig
28+
2729
self.config = SentriusAgentConfig(
28-
keycloak_server_url=keycloak_config['server_url'],
29-
keycloak_realm=keycloak_config['realm'],
30-
keycloak_client_id=keycloak_config['client_id'],
31-
keycloak_client_secret=keycloak_config['client_secret'],
32-
agent_name_prefix=agent_config['name_prefix'],
33-
agent_type=agent_config['agent_type'],
34-
agent_callback_url=agent_config['callback_url'],
35-
api_url=agent_config['api_url'],
36-
heartbeat_interval=agent_config['heartbeat_interval']
30+
keycloak=KeycloakConfig(
31+
server_url=keycloak_config['server_url'],
32+
realm=keycloak_config['realm'],
33+
client_id=keycloak_config['client_id'],
34+
client_secret=keycloak_config['client_secret']
35+
),
36+
agent=AgentConfig(
37+
name_prefix=agent_config['name_prefix'],
38+
agent_type=agent_config['agent_type'],
39+
callback_url=agent_config['callback_url'],
40+
api_url=agent_config['api_url'],
41+
heartbeat_interval=agent_config['heartbeat_interval']
42+
),
43+
llm=LLMConfig() # Default LLM config
3744
)
3845

3946
# Initialize Sentrius agent
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# MCP Agent module

0 commit comments

Comments
 (0)