Files
ajarbot/mcp_servers/excalidraw/excalidraw_mcp.py

90 lines
3.1 KiB
Python
Raw Normal View History

"""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
]