04-mcp-server案例分享-用豆包大模型 1.6 手搓文生图视频 MCP-server

1.前言

MCP Server(模型上下文协议服务器)是一种基于模型上下文协议(Model Context Protocol,简称MCP)构建的轻量级服务程序,旨在实现大型语言模型(LLM)与外部资源之间的高效、安全连接。MCP协议由Anthropic公司于2024年11月开源,其核心目标是解决AI应用中数据分散、接口不统一等问题,为开发者提供标准化的接口,使AI模型能够灵活访问本地资源和远程服务,从而提升AI助手的响应质量和工作效率。

上期手把手带大家手搓一个MCP-server 实现一个最简单的加法计算器的MCP-server. 对上期文章不太了解的小伙伴可以看我之前的文章

mcp-server案例分享-手搓一个MCP-server,手把手教你从本地开发到云部署全流程实战

昨天025年6月11日,火山引擎 FORCE 原动力大会开发者专场将围绕大模型技术创新、AI云原生、Agent开发、多模态模型、AIoT硬件及行业应用等前沿领域展开。字节豆包大模型1.6发布,会上介绍了豆包大模型1.6版本模型的能力。今天我们使用豆包最新发布的文生视频、文生图片等模型带大家搓一个文生图、文生视频、图生视频的MCP-server。

我们看一下这个MCP-server 实现的效果。

文生图片

我们下载打开生产的图片

文生视频

生成的视频效果

那么这样的文生图、文生视频、图生视频是MCP-Server是如何制作的呢?

话不多说下面带大家实现这个MCP-Server.

2.MCP-Server

火山引擎文生视频、文生图片模型API 解读

API 代码编写

首先我们需要登录火山引擎找最新的文生视频、文生图模型,我们在模型广场中找到下面的视频

接下来我们找到火山引擎的api 文档 www.volcengine.com/docs/82379/... 找到最新的模型使用文档

找到对应的API 文件。

我们这里参考了创建视频和查询视频列表API 编写文生视频的API 接口 代码,代码如下

testdoubao-seedance-1.0-pro.py

python 复制代码
import os
import time  
# 通过 pip install 'volcengine-python-sdk[ark]' 安装方舟SDK
from volcenginesdkarkruntime import Ark

# 请确保您已将 API Key 存储在环境变量 ARK_API_KEY 中
# 初始化Ark客户端,从环境变量中读取您的API Key
client = Ark(
    # 此为默认路径,您可根据业务所在地域进行配置
    base_url="https://ark.cn-beijing.volces.com/api/v3",
    # 从环境变量中获取您的 API Key。此为默认方式,您可根据需要进行修改
    api_key="xxxxxx",
)

if __name__ == "__main__":
    print("----- create request -----")
    create_result = client.content_generation.tasks.create(
        # 替换 <Model> 为模型的Model ID
        model="doubao-seedance-1-0-pro-250528",
        content=[
            {
                # 文本提示词
                "type": "text",
                "text": "戴着帽子的老爷爷面带微笑往前走"
            },
        ]
    )
    print(create_result)

    # 轮询查询部分
    print("----- polling task status -----")
    task_id = create_result.id
    while True:
        get_result = client.content_generation.tasks.get(task_id=task_id)
        status = get_result.status
        if status == "succeeded":
            print("----- task succeeded -----")
            print(get_result)
            break
        elif status == "failed":
            print("----- task failed -----")
            print(f"Error: {get_result.error}")
            break
        else:
            print(f"Current status: {status}, Retrying after 10 seconds...")
            time.sleep(10)

上面的代码就实现一个调用最新的doubao-seedance-1-0-pro-250528 模型实现一个文生视频功能。

这里需要注意的是我们是需要安装火山引擎的volcengine-python-sdk[ark] 包

shell 复制代码
pip install 'volcengine-python-sdk[ark]' -i https://pypi.tuna.tsinghua.edu.cn/simple/

代码编写完成后,我们需要使用 python testdoubao-seedance-1.0-pro.py 运行。

代码运行完成后,我们会看到返回的video-url 视频链接地址,点击视频链接下载。

这样我们就用最新的doubao-seedance-1-0-pro-250528 模型生成一个"戴着帽子的老爷爷面带微笑往前走"的视频了。

接下来我们同样的方法编写一个文生图的代码

testdoubao-seedream.py

python 复制代码
import os
# 通过 pip install 'volcengine-python-sdk[ark]' 安装方舟SDK
from volcenginesdkarkruntime import Ark

# 请确保您已将 API Key 存储在环境变量 ARK_API_KEY 中
# 初始化Ark客户端,从环境变量中读取您的API Key
client = Ark(
    # 此为默认路径,您可根据业务所在地域进行配置
    base_url="https://ark.cn-beijing.volces.com/api/v3",
    # 从环境变量中获取您的 API Key。此为默认方式,您可根据需要进行修改
    api_key="XXXX",
)

imagesResponse = client.images.generate(
    model="doubao-seedream-3-0-t2i-250415",
    prompt="鱼眼镜头,一只猫咪的头部,画面呈现出猫咪的五官因为拍摄方式扭曲的效果。"
)

print(imagesResponse.data[0].url)

同样的方式我对上面编写的代码完成测试和验证。

图片生视频和上面的类似(图生视频可以参考文生视频代码),这里就不做详细展开。

简单MCP_Server

我们需要实现一个文生图、图生视频、文生视频功能MCP_Server功能,所以我们需要对MCP_Server 要有一个简单的认识。基于上期文章最简单的MCP_Server 代码

server.py

python 复制代码
# server.py
from mcp.server.fastmcp import FastMCP

# Create an MCP server
mcp = FastMCP("Demo")


# Add an addition tool
@mcp.tool()
def add(a: int, b: int) -> int:
    """Add two numbers"""
    return a + b


# Add a dynamic greeting resource
@mcp.resource("greeting://{name}")
def get_greeting(name: str) -> str:
    """Get a personalized greeting"""
    return f"Hello, {name}!"

if __name__ == "__main__":
    mcp.run(transport="sse")

借助AI 实现MCP-Server

接下来我们需要正式编写基于上面文生图、文生视频、图生视频的MCP-Server。那么传统的方式我们是不是在上面server.py的代码框架基础上把文生图、文生视频、图生视频功能移植过来呢?那么这样写代码比较费劲。我们可不可以借用AI来帮我实现呢? 嘿嘿 这个方法不错,接下来我们就用这个偷懒的方法来实现这个MCP-Server

我们这里使用perplexity.ai来实现。

我们把之前的文生图、文生视频、图生视频的测试代码(上面的 )上传到perplexity.ai 平台

输入下面的提示词

arduino 复制代码
请参考上面的文档功能实现一个基于FastMCP 技术的文生图、图生视频、文生视频 功能的MCP-Server,请根据上面要求生成代码

AI 帮我生成代码

第一次 对话生成的代码不能满足我的要求,我忘记它不知道什么叫做FastMCP,接下来我又上传了上面的server.py 让它学习和参考

在输入提示词

shell 复制代码
上面生成的代码需要参考server.py ,这个才是真正的基于FastMCP MCP-Server 请重新修改

接下来AI 基于我上面的提示词重新生成代码

下面还很贴心告诉我这个代码如何启动

最后生成的代码

doubao_mcp_ai_server.py

python 复制代码
# mcp_ai_server.py
import time
import base64
import requests
import asyncio
from typing import Any, Dict, Optional, Union
from openai import OpenAI
from mcp.server.fastmcp import FastMCP

# 创建MCP服务器实例
mcp = FastMCP("AI Generation Server")

# 全局配置
API_KEY = None
BASE_URL = "https://ark.cn-beijing.volces.com/api/v3"

def initialize_client():
    """初始化OpenAI客户端"""
    if not API_KEY:
        raise ValueError("API key is required")
    return OpenAI(api_key=API_KEY, base_url=BASE_URL)

@mcp.tool()
def set_api_key(api_key: str) -> str:
    """设置豆包API密钥"""
    global API_KEY
    API_KEY = api_key
    return "API密钥设置成功"

@mcp.tool()
def text_to_image(
    prompt: str, 
    size: str = "1024x1024", 
    model: str = "doubao-seedream-3-0-t2i-250415"
) -> Dict[str, Any]:
    """
    文生图功能 - 根据文本描述生成图片
    
    Args:
        prompt: 图片描述提示词
        size: 图片尺寸,格式为"宽x高",如"1024x1024"
        model: 使用的模型名称
    
    Returns:
        包含图片URL或错误信息的字典
    """
    try:
        client = initialize_client()
        
        params = {
            "model": model,
            "prompt": prompt,
            "size": size,
            "response_format": "url",
            "n": 1,
        }
        
        response = client.images.generate(**params)
        
        if response.data and len(response.data) > 0:
            return {
                "success": True,
                "image_url": response.data[0].url,
                "message": "图片生成成功"
            }
        else:
            return {
                "success": False,
                "error": "未返回图片数据"
            }
            
    except Exception as e:
        return {
            "success": False,
            "error": f"生成图片时出错: {str(e)}"
        }

@mcp.tool()
def image_to_video(
    prompt: str,
    image_base64: str,
    duration: str = "5",
    ratio: str = "16:9",
    model: str = "doubao-seedance-1-0-pro-250528"
) -> Dict[str, Any]:
    """
    图生视频功能 - 根据图片和文本描述生成视频
    
    Args:
        prompt: 视频描述提示词
        image_base64: 图片的base64编码字符串
        duration: 视频时长(秒)
        ratio: 视频比例,如"16:9"
        model: 使用的模型名称
    
    Returns:
        包含视频URL或错误信息的字典
    """
    try:
        # 构造图片数据URL
        image_data_url = f"data:image/jpeg;base64,{image_base64}"
        
        # 自动添加参数到提示词
        if ratio and "--ratio" not in prompt:
            prompt += f" --ratio adaptive"
        if duration and "--duration" not in prompt and "--dur" not in prompt:
            prompt += f" --duration {duration}"
        
        headers = {
            "Content-Type": "application/json",
            "Authorization": f"Bearer {API_KEY}"
        }
        
        # 构造请求内容
        content = [
            {"type": "text", "text": prompt},
            {"type": "image_url", "image_url": {"url": image_data_url}}
        ]
        
        request_data = {
            "model": model,
            "content": content
        }
        
        # 创建视频生成任务
        response = requests.post(
            f"{BASE_URL}/contents/generations/tasks",
            headers=headers,
            json=request_data
        )
        
        if response.status_code != 200:
            return {
                "success": False,
                "error": f"创建视频生成任务失败,状态码: {response.status_code}, 信息: {response.text}"
            }
        
        task_id = response.json().get("id")
        if not task_id:
            return {
                "success": False,
                "error": "未获取到任务ID"
            }
        
        # 轮询等待任务完成
        max_retries = 60
        for retry in range(max_retries):
            time.sleep(5)
            
            task_resp = requests.get(
                f"{BASE_URL}/contents/generations/tasks/{task_id}",
                headers=headers
            )
            
            if task_resp.status_code != 200:
                return {
                    "success": False,
                    "error": f"查询任务失败,状态码: {task_resp.status_code}"
                }
            
            task_data = task_resp.json()
            status = task_data.get("status")
            
            if status == "succeeded":
                video_url = task_data.get("content", {}).get("video_url")
                return {
                    "success": True,
                    "video_url": video_url,
                    "message": "视频生成成功",
                    "task_id": task_id
                }
            elif status in ("failed", "canceled"):
                return {
                    "success": False,
                    "error": f"任务{status}"
                }
        
        return {
            "success": False,
            "error": "视频生成超时"
        }
        
    except Exception as e:
        return {
            "success": False,
            "error": f"生成视频时出错: {str(e)}"
        }

@mcp.tool()
def text_to_video(
    prompt: str,
    duration: str = "5",
    ratio: str = "16:9",
    model: str = "doubao-seedance-1-0-pro-250528"
) -> Dict[str, Any]:
    """
    文生视频功能 - 根据文本描述生成视频
    
    Args:
        prompt: 视频描述提示词
        duration: 视频时长(秒)
        ratio: 视频比例,如"16:9"
        model: 使用的模型名称
    
    Returns:
        包含视频URL或错误信息的字典
    """
    try:
        # 自动添加参数到提示词
        if ratio and "--ratio" not in prompt:
            prompt += f" --ratio {ratio}"
        if duration and "--duration" not in prompt and "--dur" not in prompt:
            prompt += f" --duration {duration}"
        
        headers = {
            "Content-Type": "application/json",
            "Authorization": f"Bearer {API_KEY}"
        }
        
        request_data = {
            "model": model,
            "content": [{"type": "text", "text": prompt}]
        }
        
        # 创建视频生成任务
        response = requests.post(
            f"{BASE_URL}/contents/generations/tasks",
            headers=headers,
            json=request_data
        )
        
        if response.status_code != 200:
            return {
                "success": False,
                "error": f"创建视频生成任务失败,状态码: {response.status_code}, 信息: {response.text}"
            }
        
        task_id = response.json().get("id")
        if not task_id:
            return {
                "success": False,
                "error": "未获取到任务ID"
            }
        
        # 轮询等待任务完成
        max_retries = 60
        for retry in range(max_retries):
            time.sleep(5)
            
            task_resp = requests.get(
                f"{BASE_URL}/contents/generations/tasks/{task_id}",
                headers=headers
            )
            
            if task_resp.status_code != 200:
                return {
                    "success": False,
                    "error": f"查询任务失败,状态码: {task_resp.status_code}"
                }
            
            task_data = task_resp.json()
            status = task_data.get("status")
            
            if status == "succeeded":
                video_url = task_data.get("content", {}).get("video_url")
                return {
                    "success": True,
                    "video_url": video_url,
                    "message": "视频生成成功",
                    "task_id": task_id
                }
            elif status in ("failed", "canceled"):
                return {
                    "success": False,
                    "error": f"任务{status}"
                }
        
        return {
            "success": False,
            "error": "视频生成超时"
        }
        
    except Exception as e:
        return {
            "success": False,
            "error": f"生成视频时出错: {str(e)}"
        }

@mcp.tool()
def encode_image_to_base64(image_path: str) -> Dict[str, Any]:
    """
    将本地图片文件编码为base64字符串
    
    Args:
        image_path: 图片文件路径
    
    Returns:
        包含base64编码字符串或错误信息的字典
    """
    try:
        with open(image_path, 'rb') as image_file:
            encoded_string = base64.b64encode(image_file.read()).decode('utf-8')
            return {
                "success": True,
                "base64_string": encoded_string,
                "message": "图片编码成功"
            }
    except Exception as e:
        return {
            "success": False,
            "error": f"编码图片失败: {str(e)}"
        }

@mcp.resource("config://models")
def get_available_models() -> str:
    """获取可用的AI模型列表"""
    models = {
        "text_to_image": [
            "doubao-seedream-3-0-t2i-250415"
        ],
        "image_to_video": [
            "doubao-seedance-1-0-pro-250528"
        ],
        "text_to_video": [
            "doubao-seedance-1-0-pro-250528"
        ]
    }
    return f"可用模型列表: {models}"

@mcp.resource("config://settings")
def get_server_settings() -> str:
    """获取服务器配置信息"""
    settings = {
        "base_url": BASE_URL,
        "api_key_set": bool(API_KEY),
        "supported_image_sizes": ["512x512", "768x768", "1024x1024", "1024x1792", "1792x1024"],
        "supported_video_ratios": ["16:9", "9:16", "1:1"],
        "max_video_duration": "10s"
    }
    return f"服务器配置: {settings}"

if __name__ == "__main__":
    mcp.run(transport="stdio")

上面的代码默认生成的MCP 使用的是stdio, 我们把它改成sse方式,代码复制到trae开发工具中,启动服务运行

这样我们基于SSE 发布了一个MCP-server了

客户端(Cherry Studio)配置

这里我们使用Cherry Studio来做测试

点开这里我们添加一个服务器,我们选择sse,添加URL

设置完成后,点击保存按钮。

接下来我点击工具按钮查看MCP 有哪些方法

这样我们就完成MCP-Server客户端的配置。

我们打开服务端代码 也能看到服务端收到的请求信息

3.MCP-Server 服务器发布

我们接下来可以参考我之前上期文档内容把这个代码发布到服务器中。详细步骤可以看我之前的文章

mcp-server案例分享-手搓一个MCP-server,手把手教你从本地开发到云部署全流程实战

启动

shell 复制代码
python3 doubao_mcp_ai_server.py 

4.验证云服务SSE

我们这里使用dify来实现SSE方式验证测试一下。

dify

​ 我们使用dify平台配置一个AI Agent,模型这里我们选择火山引擎的deepseek-v3 模型(其他模型效果不行)

我们需要其他配置好mcp-see 地址

shell 复制代码
{ "doubao_mcp_ai_server": { "url": "http://14.103.204.132:8002/sse", "headers": {}, "timeout": 60, "sse_read_timeout": 300 } }

把上面的sse配置填写到MCP-see配置中完成授权

​ 回到ai Agent中设置好MCP-SSE

接下来我们进入聊天对话窗口中

第一次对话模型调用工具发现没有授权,提示我们先填写APIkey授权。 我们填写授权后开启ai 绘画

这样我使用difyai agent实现了文生图片功能测试了,(文生视频类似,这里就不做详细展开了。)

trae

接下来我们把云端部署的SSE 部署在trae 开发工具中使用

json 复制代码
{
  "mcpServers": {
    "doubao_mcp_ai_server": {
      "url": "http://14.103.204.132:8002/sse",
      "type": "sse"  // 明确指定传输类型
    }
  }
}

把上面的mcpServers 配置添加到trae 的MCP配置中

接下我们使用文生视频提示词测试一下

shell 复制代码
请使用doubao_mcp_ai_server 服务生成一个非常卡通可爱的小猫钓鱼视频

我们点击视频下载下载本地电脑

这个视频效果非常棒。

好了以上我们就基于字节豆包大模型1.6发布 的文生视频模型doubao-seedance-1-0-pro-250528 模型生成的视频。

5.总结

今天主要带大家了解并实现了基于字节豆包大模型 1.6 发布的文生图、文生视频、图生视频功能的 MCP - Server 搭建方案。通过使用火山引擎的文生视频、文生图片模型 API,借助 AI 工具生成代码,我们成功构建了一个具备文生图、图生视频、文生视频功能的 MCP - Server,并完成了客户端配置、服务器发布以及云服务 SSE 验证。感兴趣的小伙伴可以按照本文步骤去尝试搭建自己的文生图、文生视频、图生视频 MCP - Server。今天的分享就到这里结束了,我们下一篇文章见。

相关推荐
kaizq9 小时前
AI-MCP-SQLite-SSE本地服务及CherryStudio便捷应用
python·sqlite·llm·sse·mcp·cherry studio·fastmcp
太空眼睛12 小时前
【MCP】使用SpringBoot基于Streamable-HTTP构建MCP-Server
spring boot·sse·curl·mcp·mcp-server·spring-ai·streamable
康de哥19 小时前
MCP Unity + Claude Code 配置关键步骤
unity·mcp·claude code
田井中律.1 天前
MCP协议
mcp
通义灵码1 天前
Qoder 支持通过 DeepLink 添加 MCP Server
人工智能·github·mcp
酩酊仙人2 天前
fastmcp构建mcp server和client
python·ai·mcp
kwg1263 天前
本地搭建 OPC UA MCP 服务
python·agent·mcp
小小工匠3 天前
LLM - 从通用对话到自治智能体:Agent / Skills / MCP / RAG 三层架构实战
agent·rag·skill·mcp
小小工匠3 天前
LLM - 将业务 SOP 变成 AI 能力:用 Skill + MCP 驱动 Spring AI 应用落地不完全指南
人工智能·skill·spring ai·mcp
Esun_R4 天前
当 LLM 开始连接真实世界:MCP 的原理、通信与工程落地
node.js·openai·mcp