Skip to content

Commit e7cfaa7

Browse files
hybridindieJohn D
andauthored
feat: expand workflow template library (#26)
* feat: expand workflow template library * fix: address PR feedback on workflow templates --------- Co-authored-by: John D <johnd@localhost>
1 parent 34042d4 commit e7cfaa7

File tree

6 files changed

+545
-26
lines changed

6 files changed

+545
-26
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ docker run --rm ghcr.io/hybridindie/comfyui-mcp:latest --help
131131
| `upscale_image` | Upscale an image using a model-based upscaler. Params: image (filename), upscale_model (default: RealESRGAN_x4plus.pth). |
132132
| `run_workflow` | Submit arbitrary ComfyUI workflow JSON. Inspected for dangerous nodes before execution. Set `wait=True` to block until complete and return outputs. |
133133
| `summarize_workflow` | Summarize a workflow's structure, data flow, models, and parameters. Supports `format="text"` (default) or `format="mermaid"` for diagram markup. |
134-
| `create_workflow` | Create a workflow from a template (txt2img, img2img, upscale, inpaint, txt2vid_animatediff, txt2vid_wan) with parameter overrides. |
134+
| `create_workflow` | Create a workflow from templates including txt2img/img2img/upscale/inpaint, txt2vid_animatediff/txt2vid_wan, controlnet_canny/controlnet_depth/controlnet_openpose, ip_adapter, lora_stack, face_restore, flux_txt2img, and sdxl_txt2img. |
135135
| `modify_workflow` | Apply batch operations (add_node, remove_node, set_input, connect, disconnect) to a workflow. |
136136
| `validate_workflow` | Validate workflow structure, server compatibility, and security. |
137137

src/comfyui_mcp/server.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ def _register_all_tools(
107107
model_checker=model_checker,
108108
sanitizer=sanitizer,
109109
)
110-
register_workflow_tools(server, client, audit, rate_limiters["read"], inspector)
110+
register_workflow_tools(server, client, audit, rate_limiters["read"], inspector, sanitizer)
111111
register_model_tools(
112112
mcp=server,
113113
client=client,

src/comfyui_mcp/tools/workflow.py

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,44 @@
1111
from comfyui_mcp.client import ComfyUIClient
1212
from comfyui_mcp.security.inspector import WorkflowInspector
1313
from comfyui_mcp.security.rate_limit import RateLimiter
14+
from comfyui_mcp.security.sanitizer import PathSanitizer, PathValidationError
1415
from comfyui_mcp.workflow.operations import apply_operations
1516
from comfyui_mcp.workflow.templates import create_from_template
1617
from comfyui_mcp.workflow.validation import validate_workflow as _validate_workflow
1718

19+
_PATH_LIKE_TEMPLATE_PARAMS = {
20+
"model",
21+
"model_name",
22+
"motion_module",
23+
"controlnet_model",
24+
"ipadapter_model",
25+
"clip_vision_model",
26+
"lora_name",
27+
"face_restore_model",
28+
"image",
29+
"mask",
30+
}
31+
32+
33+
def _sanitize_template_params(
34+
param_dict: dict[str, Any], sanitizer: PathSanitizer
35+
) -> dict[str, Any]:
36+
"""Sanitize filename-like template params to block traversal/null-byte inputs."""
37+
sanitized = dict(param_dict)
38+
for key in _PATH_LIKE_TEMPLATE_PARAMS:
39+
value = sanitized.get(key)
40+
if isinstance(value, str):
41+
sanitized[key] = sanitizer.validate_path_segment(value, label=key)
42+
return sanitized
43+
1844

1945
def register_workflow_tools(
2046
mcp: FastMCP,
2147
client: ComfyUIClient,
2248
audit: AuditLogger,
2349
limiter: RateLimiter,
2450
inspector: WorkflowInspector,
51+
sanitizer: PathSanitizer,
2552
) -> dict[str, Any]:
2653
"""Register workflow composition tools."""
2754
tool_fns: dict[str, Any] = {}
@@ -30,13 +57,16 @@ def register_workflow_tools(
3057
async def create_workflow(template: str, params: str = "{}") -> str:
3158
"""Create a ComfyUI workflow from a template with optional parameter overrides.
3259
33-
Available templates: txt2img, img2img, upscale, inpaint, txt2vid_animatediff, txt2vid_wan.
60+
Available templates: txt2img, img2img, upscale, inpaint, txt2vid_animatediff,
61+
txt2vid_wan, controlnet_canny, controlnet_depth, controlnet_openpose,
62+
ip_adapter, lora_stack, face_restore, flux_txt2img, sdxl_txt2img.
3463
3564
Args:
3665
template: Template name (e.g. 'txt2img', 'img2img')
3766
params: Optional JSON string of parameter overrides.
3867
Common params: prompt, negative_prompt, width, height,
39-
steps, cfg, model, denoise.
68+
steps, cfg, model, denoise, controlnet_model,
69+
control_strength, lora_name, lora_strength.
4070
"""
4171
limiter.check("create_workflow")
4272
try:
@@ -47,7 +77,12 @@ async def create_workflow(template: str, params: str = "{}") -> str:
4777
if not isinstance(param_dict, dict):
4878
raise ValueError('params must be a JSON object (e.g. {"key": "value"})')
4979

50-
wf = create_from_template(template, param_dict)
80+
try:
81+
clean_params = _sanitize_template_params(param_dict, sanitizer)
82+
except PathValidationError as e:
83+
raise ValueError(str(e)) from e
84+
85+
wf = create_from_template(template, clean_params)
5186
audit.log(
5287
tool="create_workflow",
5388
action="created",

0 commit comments

Comments
 (0)