#!/usr/bin/env python3
"""
Validate that all expected MCP tools are registered correctly.
This MUST pass before any installation.
"""
import sys
import asyncio
from pathlib import Path
# Add source to path
sys.path.insert(0, str(Path(__file__).parent.parent / "src"))
from amicus.server import mcp
# Expected tools with their minimum version
EXPECTED_TOOLS = {
# Core tools (v0.1.0+)
"update_state",
"add_task",
"read_state",
"broadcast_message",
"claim_task",
"complete_task",
"is_safe_path",
"execute_safe_command",
"heartbeat",
"toggle_tracking",
# Cluster management tools (v0.3.0+)
"register_node",
"get_best_model",
# Anti-idle system tools (v0.4.0+)
"set_agent_status",
"claim_best_task",
"assess_workload",
}
MINIMUM_TOOL_COUNT = len(EXPECTED_TOOLS)
async def validate_tools():
"""Validate all tools are registered correctly."""
print("=" * 60)
print("AMICUS MCP TOOL VALIDATION")
print("=" * 60)
print()
# Get registered tools
try:
tools = await mcp.get_tools()
except Exception as e:
print(f"✗ FAILED: Could not get tools from MCP server")
print(f" Error: {e}")
return False
# Convert to set of names
tool_names = set()
for tool in tools:
if isinstance(tool, str):
tool_names.add(tool)
elif hasattr(tool, 'name'):
tool_names.add(tool.name)
else:
tool_names.add(str(tool))
# Check tool count
print(f"Registered tools: {len(tool_names)}")
print(f"Expected minimum: {MINIMUM_TOOL_COUNT}")
print()
if len(tool_names) < MINIMUM_TOOL_COUNT:
print(f"✗ FAILED: Tool count too low ({len(tool_names)} < {MINIMUM_TOOL_COUNT})")
print(f" This is a regression - tools have been lost!")
return False
# Check for expected tools
missing_tools = EXPECTED_TOOLS - tool_names
if missing_tools:
print(f"✗ FAILED: Missing expected tools:")
for tool in sorted(missing_tools):
print(f" - {tool}")
return False
# Check for unexpected duplicates
if len(tool_names) != len(tools):
print(f"⚠ WARNING: Possible duplicate tools detected")
print(f" Unique names: {len(tool_names)}")
print(f" Total tools: {len(tools)}")
# List all registered tools
print("✓ All expected tools present:")
for tool in sorted(tool_names):
status = "✓" if tool in EXPECTED_TOOLS else "+"
print(f" {status} {tool}")
print()
print("=" * 60)
print(f"✓ VALIDATION PASSED: {len(tool_names)} tools registered")
print("=" * 60)
return True
def main():
"""Run validation and exit with appropriate code."""
try:
result = asyncio.run(validate_tools())
sys.exit(0 if result else 1)
except Exception as e:
print(f"\n✗ VALIDATION FAILED WITH EXCEPTION:")
print(f" {type(e).__name__}: {e}")
import traceback
traceback.print_exc()
sys.exit(2)
if __name__ == "__main__":
main()