Features: - FastMCP-based MCP server for Claude Code agent recommendations - Hierarchical agent architecture with 39 specialized agents - 10 MCP tools with enhanced LLM-friendly descriptions - Composed agent support with parent-child relationships - Project root configuration for focused recommendations - Smart agent recommendation engine with confidence scoring Server includes: - Core recommendation tools (recommend_agents, get_agent_content) - Project management tools (set/get/clear project roots) - Discovery tools (list_agents, server_stats) - Hierarchy navigation (get_sub_agents, get_parent_agent, get_agent_hierarchy) All tools properly annotated for calling LLM clarity with detailed arguments, return values, and usage examples.
181 lines
6.5 KiB
Python
181 lines
6.5 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Test agent library functionality without external dependencies
|
|
"""
|
|
|
|
import json
|
|
import os
|
|
import yaml
|
|
from pathlib import Path
|
|
from typing import List, Dict, Optional
|
|
from dataclasses import dataclass, asdict
|
|
|
|
@dataclass
|
|
class AgentInfo:
|
|
name: str
|
|
emoji: str
|
|
description: str
|
|
tools: List[str]
|
|
content: str
|
|
file_path: str
|
|
|
|
@dataclass
|
|
class ProjectRoots:
|
|
directories: List[str]
|
|
base_path: str
|
|
description: str = ""
|
|
|
|
class SimpleAgentLibrary:
|
|
def __init__(self, templates_path: Path):
|
|
self.templates_path = templates_path
|
|
self.agents: Dict[str, AgentInfo] = {}
|
|
self.roots: Optional[ProjectRoots] = None
|
|
|
|
def load_agents(self):
|
|
"""Load all agent templates from the directory"""
|
|
if not self.templates_path.exists():
|
|
print(f"⚠️ Templates path not found: {self.templates_path}")
|
|
return
|
|
|
|
for file_path in self.templates_path.glob("*.md"):
|
|
try:
|
|
content = file_path.read_text()
|
|
|
|
# Extract YAML frontmatter
|
|
if content.startswith("---\n"):
|
|
parts = content.split("---\n", 2)
|
|
if len(parts) >= 3:
|
|
frontmatter = yaml.safe_load(parts[1])
|
|
body = parts[2]
|
|
|
|
agent = AgentInfo(
|
|
name=frontmatter.get("name", file_path.stem),
|
|
emoji=frontmatter.get("emoji", "🤖"),
|
|
description=frontmatter.get("description", ""),
|
|
tools=frontmatter.get("tools", []),
|
|
content=body.strip(),
|
|
file_path=str(file_path)
|
|
)
|
|
|
|
self.agents[agent.name] = agent
|
|
|
|
except Exception as e:
|
|
print(f"❌ Error loading {file_path}: {e}")
|
|
|
|
print(f"✅ Loaded {len(self.agents)} agents")
|
|
return self.agents
|
|
|
|
def set_roots(self, directories: List[str], base_path: str, description: str = ""):
|
|
"""Set project roots for focused analysis"""
|
|
self.roots = ProjectRoots(directories, base_path, description)
|
|
return f"✅ Set project roots: {directories} in {base_path}"
|
|
|
|
def get_roots(self) -> Optional[Dict]:
|
|
"""Get current project roots"""
|
|
if self.roots:
|
|
return asdict(self.roots)
|
|
return {"message": "No roots configured"}
|
|
|
|
def clear_roots(self):
|
|
"""Clear project roots"""
|
|
self.roots = None
|
|
return "✅ Cleared project roots"
|
|
|
|
def recommend_agents(self, task: str, project_context: str = "") -> List[Dict]:
|
|
"""Simple recommendation logic"""
|
|
recommendations = []
|
|
task_lower = task.lower()
|
|
|
|
# Keywords to agent mapping
|
|
keywords = {
|
|
"python": ["🔮-python-mcp-expert", "🧪-testing-integration-expert"],
|
|
"fastapi": ["🚄-fastapi-expert"],
|
|
"docker": ["🐳-docker-infrastructure-expert"],
|
|
"security": ["🔒-security-audit-expert"],
|
|
"documentation": ["📖-readme-expert"],
|
|
"subagent": ["🎭-subagent-expert"],
|
|
"test": ["🧪-testing-integration-expert"],
|
|
"mcp": ["🔮-python-mcp-expert"]
|
|
}
|
|
|
|
# Find matching agents
|
|
for keyword, agent_names in keywords.items():
|
|
if keyword in task_lower:
|
|
for agent_name in agent_names:
|
|
if agent_name in self.agents:
|
|
agent = self.agents[agent_name]
|
|
recommendations.append({
|
|
"name": agent.name,
|
|
"emoji": agent.emoji,
|
|
"description": agent.description,
|
|
"confidence": 0.8,
|
|
"reason": f"Matches keyword '{keyword}' in task description"
|
|
})
|
|
|
|
# If no specific matches, suggest subagent expert
|
|
if not recommendations and "🎭-subagent-expert" in self.agents:
|
|
agent = self.agents["🎭-subagent-expert"]
|
|
recommendations.append({
|
|
"name": agent.name,
|
|
"emoji": agent.emoji,
|
|
"description": agent.description,
|
|
"confidence": 0.6,
|
|
"reason": "General purpose recommendation for task planning"
|
|
})
|
|
|
|
return recommendations[:5] # Limit to top 5
|
|
|
|
def test_functionality():
|
|
"""Test the agent library functionality"""
|
|
print("🚀 Testing Claude Agent Library...")
|
|
|
|
# Initialize with local templates
|
|
templates_path = Path(__file__).parent / "agent_templates"
|
|
library = SimpleAgentLibrary(templates_path)
|
|
|
|
# Load agents
|
|
agents = library.load_agents()
|
|
|
|
print(f"\n📋 Available agents ({len(agents)}):")
|
|
for name, agent in list(agents.items())[:5]: # Show first 5
|
|
print(f" {agent.emoji} {name}")
|
|
print(f" {agent.description[:80]}...")
|
|
|
|
# Test recommendations
|
|
print("\n🔧 Testing recommendations...")
|
|
tasks = [
|
|
"I need help with Python FastAPI development",
|
|
"How do I write better documentation?",
|
|
"I need to containerize my application with Docker",
|
|
"Help me set up testing for my project"
|
|
]
|
|
|
|
for task in tasks:
|
|
print(f"\n📝 Task: \"{task}\"")
|
|
recs = library.recommend_agents(task)
|
|
for rec in recs:
|
|
print(f" {rec['emoji']} {rec['name']} (confidence: {rec['confidence']:.1f})")
|
|
print(f" → {rec['reason']}")
|
|
|
|
# Test roots functionality
|
|
print("\n🗂️ Testing roots functionality...")
|
|
result = library.set_roots(['src/api', 'src/backend'], '/home/rpm/project', 'API development focus')
|
|
print(result)
|
|
|
|
roots = library.get_roots()
|
|
print(f"Current roots: {json.dumps(roots, indent=2)}")
|
|
|
|
clear_result = library.clear_roots()
|
|
print(clear_result)
|
|
|
|
# Test getting agent content
|
|
print("\n📄 Testing agent content retrieval...")
|
|
if "🎭-subagent-expert" in agents:
|
|
content = agents["🎭-subagent-expert"].content
|
|
print(f"Content preview (first 200 chars):")
|
|
print(content[:200] + "..." if len(content) > 200 else content)
|
|
|
|
print("\n✅ All tests completed!")
|
|
|
|
if __name__ == "__main__":
|
|
test_functionality() |