1前言
上期給大家介紹過mcp-server案例分享-用豆包大模型 1.6 手搓文生圖視頻 MCP-server。當時部署的方式使用了一個私有云SSE的部署。當時缺少一個本地部署的方式,有的小伙伴給我留言能不能有一個本地話部署方式了。今天就給大家帶來一個本地化部署的方案。
話不多說下面介紹一下具體如何打包和操作的。
2.打包發布Python庫到PyPI
基于上期文章我們已經有了代碼mcp_ai_server.py
# doubao_mcp_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_KEYAPI_KEY = api_keyreturn "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-lite-i2v-250428"
) -> Dict[str, Any]:"""圖生視頻功能 - 根據圖片和文本描述生成視頻Args:prompt: 視頻描述提示詞image_base64: 圖片的base64編碼字符串duration: 視頻時長(秒)ratio: 視頻比例,如"16:9"model: 使用的模型名稱Returns:包含視頻URL或錯誤信息的字典"""try:# 構造圖片數據URLimage_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 = 60for 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-lite-t2v-250428"
) -> 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 = 60for 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-lite-i2v-250428"],"text_to_video": ["doubao-seedance-1-0-lite-t2v-250428"]}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}"def main():"""主函數入口點"""mcp.run(transport="stdio")if __name__ == "__main__":main()
包代碼開發
將您MCP server本地腳本打包,需要在doubao_mcp_server目錄新建一個文件__init__.py
init.py
from .doubao_mcp_server import main__all__ = ["main"]
本地測試
打包后測試可以將這個mcp server作為模塊來運行,而不是直接通過腳本運行。
# 以模塊運行
uv run -m mcp_ai_server
或者也可以在MCP 客戶端比如Cherry Studio上配置config測試
{"mcpServers": {"r-FY6A48OrPGz5fknShHt": {"name": "doubao-mcp-server","type": "stdio","description": "","isActive": true,"registryUrl": "https://pypi.tuna.tsinghua.edu.cn/simple","command": "uv","args": ["--directory","F:\\work\\code\\AIcode\\doubao_mcp_server","run","doubao-mcp-server.py"]}}
Cherry Studio上 界面配置
點擊保存驗證一下,查看下工具列表
看到這個說明可以在客戶端使用這個MCP-Server了。
作為一個包發布到PyPI
編寫pyproject.toml
您需要確保在您的項目根目錄,存在一個完整的pyproject.toml文件(在前面的步驟中應該已經自動生成)。這個文件的內容包括:
- 包的元信息:名字、版本、描述、作者
- 依賴項
- 構建系統配置
- MCP入口
pyproject.toml文件:
[project]
name = “doubao-mcp-server”
version = “0.1.0”
description = “主要實現的是火山引擎的提供的豆包文生圖、文生視頻、圖生視頻MCP-Server”
authors = [
{name = “wwzhouhui”,email = “75271002@qq.com”}
]
readme = “README.md”
requires-python = “>=3.13”
dependencies = [
“mcp[cli]>=1.9.4”, # 添加requests依賴
“requests>=2.31.0”,
“openai>=1.86.0”,
]
[project.scripts]
doubao-mcp-server = “doubao_mcp_server:main”
[build-system]
requires = [“hatchling”]
build-backend = “hatchling.build”
Python包創建一個README.md
這個地方我們省略
編譯打包
構建你Python包,這個地方我稍微講一下
cd F:\work\code\AIcode\doubao_mcp_server
uv build
檢查打包文件
在dist/目錄下看見.whl和.tar.gz的兩個文件
準備PyPI賬戶
我需要登錄PyPI官網:https://pypi.org/account/login/ 注冊一個賬號(如果之前沒有的話)
關于PyPI注冊比較麻煩,這里不做詳細展開。主要是注冊之后還需要微軟的Authenticator 手機上安裝,然后通過雙重身份驗證完成登錄
完整雙重身份驗證后,我們就可以實現打包文件上傳了。
pypi api token創建
雙重身份驗證通過后,我們點擊“add api token” 創建一個api
復制上面的token用記事本保存好。
上傳您的Python包
我們在命令行窗口輸入如下命令
uv publish --token pypi-xxxxxx
我們去pypi 查看我們上傳的包
打開view 我們就查看剛剛上傳的詳細的依賴包
MCP客戶端測試
一旦發布完成, 用戶就可以通過uvx安裝和使用您的 MCP server。uvx會創建一個臨時環境,安裝依賴并執行這個包,非常的簡潔優雅。
接下來我們使用trae 來下載安裝我們剛才上傳的pypi依賴包
我們在trae 添加如下mcp-server配置
{"mcpServers": {"doubao-mcp-server": {"command": "uvx","args": ["doubao-mcp-server"],"env": {"DOUBAO_API_KEY": "your-api-key-here"}}}
}
配置完成后
我們測試一下
有點丑,不過確實已經弄個調用生產圖片了。
3.部署到魔搭MCP廣場
我們也可以把這個MCP部署到魔搭社區的MCP廣場上給大家使用。
-
進入魔搭MCP廣場
MCP廣場地址:modelscope.cn/mcp
-
基礎信息填寫
創建類型:選擇“GitHub快速創建”
英文名稱:英文MCP Server名字,
中文名稱:中文MCP Server名字,
來源地址:代碼我們已經上傳github地址:https://github.com/wwwzhouhui/doubao_mcp_server
所有者:默認已填好
托管類型:選擇“可托管部署”
完成部署
上面填寫APIkey 就可以體驗了。按照下面填寫APIkey
生成SSE URL 地址(上面地址有效期時間24個小時,也可以設置長期有效)
{"mcpServers": {"DoubaoMCPServer-MCP_Agent_Challenge": {"type": "sse","url": "https://mcp.api-inference.modelscope.net/aee3086059a34e/sse"}}
}
接下來我們也可以在魔搭的應用廣場上體驗了。我們點擊“試用” 就可以在魔搭社區免費體驗了。
摩搭社區MCP應用廣場測試
進入應用廣場 輸入下面的提示詞
文生圖
給我畫一個 小白兔吃蘿卜
這樣我們在魔搭社區里面也可以使用我我們剛才部署打包的MCP-server了。
文生視頻
提示詞:給我生成一個小白兔吃蘿卜的視頻
4.總結
今天主要帶大家了解并實現了基于豆包大模型 1.6 發布的文生圖、文生視頻、圖生視頻功能的 MCP-Server 本地化部署與發布方案。通過將 MCP Server 腳本打包為 Python 庫并發布至 PyPI,我們成功實現了可跨平臺調用的 AI 生成服務。借助火山引擎提供的文生圖、文生視頻、圖生視頻模型 API,我們構建了一個功能完整的 MCP-Server,支持通過文本描述生成高質量圖片和視頻內容。
通過本文的方案,開發者可以輕松搭建自己的文生圖、文生視頻、圖生視頻服務,為應用程序添加強大的 AI 生成能力。感興趣的小伙伴可以按照本文步驟去嘗試搭建自己的 MCP-Server。今天的分享就到這里結束了,我們下一篇文章見。