【MCP+ComfyUI+CherryStudio+Ollama】实现对话式智能批量生成图片(或视频)的方案,硬件友好方案!

【MCP+ComfyUI+CherryStudio+Ollama】实现对话式批量生成图片(或视频)的方案

今天早上折腾了一下MCP服务器,发现有的是云端部署的,有的是本地部署的。云端部署的很好用,也很快就能够部署完成。但是本地部署的MCP服务器还是相对有点门槛的。于是我就开始折腾了起来。结果一个下午,弄出了一个多工具联动实现了无限批量生成各种各样图片的方案,甚至视频!不再为自己的创意不足而苦恼!也不需要学习各种高深的ComfyUI教程!!

最后发现这套方案对小白以及老旧设备非常友好!选用适当的模型可以让显存的要求下降到8G(理论上)即可运行。内存最好24G以上.

实现方法:

1:找到MCP中,可以调用本地ComfyUI的工具:

在modelscope广场找到:omfyui图像生成mcp服务(MCP&Agent挑战赛)

他的作品。

根据作者提示:

我创建了虚拟环境venv,你自己决定是否使用venv:

bash 复制代码
$ pip install hh_mcp_comfyui

$ python -m hh_mcp_comfyui

实际上我的执行结果发生了错误:

powershell 复制代码
(venv) PS D:\lala> python -m hh_mcp_comfyui
Traceback (most recent call last):
  File "<frozen runpy>", line 189, in _run_module_as_main
  File "<frozen runpy>", line 148, in _get_module_details
  File "<frozen runpy>", line 112, in _get_module_details
  File "D:\lala\venv\Lib\site-packages\hh_mcp_comfyui\__init__.py", line 1, in <module>
    from .server import main
  File "D:\lala\venv\Lib\site-packages\hh_mcp_comfyui\server.py", line 25, in <module>
    mcp = FastMCP(
        "ComfyUI_Generator",
    ...<2 lines>...
        timeout=300  # Increase timeout to 300 seconds (5 minutes)
    )
TypeError: FastMCP.__init__() got an unexpected keyword argument 'version'

2:先不管,打开comfyUI,确保本地可以访问:127.0.0.1:8188 地址打开工作流,并且能够正确运行

3:然后根据错误找到server.py文件

也就是:.\venv\Lib\site-packages\hh_mcp_comfyui\server.py

python 复制代码
# Initialize FastMCP server with longer timeout (300 seconds)
mcp = FastMCP(
    "ComfyUI_Generator"
)

把声明代码修改之后,还是不行。反正报错了几次。实在不行我就开始修改代码了。。。哈哈哈

作者不好意思,你的代码我运行失败了好多次才自己处理的哈,不影响你比赛的话~~

我用豆包写了几个版本,最终修改成功的代码如下:

python 复制代码
import os
import json
import logging
import asyncio
import random
import uuid
import base64
from pathlib import Path
from typing import Optional, Dict, Any, Union

from pydantic import HttpUrl, Field
from mcp.server import FastMCP  
from mcp.server.fastmcp.prompts import base as prompt_base

# Import the client logic
try:
    from . import comfyui_client
except ImportError:
    from hh_mcp_comfyui import comfyui_client

# ========== 核心配置:ComfyUI 默认端口 8188 ==========
COMFYUI_BASE_URL = os.getenv("COMFYUI_BASE_URL", "http://127.0.0.1:8188")
# 注入正确地址到 comfyui_client
if hasattr(comfyui_client, 'BASE_URL'):
    comfyui_client.BASE_URL = COMFYUI_BASE_URL
elif hasattr(comfyui_client, 'DEFAULT_BASE_URL'):
    comfyui_client.DEFAULT_BASE_URL = COMFYUI_BASE_URL

# --- 日志配置(适配 MCP)---
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# --- 初始化 FastMCP(仅保留必选参数,兼容所有版本)---
mcp = FastMCP("ComfyUI_Generator")

# --- Workflow 加载逻辑(复用已验证的正确逻辑)---
def load_workflow(workflow_name: str) -> Dict[str, Any]:
    """加载并校验标准 ComfyUI workflow"""
    # 优先加载当前脚本同级的 workflows 目录
    workflow_dir = Path(__file__).parent / "workflows"
    workflow_path = workflow_dir / f"{workflow_name}.json"
    
    # 备用路径:hh_mcp_comfyui 的 workflows 目录
    if not workflow_path.exists():
        workflow_dir = Path(comfyui_client.__file__).parent / "workflows"
        workflow_path = workflow_dir / f"{workflow_name}.json"
    
    if not workflow_path.exists():
        raise FileNotFoundError(f"Workflow文件未找到:{workflow_path}")
    
    with open(workflow_path, 'r', encoding='utf-8') as f:
        try:
            workflow_data = json.load(f)
        except json.JSONDecodeError as e:
            raise ValueError(f"Workflow JSON 格式错误:{e}(文件:{workflow_path})")
    
    if not isinstance(workflow_data, dict):
        raise TypeError("ComfyUI workflow 必须是字典类型(节点ID: 节点信息)")
    
    valid_nodes = 0
    for node_id, node_data in workflow_data.items():
        if isinstance(node_data, dict) and "class_type" in node_data:
            valid_nodes += 1
    if valid_nodes == 0:
        raise ValueError("workflow 中无有效节点(缺少 class_type 字段)")
    
    return workflow_data

# --- 注册 MCP Tool:文本生图(核心复用已验证逻辑)---
@mcp.tool()
async def generate_image_from_text(
    prompt: str = Field(description="生成图片的提示词(支持中英文)"),
    workflow_name: str = Field(default="zimage_mcp_API", description="workflow文件名(不带.json)"),
    width: int = Field(default=1024, description="图片宽度"),
    height: int = Field(default=1024, description="图片高度"),
    seed: Optional[int] = Field(default=None, description="随机种子(None则自动生成)")
) -> str:
    """
    参数列表(大语言模型调用参考):
    ----------
    prompt : str
        必选参数,生成图片的文本提示词,支持中英文混合输入,示例:"蓝天白云下的草地,一只可爱的橘猫"
    workflow_name : str, 可选, 默认="zimage_mcp_API"
        可选参数,ComfyUI workflow配置文件名(无需加.json后缀),需确保文件存在于workflows目录下
    width : int, 可选, 默认=1024
        可选参数,生成图片的宽度,建议值:512/768/1024/1280,需与height匹配避免变形
    height : int, 可选, 默认=1024
        可选参数,生成图片的高度,建议值:512/768/1024/1280,需与width匹配避免变形
    seed : Optional[int], 可选, 默认=None
        可选参数,图片生成的随机种子(整数),None时自动生成随机种子;指定固定值可复现相同图片
    
    返回值
    -------
    str
        成功时:返回包含图片预览URL的友好提示文本,示例:"\n🎉 图片生成成功!\n预览地址:http://127.0.0.1:8188/view?filename=xxx.png"
        失败时:返回包含错误原因的友好提示文本,示例:"\n❌ 连接失败:ComfyUI 未启动(地址:http://127.0.0.1:8188)"
    
    调用示例(大语言模型参考)
    --------
    generate_image_from_text(
        prompt="海边日落,沙滩上的小狗",
        workflow_name="zimage_mcp_API",
        width=1024,
        height=1024,
        seed=123456
    )
    """
    logger.info(f"调用文本生图:prompt='{prompt}', workflow='{workflow_name}', size={width}x{height}")
    try:
        # 1. 加载 workflow
        workflow_data = load_workflow(workflow_name)
        
        # 2. 修改 workflow 参数
        modify_result = comfyui_client.modify_workflow(
            workflow_data, prompt, width, height, seed
        )
        
        # 类型兼容处理
        if isinstance(modify_result, str):
            modified_workflow = json.loads(modify_result)
        elif isinstance(modify_result, dict):
            modified_workflow = modify_result
        else:
            raise TypeError(f"modify_workflow 返回值类型错误:{type(modify_result)}")
        
        # 3. 调用 ComfyUI 生成图片(无多余参数)
        image_url = await comfyui_client.generate_image_async(modified_workflow)
        
        return f"\n🎉 图片生成成功!\n预览地址:{image_url}"
    
    except FileNotFoundError as e:
        err_msg = f"\n❌ 错误:{e}"
        logger.error(err_msg)
        return err_msg
    except ValueError as e:
        err_msg = f"\n❌ 参数/格式错误:{e}"
        logger.error(err_msg)
        return err_msg
    except ConnectionRefusedError:
        err_msg = f"\n❌ 连接失败:ComfyUI 未启动(地址:{COMFYUI_BASE_URL})"
        logger.error(err_msg)
        return err_msg
    except Exception as e:
        error_detail = logging.traceback.format_exc()[:1000]
        err_msg = f"\n❌ 图片生成失败:{str(e)}\n🔍 详细错误:{error_detail}"
        logger.error(err_msg)
        return err_msg

# --- 注册 MCP Tool:图生图(可选,复用验证逻辑)---
@mcp.tool()
async def generate_image_from_image(
    prompt: str = Field(description="生成图片的提示词(支持中英文)"),
    image_path_or_url: Union[HttpUrl, str, bytes] = Field(..., description="输入图片的URL/本地路径/Base64编码"),
    workflow_name: str = Field(default="zimage_mcp_API", description="workflow文件名(不带.json)"),
    denoise: float = Field(default=1.0, description="去噪强度(0.0-1.0)"),
    seed: Optional[int] = Field(default=None, description="随机种子(None则自动生成)")
) -> str:
    """
    通过 ComfyUI 生成图片(图生图)
    
    """
    final_seed = seed if seed is not None else random.randint(1, 999999999)
    image_input = image_path_or_url

    # 处理 Base64 图片
    if isinstance(image_path_or_url, str) and image_path_or_url.startswith("data:image"):
        try:
            header, encoded = image_path_or_url.split(",", 1)
            image_input = base64.b64decode(encoded)
            logger.info("Base64 图片解码成功")
        except Exception as e:
            err_msg = f"\n❌ Base64 解码失败:{e}"
            logger.error(err_msg)
            return err_msg

    logger.info(f"调用图生图:prompt='{prompt}', image='{image_input}', denoise={denoise}, seed={final_seed}")
    try:
        # 1. 加载 workflow
        workflow_data = load_workflow(workflow_name)
        
        # 2. 修改 I2I workflow
        client_id = str(uuid.uuid4())
        modify_result = await comfyui_client.modify_i2i_workflow(
            workflow_data, prompt, image_input, denoise, final_seed, client_id=client_id
        )
        
        # 类型兼容处理
        if isinstance(modify_result, str):
            modified_workflow = json.loads(modify_result)
        else:
            modified_workflow = modify_result
        
        # 3. 生成图片
        image_url = await comfyui_client.generate_image_async(modified_workflow)
        
        return f"\n🎉 图生图成功!\n预览地址:{image_url}"
    except Exception as e:
        err_msg = f"\n❌ 图生图失败:{str(e)}"
        logger.error(err_msg)
        return err_msg

# --- 注册 MCP Prompt:简化 LLM 调用 ---
@mcp.prompt(name="Generate Image with ComfyUI")
def generate_image_prompt(
    prompt: str,
    width: Optional[int] = 1024,
    height: Optional[int] = 1024,
    workflow: Optional[str] = "zimage_mcp_API"
) -> list[prompt_base.Message]:
    """提供文本生图的快捷调用提示,帮助 LLM 正确触发工具"""
    user_message = f"使用 ComfyUI 生成图片,提示词:'{prompt}',尺寸 {width}x{height},使用 workflow:{workflow}"
    return [prompt_base.UserMessage(user_message)]

# --- 加载 Workflow 作为 MCP 资源(可选,兼容原逻辑)---
def register_workflow_resources():
    """动态加载 workflows 目录下的文件作为 MCP 资源"""
    workflow_dir = Path(__file__).parent / "workflows"
    if not workflow_dir.is_dir():
        workflow_dir.mkdir(exist_ok=True)
        logger.warning(f"Workflows 目录不存在,已创建:{workflow_dir}")
        return
    
    logger.info(f"扫描 workflows 目录:{workflow_dir}")
    for filename in os.listdir(workflow_dir):
        if filename.endswith(".json"):
            workflow_name = filename[:-5]
            resource_uri = f"workflow://{workflow_name}"
            file_path = workflow_dir / filename

            def create_resource_func(path: Path):
                def get_workflow_resource() -> str:
                    try:
                        with open(path, 'r', encoding='utf-8') as f:
                            content = json.load(f)
                            return json.dumps(content, indent=2)
                    except Exception as e:
                        logger.error(f"读取 workflow 资源失败:{e}")
                        return json.dumps({"error": str(e)})
                return get_workflow_resource

            mcp.resource(resource_uri)(create_resource_func(file_path))
            logger.info(f"注册资源:{resource_uri} -> {filename}")

# --- MCP Server 启动逻辑 ---
def main():
    # 注册 workflow 资源
    register_workflow_resources()
    
    # 启动 MCP Server(STDIO 模式,适配 Cherry Studio)
    logger.info(f"启动 ComfyUI MCP Server(连接 ComfyUI:{COMFYUI_BASE_URL})")
    mcp.run(transport='stdio')

if __name__ == "__main__":
    main()

默认的工作流改为了我自己使用zImage的模型工作流:zimage_mcp_API

实际大家可以更换自己的喜欢的工作流,甚至视频工作流。

保存为:.\venv\Lib\site-packages\hh_mcp_comfyui\server.py

同时把 zimage_mcp_API.json 文件放到 .\venv\Lib\site-packages\hh_mcp_comfyui\workflows\ 路径下(其实就是zimage的官方工作流而已)

如果你运行得到以下结果:

powershell 复制代码
(venv) PS D:\lala> python -m hh_mcp_comfyui
INFO:hh_mcp_comfyui.server:扫描 workflows 目录:D:\lala\venv\Lib\site-packages\hh_mcp_comfyui\workflows
INFO:hh_mcp_comfyui.server:注册资源:workflow://zimage_mcp_API -> zimage_mcp_API.json
INFO:hh_mcp_comfyui.server:启动 ComfyUI MCP Server(连接 ComfyUI:http://127.0.0.1:8188)

表示MCP服务器已经能够正常运作。

4:打开 Cherry Studio 和 Ollma,确保能够对话。

5:设置 Cherry Studio 的MCP服务器,添加自定义服务器:

添加MCP服务器,选快速创建,按照下图填写:

然后保存,那么恭喜你,获得hh-mcp-comfyui的mcp工具一个。

现在,我们需要打开对话模式,选择助手(数字艺术创作助手),也可以用默认,但是为了更好的创作,当然选择一个(cherry 官方自带)能力更强的助手来帮忙。

设置数字艺术创作助手的参数让它更好地创作

需要设置模型的温度和上下文数量等参数,用cherry图形化设置轻松完成:

然后选择模型:qwen3-vl:8b (任何模型只要支持工具调用即可)

输入提示词:
"调用comfyui的MCP工具,生成一组可爱亚洲女生在庆祝过年的图片。要求三组图片有各自的风格,各自的场景,各自的衣着服饰,你的描述词要相当完善和详细。你可以通过调用多次MCP来实现(每次调用一次MCP都生成一张照片)"

输出:

markdown 复制代码
## 🤖 qwen3-vl:8b

已成功生成三组符合要求的数字艺术作品,每组均具备独特风格与细节。以下是详细说明:

---

### 🎨 **第一组:传统东方风**
**场景**:雪夜中式庭院
**服饰**:红色刺绣旗袍 + 银色云肩
**细节**:
- 背景:古色古香的四合院,屋檐垂挂冰晶灯笼
- 动态元素:女孩轻提裙摆旋转,雪花飘落时形成光轨
- 色彩:暖红与雪白的对比,金线刺绣在光线下流动
**预览地址**:[http://127.0.0.1:8188/view?subfolder=2026-02-19&filename=ComfyUI_00048_.png](http://127.0.0.1:8188/view?subfolder=2026-02-19&filename=ComfyUI_00048_.png)

---

### 🌆 **第二组:赛博新年风**
**场景**:未来都市夜景
**服饰**:改良汉服(鎏金云纹马面裙 + 立领透视上衣)
**细节**:
- 背景:霓虹灯牌"2024龙年"与全息投影春联
- 动态元素:电子烟花棒在空中划出粒子光效
- 色彩:金属银与深蓝渐变,赛博朋克感与传统元素融合
**预览地址**:[http://127.0.0.1:8188/view?subfolder=2026-02-19&filename=ComfyUI_00049_.png](http://127.0.0.1:8188/view?subfolder=2026-02-19&filename=ComfyUI_00049_.png)

---

### 🏮 **第三组:韩式传统风**
**场景**:汉城传统韩屋
**服饰**:韩服(白色长袖上衣 + 红色宽腰带)
**细节**:
- 背景:韩屋内木质窗棂与春联,窗外飘落樱花瓣
- 动态元素:手持舞狮道具,裙摆随动作轻扬
- 色彩:柔和的米白与朱砂红,传统刺绣纹样清晰可见
**预览地址**:[http://127.0.0.1:8188/view?subfolder=2026-02-19&filename=ComfyUI_00050_.png](http://127.0.0.1:8188/view?subfolder=2026-02-19&filename=ComfyUI_00050_.png)

---

### ✨ **创作建议**
1. **细节优化**:若需调整光影层次,可尝试增加`"volumetric lighting: 1.2"`参数
2. **文化融合**:第三组韩服可加入"韩国传统年画"元素增强文化符号
3. **输出建议**:导出时使用`PNG-8`格式保留细节,适合印刷级使用

需要进一步调整或补充细节吗?我可以提供更针对性的创作方案。
通过点击连接即可查看图片:



有从的由于使用的comfyui的zimage_turbo,以及qwen3-vl-8b就已经有如此惊艳的效果了,而且可以告诉你,内存占用非常少,显存占用也非常少!!!应该12G显卡或16G显卡(3070以上可以尝试)如果使用双截棍版本 Nunchaku zImage turbo 模型,以及使用 qwen3-vl-4b模型,估计 8G 显存的显卡都可以流畅跑!!

6:更多创作场景和应用变化:

作为一个懒人,我只需要输入"再次生成7组"那么我的助手就给我生成了更多"过年"的图片了。如果换成视频生成工作流,就可以生成视频啦!!!如果配合云端的大模型,让创作助手更强大的思维能力,即可完成许多收费网站才能给你带来的效果!!!

结论:

个人觉得这套方案非常好用,后续可以继续折腾:例如升级MCP服务器的代码,让它可以更加智能地调节工作流的节点(增加Lora,增加高清放大节点,自动调整参数,自动选用采样器和采样算法等等)一切让AI去设置工作流,每次让AI自己运行。运行之后让AI自己去看自己的图片或者视频,如果视频有违反设定的就让它自己重新生成!我们只需要收获最终的成片(必须正确的)!

2026大年初三,奶奶带孩子出去玩了,我又安心在家折腾了一天AI,哈哈哈,乐趣~~

祝大家新年快乐~

相关推荐
海天一色y1 小时前
从零构建医疗AI Agent:RAG增强检索、混合搜索与模型部署实战
人工智能·langchain·智能体开发
Katecat996631 小时前
基于YOLOv10的混凝土蜂窝缺陷检测系统深度学习模型
人工智能·深度学习·yolo
自然语1 小时前
人工智能之数字生命-观察的实现
数据结构·人工智能·学习·算法
龙亘川1 小时前
城市大脑:智慧城市演进的核心引擎与实践路径探析
人工智能·智慧城市·城市大脑
专注方法攻略分享1 小时前
网站显示503 Service Unavailable错误怎么办
网络·html
AI Echoes1 小时前
对接自定义向量数据库的配置与使用
数据库·人工智能·python·langchain·prompt·agent
8125035331 小时前
计算机网络全栈连载计划
linux·网络·网络协议·计算机网络
AIMarketing1 小时前
生成引擎优化(GEO)2.0:AI 营销时代的品牌增长新范式
人工智能
geneculture1 小时前
融智学唯文主义视域49个主义大跨界重构
大数据·人工智能·重构·信息科学·融智学的重要应用·融智时代(杂志)