Add MCP delegation bridge and diagram tools

**Features Added**:

1. **Agent Registry (agent_registry.py)**
   - Thread-safe global singleton for MCP tool access to Agent instance
   - Enables MCP tools to call Agent.delegate() without circular imports
   - Registered at bot startup in bot_runner.py

2. **Sub-Agent Manager (sub_agent_manager.py)**
   - Watchdog system monitoring sub-agent lifecycle
   - Detects hung agents (5min timeout, 30s check interval)
   - Auto-cleanup and status tracking

3. **delegate_task MCP Tool (mcp_tools.py)**
   - Exposes Agent.delegate() to Claude via MCP protocol
   - Enables parallel sub-agent execution via tool calls
   - Supports specialist prompts and agent ID caching

4. **Memory Write Locks (memory_system.py)**
   - Thread-safe writes to prevent file corruption
   - Protects write_memory(), update_soul(), update_user()

5. **Diagram Tools**
   - Mermaid MCP server (flowcharts, sequence diagrams, etc.)
   - Excalidraw MCP server (hand-drawn style diagrams)
   - Config files in config/ directory

6. **Adapter Improvements**
   - Enhanced error handling across all adapters
   - Unified logging patterns

**Testing**: Ready for parallel sub-agent testing

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-03-01 14:34:24 -07:00
parent dd5beb11c2
commit e909cc0044
13 changed files with 1081 additions and 26 deletions

View File

@@ -0,0 +1,86 @@
"""Mermaid MCP Server Integration.
Manages the external @peng-shawn/mermaid-mcp-server process for diagram generation.
Architecture:
Garvis → (stdio) → mermaid-mcp-server (Node.js) → Puppeteer → PNG images
"""
import os
from pathlib import Path
from typing import Any, Dict, List
import yaml
_CONFIG_FILE = Path("config/mermaid_mcp.yaml")
def _load_config() -> Dict[str, Any]:
"""Load Mermaid MCP configuration from YAML and env vars."""
config = {}
if _CONFIG_FILE.exists():
try:
with open(_CONFIG_FILE, encoding="utf-8") as f:
config = yaml.safe_load(f) or {}
except Exception:
pass # Use defaults if config fails to load
mermaid = config.get("mermaid_mcp", {})
# Apply env var overrides
if os.getenv("MERMAID_ENABLED"):
mermaid["enabled"] = os.getenv("MERMAID_ENABLED").lower() in ("true", "1")
if os.getenv("MERMAID_OUTPUT_DIR"):
mermaid["output_dir"] = os.getenv("MERMAID_OUTPUT_DIR")
if os.getenv("MERMAID_DEFAULT_FORMAT"):
mermaid["default_format"] = os.getenv("MERMAID_DEFAULT_FORMAT")
if os.getenv("MERMAID_THEME"):
mermaid["theme"] = os.getenv("MERMAID_THEME")
# Set defaults if not configured
mermaid.setdefault("enabled", True)
mermaid.setdefault("output_dir", "downloads/diagrams/mermaid")
mermaid.setdefault("default_format", "png")
mermaid.setdefault("theme", "default")
return mermaid
def is_mermaid_enabled() -> bool:
"""Check if Mermaid MCP integration is enabled."""
config = _load_config()
return config.get("enabled", True)
def get_mermaid_server_config() -> Dict[str, Any]:
"""Build the MCP server configuration for Agent SDK registration.
Returns:
Dict with command, args, and env for subprocess execution
"""
config = _load_config()
output_dir = config.get("output_dir", "downloads/diagrams/mermaid")
# Ensure output directory exists
Path(output_dir).mkdir(parents=True, exist_ok=True)
# Build environment variables for the MCP server
env = {
"PATH": os.environ.get("PATH", ""),
"HOME": os.environ.get("HOME", os.environ.get("USERPROFILE", "")),
"APPDATA": os.environ.get("APPDATA", ""),
"TEMP": os.environ.get("TEMP", os.environ.get("TMP", "")),
}
# Add config as env vars for the server
env["MERMAID_OUTPUT_DIR"] = str(Path(output_dir).absolute())
env["MERMAID_DEFAULT_FORMAT"] = config.get("default_format", "png")
env["MERMAID_THEME"] = config.get("theme", "default")
return {
"command": "npx",
"args": ["-y", "@peng-shawn/mermaid-mcp-server"],
"env": env,
}
# Tool names exposed by mermaid-mcp-server
# Based on @peng-shawn/mermaid-mcp-server documentation
MERMAID_TOOLS: List[str] = [
"render_mermaid", # Main tool: convert Mermaid syntax to PNG
]