Skip to content

Commit 0b75707

Browse files
authored
Feature/mcp support (#79)
* feat: Implement MCP server integration with navigation and tool execution capabilities - Added mcp_server.py to define basic math tools and server file retrieval. - Introduced mcp_servers.json for server configuration. - Updated poetry.lock to include MCP and related dependencies. - Enhanced test feature to validate MCP server connection and calculations. - Implemented MCP Navigation Agent for executing tools and managing resources. - Developed MCP tools for server communication and tool execution, including connection management and error handling. - Configured environment variables for MCP integration in BaseConfigManager. * working mcp client * bug fix * deps update * removed unwanted file * update gitignore * feat: Enhance MCP support with detailed documentation and configuration - Added MCP integration section in README.md, including quick start guide and example usage. - Introduced MCP Integration details in environment_variables.md, outlining configuration options. - Created MCP_Usage.md to provide comprehensive guidance on connecting Hercules to MCP servers and executing tools. - Updated simple_hercules.py to ensure MCP agents are properly set up. - Refactored mcp_tools.py for improved organization and clarity in MCP server communication. * mcp working code but not clean * updated mcp agent workflow
1 parent 1ecf45f commit 0b75707

File tree

6 files changed

+565
-524
lines changed

6 files changed

+565
-524
lines changed

testzeus_hercules/core/agents/base_nav_agent.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
class BaseNavAgent:
1616
agent_name: str = "base_nav_agent"
1717
prompt = "Base Agent"
18-
prompt = "Base Agent"
1918

2019
def __init__(self, model_config_list, llm_config_params: dict[str, Any], system_prompt: str | None, nav_executor: autogen.UserProxyAgent, agent_name: str = None, agent_prompt: str | None = None): # type: ignore
2120
"""
@@ -91,6 +90,12 @@ def register_tools(self) -> None:
9190
# Register the tools that were dynamically discovered
9291
return None
9392

93+
def shutdown(self) -> None:
94+
"""Shutdown the agent."""
95+
pass
96+
97+
# MCP shutdown is managed centrally in the runner; no agent-level scheduling here.
98+
9499
def load_tools(self, additional_tool_dirs: str = os.getenv("ADDITIONAL_TOOL_DIRS", "")) -> None:
95100
"""
96101
Dynamically load additional tools from directories or specific Python files
Lines changed: 84 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,77 +1,114 @@
11
"""MCP Navigation Agent for Model Context Protocol server interactions."""
22

3+
import asyncio
4+
35
from testzeus_hercules.core.agents.base_nav_agent import BaseNavAgent
6+
from testzeus_hercules.utils.mcp_helper import MCPHelper, set_mcp_agents
7+
from testzeus_hercules.utils.logger import logger
48

59
class McpNavAgent(BaseNavAgent):
610
"""MCP Navigation Agent for executing MCP server tools and managing resources."""
711

812
agent_name: str = "mcp_nav_agent"
9-
prompt = """# MCP Navigation Agent
13+
prompt = """### MCP Navigation Agent
14+
15+
You are an MCP (Model Context Protocol) Navigation Agent that assists the Testing Agent by discovering MCP servers, cataloging their exposed tools/resources, and executing the right tool calls to complete the task. Always begin by scanning all configured servers before taking any action.
16+
17+
---
18+
19+
#### 1. Core Functions
20+
21+
- **Discover servers**: Enumerate configured MCP servers and their connection status.
22+
- **Catalog capabilities**: List tools and resource namespaces for each connected server.
23+
- **Execute tools**: Call tools with correct parameters and handle responses.
24+
- **Retrieve resources**: Read resources by URI when required.
25+
- **Summarize results**: Capture server, tool, arguments, outputs; include timings/status if available.
26+
- **Stay on task**: Only perform actions required by the "TASK FOR HELPER"; use extra info cautiously.
27+
28+
---
29+
30+
#### 2. Operational Rules
31+
32+
1. **Previous Step Validation**
33+
- MANDATORY: Before any new action, explicitly review the previous step and its outcome.
34+
- Do not proceed if the prior critical step failed; address it first.
35+
36+
2. **Server Scan First**
37+
- Call `get_configured_mcp_servers`.
38+
- For each server, call `check_mcp_server_status`.
39+
- For connected servers, call `list_mcp_tools` to build a capability map.
40+
- If no server is connected, report INCOMPLETE and wait for initialization rather than guessing.
1041
11-
You are an MCP (Model Context Protocol) Navigation Agent responsible for executing tools and accessing resources from MCP servers. Your primary focus is on communicating with MCP servers and executing their available tools.
42+
3. **Sequential Execution**
43+
- Execute only one function/tool at a time and await its result before the next call.
1244
13-
## Core Responsibilities
45+
4. **Accurate Parameters**
46+
- Include all required parameters for every call; if unsure, pass explicit defaults.
47+
- Use server names exactly as discovered; do not invent names or tools.
1448
15-
- **Execute MCP Tools**: Call tools available on connected MCP servers
16-
- **Manage Resources**: Access and retrieve resources from MCP servers
17-
- **Server Communication**: Maintain connections and handle server interactions
18-
- **Result Processing**: Process tool execution results and provide clear summaries
49+
5. **Tool Selection**
50+
- Choose the minimal set of tools to satisfy the task.
51+
- If ambiguous, request clarification once with the discovered server/tool information.
1952
20-
## Available Functions
53+
6. **Validation & Idempotency**
54+
- Verify each result is sufficient before moving on.
55+
- Avoid redundant or duplicate calls to the same tool with the same arguments.
2156
22-
1. **get_configured_mcp_servers()**: Get list of configured MCP servers and their status
23-
2. **initialize_mcp_connections()**: Initialize connections to configured MCP servers
24-
3. **check_mcp_server_status(server_name)**: Check if a specific server is connected
25-
4. **execute_mcp_tool(server_name, tool_name, arguments)**: Execute a specific tool on an MCP server
26-
5. **list_mcp_tools(server_name)**: List all available tools from a server
27-
6. **get_mcp_resource(server_name, resource_uri)**: Retrieve a resource from a server
57+
7. **Error Handling**
58+
- If a call fails due to validation or parameter mismatch, correct and retry at most once.
59+
- Provide precise errors; do not retry blindly or loop.
2860
29-
## Core Rules
61+
8. **Data Usage**
62+
- Use provided test data and prior results to build inputs.
63+
- Use `data_only` vs `all_fields` appropriately when extracting structured content.
3064
31-
1. **Connection First**: Always check configured servers and initialize connections before using MCP tools
32-
2. **Use Correct Server Names**: Use server names from configuration
33-
3. **Sequential Execution**: Execute one function at a time, wait for response
34-
4. **Proper Parameters**: Always include all required parameters in function calls
35-
5. **Error Handling**: Handle connection errors and tool failures gracefully
36-
6. **Result Verification**: Verify each result before proceeding to next operation
65+
---
3766
38-
## Response Formats
67+
#### 3. Server and Tool Workflow (Default)
68+
1) `get_configured_mcp_servers`
69+
2) `check_mcp_server_status` for each server
70+
3) `list_mcp_tools` for each connected server
71+
4) Select and `execute_mcp_tool` in order; `get_mcp_resource` when required
72+
5) Verify outcomes and summarize
3973
40-
**Success:**
41-
```
42-
previous_step: [previous step summary]
43-
current_output: [DETAILED tool execution result with server response]
74+
---
75+
76+
#### 4. Response Formats
77+
78+
- **Success:**
79+
previous_step: [MANDATORY: Explicit review of previous step outcome and its impact on task progression]
80+
previous_step_status: [MANDATORY: COMPLETED_SUCCESSFULLY or FAILED or INCOMPLETE]
81+
current_output: [DETAILED EXPANDED COMPLETE LOSS LESS output with server, tool, arguments, and results]
82+
Task_Completion_Validation: [MANDATORY before terminating: Explicit confirmation that ALL task requirements have been met]
4483
##FLAG::SAVE_IN_MEM##
4584
##TERMINATE TASK##
46-
```
4785
48-
**Error:**
49-
```
50-
previous_step: [previous step summary]
51-
current_output: [Error description and attempted resolution]
86+
- **Information Request:**
87+
previous_step: [MANDATORY: Explicit review of previous step outcome and its impact on task progression]
88+
previous_step_status: [MANDATORY: COMPLETED_SUCCESSFULLY or FAILED or INCOMPLETE]
89+
current_output: [Describe missing info or ambiguity; summarize discovered servers and tools]
5290
##TERMINATE TASK##
53-
```
5491
55-
## Error Handling
92+
- **Error:**
93+
previous_step: [MANDATORY: Explicit review of previous step outcome and its impact on task progression]
94+
previous_step_status: [MANDATORY: COMPLETED_SUCCESSFULLY or FAILED or INCOMPLETE]
95+
current_output: [Issue description; server/tool involved; parameters; single corrective attempt summary]
96+
##TERMINATE TASK##
5697
57-
- Check server connectivity before tool execution
58-
- Provide clear error messages for failed operations
59-
- Suggest alternative approaches when tools fail
60-
- Document all server interactions for debugging
98+
**CRITICAL RULE: DO NOT TERMINATE if previous_step_status is FAILED or INCOMPLETE unless you have addressed and resolved the issue first.**
6199
62100
Available Test Data: $basic_test_information
63101
"""
64102

65-
def __init__(self, model_config_list, llm_config_params, system_prompt, nav_executor, agent_name=None, agent_prompt=None):
66-
"""Initialize MCP Navigation Agent and connect to configured MCP servers."""
67-
super().__init__(model_config_list, llm_config_params, system_prompt, nav_executor, agent_name, agent_prompt)
68-
69-
70-
71103
def register_tools(self) -> None:
72104
"""Register MCP-specific tools and MCP server toolkits for the agent."""
73105
self.load_tools()
74-
75-
76-
77-
106+
try:
107+
self._mcp_init_task = asyncio.create_task(set_mcp_agents(self, self.nav_executor))
108+
except Exception as e:
109+
logger.error("Failed to schedule MCP initialization: %s", e)
110+
111+
async def shutdown(self) -> None:
112+
"""Shutdown the agent."""
113+
await MCPHelper.instance().destroy()
114+
await super().shutdown()

testzeus_hercules/core/runner.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ async def initialize(self) -> None:
9292
async def clean_up(self) -> None:
9393
"""Clean up resources."""
9494
if self.simple_hercules:
95-
await self.simple_hercules.clean_up_plan()
95+
await self.simple_hercules.shutdown()
9696
if self.browser_manager:
9797
await self.browser_manager.stop_playwright()
9898

@@ -204,9 +204,11 @@ async def shutdown(self) -> None:
204204
Shuts down the components gracefully.
205205
"""
206206
logger.info("Shutting down...")
207+
# Then shut down browser components
207208
if self.browser_manager:
208209
await self.browser_manager.stop_playwright()
209210
PlaywrightManager.close_all_instances()
211+
210212
self.shutdown_event.set()
211213

212214
async def wait_for_exit(self) -> None:

testzeus_hercules/core/simple_hercules.py

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@
4848
)
4949
from testzeus_hercules.utils.timestamp_helper import get_timestamp_str
5050
from testzeus_hercules.utils.ui_messagetype import MessageType
51-
from testzeus_hercules.core.tools.mcp_tools import set_mcp_agents
5251

5352
nest_asyncio.apply() # type: ignore
5453
from autogen import oai
@@ -422,6 +421,13 @@ def get_chat_logs_dir(self) -> str | None:
422421
# Get paths from config with timestamp
423422
return get_global_conf().get_source_log_folder_path(self.stake_id)
424423

424+
async def shutdown(self) -> None:
425+
"""Shutdown the SimpleHercules instance."""
426+
await self.clean_up_plan()
427+
for agent in self.agents_map.values():
428+
if isinstance(agent, autogen.ConversableAgent):
429+
await agent.shutdown()
430+
425431
def set_chat_logs_dir(self, chat_logs_dir: str) -> None:
426432
"""
427433
Set the directory for saving chat logs.
@@ -499,14 +505,6 @@ async def __initialize_agents(self) -> dict[str, autogen.ConversableAgent]:
499505
agents_map["time_keeper_nav_agent"] = self.__create_time_keeper_nav_agent(agents_map["time_keeper_nav_executor"])
500506
agents_map["mcp_nav_executor"] = self.__create_mcp_nav_executor_agent()
501507
agents_map["mcp_nav_agent"] = self.__create_mcp_nav_agent(agents_map["mcp_nav_executor"])
502-
# Provide MCP agents to the MCP toolkit layer for native registration
503-
try:
504-
505-
set_mcp_agents(agents_map["mcp_nav_agent"], agents_map["mcp_nav_executor"])
506-
except Exception as e:
507-
logger.error(
508-
f"Failed to set MCP agents for toolkit registration: {e}"
509-
)
510508
agents_map["planner_agent"] = self.__create_planner_agent(agents_map["user"])
511509
return agents_map
512510

0 commit comments

Comments
 (0)