**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>
90 lines
3.1 KiB
Python
90 lines
3.1 KiB
Python
"""Excalidraw MCP Server Integration.
|
|
|
|
Manages the external excalidraw-mcp server process for hand-drawn style diagram generation.
|
|
|
|
Architecture:
|
|
Garvis → (stdio) → excalidraw-mcp (Node.js) → Canvas API → PNG/SVG images
|
|
"""
|
|
|
|
import os
|
|
from pathlib import Path
|
|
from typing import Any, Dict, List
|
|
import yaml
|
|
|
|
_CONFIG_FILE = Path("config/excalidraw_mcp.yaml")
|
|
|
|
def _load_config() -> Dict[str, Any]:
|
|
"""Load Excalidraw 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
|
|
|
|
excalidraw = config.get("excalidraw_mcp", {})
|
|
|
|
# Apply env var overrides
|
|
if os.getenv("EXCALIDRAW_ENABLED"):
|
|
excalidraw["enabled"] = os.getenv("EXCALIDRAW_ENABLED").lower() in ("true", "1")
|
|
if os.getenv("EXCALIDRAW_OUTPUT_DIR"):
|
|
excalidraw["output_dir"] = os.getenv("EXCALIDRAW_OUTPUT_DIR")
|
|
if os.getenv("EXCALIDRAW_DEFAULT_EXPORT"):
|
|
excalidraw["default_export_type"] = os.getenv("EXCALIDRAW_DEFAULT_EXPORT")
|
|
|
|
# Set defaults if not configured
|
|
excalidraw.setdefault("enabled", True)
|
|
excalidraw.setdefault("output_dir", "downloads/diagrams/excalidraw")
|
|
excalidraw.setdefault("default_export_type", "png")
|
|
excalidraw.setdefault("canvas_width", 1920)
|
|
excalidraw.setdefault("canvas_height", 1080)
|
|
|
|
return excalidraw
|
|
|
|
def is_excalidraw_enabled() -> bool:
|
|
"""Check if Excalidraw MCP integration is enabled."""
|
|
config = _load_config()
|
|
return config.get("enabled", True)
|
|
|
|
def get_excalidraw_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/excalidraw")
|
|
|
|
# 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["EXCALIDRAW_OUTPUT_DIR"] = str(Path(output_dir).absolute())
|
|
env["EXCALIDRAW_DEFAULT_EXPORT"] = config.get("default_export_type", "png")
|
|
env["EXCALIDRAW_CANVAS_WIDTH"] = str(config.get("canvas_width", 1920))
|
|
env["EXCALIDRAW_CANVAS_HEIGHT"] = str(config.get("canvas_height", 1080))
|
|
|
|
return {
|
|
"command": "npx",
|
|
"args": ["-y", "excalidraw-mcp"],
|
|
"env": env,
|
|
}
|
|
|
|
# Tool names exposed by excalidraw-mcp
|
|
# Based on excalidraw-mcp documentation
|
|
EXCALIDRAW_TOOLS: List[str] = [
|
|
"create_diagram", # Create new Excalidraw diagram
|
|
"add_element", # Add shape/element to diagram
|
|
"export_diagram", # Export to PNG/SVG
|
|
"list_diagrams", # List saved diagrams
|
|
]
|