Skip to content

Commit 4f1b2fa

Browse files
committed
fix agent tests, fix agent cleanup, fix plan output, add mcp functions
1 parent 1a1c84e commit 4f1b2fa

File tree

7 files changed

+113
-50
lines changed

7 files changed

+113
-50
lines changed

src/backend/v3/magentic_agents/common/lifecycle.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
from typing import Any
55

66
from azure.ai.projects.aio import AIProjectClient
7-
from azure.identity import InteractiveBrowserCredential
87
from azure.identity.aio import DefaultAzureCredential
98
from semantic_kernel.agents.azure_ai.azure_ai_agent import AzureAIAgent
109
from semantic_kernel.connectors.mcp import MCPStreamableHttpPlugin
@@ -35,7 +34,7 @@ async def close(self) -> None:
3534
if self._stack is None:
3635
return
3736
try:
38-
self.cred.close()
37+
#self.cred.close()
3938
await self._stack.aclose()
4039
finally:
4140
self._stack = None

src/backend/v3/orchestration/human_approval_manager.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,9 @@ def plan_to_obj(self, magentic_context, ledger) -> MPlan:
190190
line = line.replace('*', '').strip()
191191
break
192192

193+
if not found_agent:
194+
# If no agent found, assign to ProxyAgent if available
195+
found_agent = "MagenticAgent"
193196
# If line indicates a following list of actions (e.g. "Assign **EnhancedResearchAgent**
194197
# to gather authoritative data on:") save and prefix to the steps
195198
if line.endswith(':'):

src/mcp_server/mcp_server.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,23 @@
22
MACAE MCP Server - FastMCP server with organized tools and services.
33
"""
44

5+
import argparse
6+
import logging
57
###
68
import sys
7-
import argparse
89
from pathlib import Path
9-
from fastmcp import FastMCP
10-
from fastmcp.server.auth.providers.jwt import JWTVerifier
11-
import logging
1210
from typing import Optional
1311

12+
from config.settings import config
1413
from core.factory import MCPToolFactory
14+
from fastmcp import FastMCP
15+
from fastmcp.server.auth.providers.jwt import JWTVerifier
16+
from services.data_tool_service import DataToolService
17+
from services.general_service import GeneralService
1518
from services.hr_service import HRService
19+
from services.marketing_service import MarketingService
20+
from services.product_service import ProductService
1621
from services.tech_support_service import TechSupportService
17-
from services.general_service import GeneralService
18-
from services.data_tool_service import DataToolService
19-
from config.settings import config
2022

2123
# Setup logging
2224
logging.basicConfig(level=logging.INFO)
@@ -28,6 +30,8 @@
2830
# Initialize services
2931
factory.register_service(HRService())
3032
factory.register_service(TechSupportService())
33+
factory.register_service(MarketingService())
34+
factory.register_service(ProductService())
3135
factory.register_service(GeneralService())
3236

3337
# Register DataToolService with the dataset path
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
"""
2+
Marketing MCP tools service.
3+
"""
4+
5+
from typing import Any, Dict
6+
7+
from core.factory import Domain, MCPToolBase
8+
from utils.date_utils import format_date_for_user
9+
from utils.formatters import format_error_response, format_success_response
10+
11+
12+
class MarketingService(MCPToolBase):
13+
"""Marketing tools for employee onboarding and management."""
14+
15+
def __init__(self):
16+
super().__init__(Domain.HR)
17+
18+
def register_tools(self, mcp) -> None:
19+
"""Register Marketing tools with the MCP server."""
20+
21+
@mcp.tool(tags={self.domain.value})
22+
async def generate_press_release(key_information_for_press_release: str) -> str:
23+
"""This is a function to draft / write a press release. You must call the function by passing the key information that you want to be included in the press release."""
24+
25+
return f"Look through the conversation history. Identify the content. Now you must generate a press release based on this content {key_information_for_press_release}. Make it approximately 2 paragraphs."
26+
27+
@mcp.tool(tags={self.domain.value})
28+
async def handle_influencer_collaboration(influencer_name: str, campaign_name: str) -> str:
29+
"""Handle collaboration with an influencer."""
30+
31+
return f"Collaboration with influencer '{influencer_name}' for campaign '{campaign_name}' handled."
32+
33+
@property
34+
def tool_count(self) -> int:
35+
"""Return the number of tools provided by this service."""
36+
return 2
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
"""
2+
Product MCP tools service.
3+
"""
4+
5+
from typing import Any, Dict
6+
7+
from core.factory import Domain, MCPToolBase
8+
from utils.date_utils import format_date_for_user
9+
from utils.formatters import format_error_response, format_success_response
10+
11+
12+
class ProductService(MCPToolBase):
13+
"""Product tools for employee onboarding and management."""
14+
15+
def __init__(self):
16+
super().__init__(Domain.HR)
17+
18+
def register_tools(self, mcp) -> None:
19+
"""Register Product tools with the MCP server."""
20+
21+
@mcp.tool(tags={self.domain.value})
22+
async def get_product_info() -> str:
23+
"""Get information about the different products and phone plans available, including roaming services."""
24+
product_info = """
25+
26+
# Simulated Phone Plans
27+
28+
## Plan A: Basic Saver
29+
- **Monthly Cost**: $25
30+
- **Data**: 5GB
31+
- **Calls**: Unlimited local calls
32+
- **Texts**: Unlimited local texts
33+
34+
## Plan B: Standard Plus
35+
- **Monthly Cost**: $45
36+
- **Data**: 15GB
37+
- **Calls**: Unlimited local and national calls
38+
- **Texts**: Unlimited local and national texts
39+
40+
## Plan C: Premium Unlimited
41+
- **Monthly Cost**: $70
42+
- **Data**: Unlimited
43+
- **Calls**: Unlimited local, national, and international calls
44+
- **Texts**: Unlimited local, national, and international texts
45+
46+
# Roaming Extras Add-On Pack
47+
- **Cost**: $15/month
48+
- **Data**: 1GB
49+
- **Calls**: 200 minutes
50+
- **Texts**: 200 texts
51+
52+
"""
53+
return f"Here is information to relay back to the user. Repeat back all the relevant sections that the user asked for: {product_info}."
54+
55+
56+
@property
57+
def tool_count(self) -> int:
58+
"""Return the number of tools provided by this service."""
59+
return 1

src/tests/agents/test_foundry_integration.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,13 +157,13 @@ async def test_mcp_functionality(self):
157157
if not agent.mcp or not agent.mcp.url:
158158
pytest.skip("MCP configuration not available - skipping MCP test")
159159

160-
query = "Please greet Tom using an MCP tool"
160+
query = "Please greet Tom"
161161

162162
response = await self._get_agent_response(agent, query)
163163

164164
# Check for the expected MCP response indicator
165-
assert "Hello from MCP, Tom" in response, \
166-
f"Expected 'Hello from MCP, Tom' in MCP response, got: {response}"
165+
assert "Hello from MACAE MCP Server, Tom" in response, \
166+
f"Expected 'Hello from MACAE MCP Server, Tom' in MCP response, got: {response}"
167167

168168
except Exception as e:
169169
pytest.fail(f"MCP test failed with error: {e}")
Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +0,0 @@
1-
"""
2-
Integration tests for FoundryAgentTemplate functionality.
3-
Tests Bing search, RAG, MCP tools, and Code Interpreter capabilities.
4-
"""
5-
# pylint: disable=E0401, E0611, C0413
6-
7-
import asyncio
8-
import os
9-
import sys
10-
import time
11-
from pathlib import Path
12-
13-
import pytest
14-
15-
# Add the backend path to sys.path so we can import v3 modules
16-
backend_path = Path(__file__).parent.parent.parent / "backend"
17-
sys.path.insert(0, str(backend_path))
18-
19-
# Now import from the v3 package
20-
from v3.magentic_agents.proxy_agent import (DummyAgentThread, ProxyAgent,
21-
ProxyAgentResponseItem)
22-
23-
24-
@pytest.mark.asyncio
25-
async def test_proxy_agent(monkeypatch):
26-
"""Test the proxy agent."""
27-
# Mock the input function to simulate user input
28-
monkeypatch.setattr("builtins.input", lambda _: "Jane Doe")
29-
30-
agent = ProxyAgent()
31-
test_messages = [
32-
"More information needed. What is the name of the employee?"
33-
]
34-
35-
for message in test_messages:
36-
async for response in agent.invoke(message):
37-
assert "Human clarification: Jane Doe" in response.message.content, \
38-
f"Unexpected response: {response.message.content}"

0 commit comments

Comments
 (0)