"""Configuration tools for ComfyUI MCP Server
Thin MCP wrapper around DefaultsManager for configuration management.
NO business logic - delegates to orchestrator.
"""
from typing import Any
from fastmcp import FastMCP
from src.orchestrators.defaults import DefaultsManager
from src.utils import get_global_logger
logger = get_global_logger("MCP_Server.tools.configuration")
def register_configuration_tools(
mcp: FastMCP, model_validator: callable, defaults_manager: DefaultsManager
):
"""Register configuration tools with the MCP server
Args:
mcp: FastMCP server instance
model_validator: Callable that returns available models (for list_models tool)
defaults_manager: Orchestrator for defaults management
"""
@mcp.tool()
def list_models() -> dict:
"""List all available checkpoint models in ComfyUI.
Returns a list of model names that can be used with generation tools.
This helps AI agents choose appropriate models for different use cases.
"""
models = model_validator() # Get available models from injected validator
return {
"models": models,
"count": len(models),
"default": "v1-5-pruned-emaonly.ckpt" if models else None,
}
@mcp.tool()
def get_defaults() -> dict:
"""Get current effective defaults for image, audio, and video generation.
Returns merged defaults from all sources (runtime, config, env, hardcoded).
Shows what values will be used when parameters are not explicitly provided.
"""
return {
"image": defaults_manager.get_all_defaults("image"),
"audio": defaults_manager.get_all_defaults("audio"),
"video": defaults_manager.get_all_defaults("video"),
}
@mcp.tool()
def set_defaults(
image: dict[str, Any] | None = None,
audio: dict[str, Any] | None = None,
video: dict[str, Any] | None = None,
persist: bool = False,
) -> dict:
"""Set runtime defaults for image, audio, and/or video generation.
Args:
image: Optional dict of default values for image generation (e.g., {"model": "sd_xl_base_1.0.safetensors", "width": 1024})
audio: Optional dict of default values for audio generation (e.g., {"model": "ace_step_v1_3.5b.safetensors", "seconds": 30})
video: Optional dict of default values for video generation (e.g., {"model": "wan2.2_vae.safetensors", "width": 1280, "duration": 5})
persist: If True, write defaults to config file (~/.config/comfy-mcp/config.json). Otherwise, changes are ephemeral.
Returns:
Success status and any validation errors (e.g., invalid model names).
"""
results = {}
errors = []
if image:
result = defaults_manager.set_defaults("image", image)
if "error" in result or "errors" in result:
errors.extend(result.get("errors", [result.get("error")]))
else:
results["image"] = result
if persist:
persist_result = defaults_manager.persist_defaults("image")
if "error" in persist_result:
errors.append(
f"Failed to persist image defaults: {persist_result['error']}"
)
if audio:
result = defaults_manager.set_defaults("audio", audio)
if "error" in result or "errors" in result:
errors.extend(result.get("errors", [result.get("error")]))
else:
results["audio"] = result
if persist:
persist_result = defaults_manager.persist_defaults("audio")
if "error" in persist_result:
errors.append(
f"Failed to persist audio defaults: {persist_result['error']}"
)
if video:
result = defaults_manager.set_defaults("video", video)
if "error" in result or "errors" in result:
errors.extend(result.get("errors", [result.get("error")]))
else:
results["video"] = result
if persist:
persist_result = defaults_manager.persist_defaults("video")
if "error" in persist_result:
errors.append(
f"Failed to persist video defaults: {persist_result['error']}"
)
if errors:
return {"success": False, "errors": errors}
return {"success": True, "updated": results}