1. 即梦AI文生视频接入MCP Server的真实痛点
即梦AI文生视频是字节跳动剪映团队推出的AI视频生成能力,输入一段文本提示词,就能产出带运镜、带转场的短视频片段。对做内容批量生产、电商素材、短剧预演的开发者来说,它比传统剪辑快得多。但真正把它接进自己的 Agent 工作流时,问题就来了:即梦的接口鉴权走的是 Cookie + sign 这套网页端签名机制,跟 OpenAI 那套 Bearer Token 完全不是一回事;同时你手里可能还攥着 DeepSeek、通义、Claude 好几个模型的 Key,每个都要单独配环境变量、单独写请求封装,项目一多就乱成一锅粥。
MCP Server(Model Context Protocol Server)正好是解决这类问题的抓手。它把「调用即梦生成视频」这件事封装成一个标准工具,任何支持 MCP 协议的客户端(Cherry Studio、Cline、Claude Code 等)都能通过统一的 SSE 或 STDIO 通道调用它,不用再关心底层是 Cookie 还是 sign。而 TaoToken 在这里扮演的是「统一 Key 与 API 通道」的角色——你不需要在每台机器、每个项目里散落一堆厂商 Key,而是通过一个统一的 API 入口来管理模型调用凭证,MCP Server 侧只认这一套配置。
这篇文章面向的是需要统一管理多模型 Key 的开发者。我会给出可复制的 mcp-server 配置片段、TaoToken 统一 Key 通道的对接步骤,以及调用即梦AI文生视频接口的验证动作和预期返回结果。整条链路从配置到出片,你跟着做就能跑通。适合谁:已经会用 FastAPI 写接口、想在 Agent 里加视频生成能力的后端或全栈开发者;也适合正在用 Cherry Studio 这类客户端、想扩展自定义工具的 AI 应用玩家。
先说清楚一个边界:即梦AI文生视频的底层调用依赖其网页端接口的 Cookie 和 sign 参数,这部分需要你自己从已登录的即梦账号里获取,本文不涉及任何绕过鉴权的操作,只讲怎么把它规范地封装成 MCP 工具并接入统一通道。TaoToken 负责的是模型调用凭证的统一管理,不是替代即梦的鉴权。
2. TaoToken 统一 Key 与 mcp-server 前置准备
在动手写代码之前,先把「统一 Key 通道」这件事理清楚。很多开发者的习惯是每个项目建一个.env,里面塞满JIMENG_COOKIE、DEEPSEEK_KEY、QWEN_KEY……项目一多,改一个 Key 要翻五个仓库。TaoToken 的思路是提供一个统一的 API 入口,你在这里管理调用凭证,业务侧只对接一个 Base URL 和一套 Key。
TaoToken 的 API 入口是https://taotoken.net/api,官网是https://taotoken.net/。你需要先在控制台创建一个 API Key,路径是https://taotoken.net/console,然后在 API Keys 页面生成。这个 Key 就是你后续在 MCP Server 配置里填的凭证。如果你还没建过,直接去https://taotoken.net/api-keys也能到对应页面。
这里要强调一个概念:TaoToken 的统一 Key 解决的是「模型调用凭证集中管理」,而即梦AI文生视频的 Cookie/sign 是即梦平台自己的鉴权,两者是不同层的东西。MCP Server 里我们会把这两类凭证分开配置——TaoToken 的 Key 用于模型侧调用,即梦的 Cookie/sign 用于视频生成接口。这样设计的好处是,当你要换模型供应商时,只改 TaoToken 侧的配置,视频生成逻辑完全不用动。
前置准备清单:
第一,Python 3.10 以上环境,FastAPI、uvicorn、requests、fastapi_mcp、腾讯云 COS SDK(cos-python-sdk-v5)都要装。fastapi_mcp 是把 FastAPI 接口转成 MCP 工具的核心库,源码在https://github.com/tadata-org/fastapi_mcp,它的用法很直接:add_mcp_server(app, mount_path="/mcp", ...)就能把现有 FastAPI 应用挂载成 MCP 服务。
第二,一个即梦账号,登录后从浏览器开发者工具里拿到cookie和sign两个值。cookie 是一长串,sign 是每次请求动态生成的签名,实际使用中你需要根据即梦的签名规则生成,或者从抓包结果里取。本文的示例代码里用配置文件读取,你替换成自己的值即可。
第三,腾讯云 COS 对象存储(可选但推荐)。即梦返回的视频 URL 有时效性,直接给客户端用容易过期,所以示例里会把视频下载后上传到 COS,返回一个稳定的公网 URL。如果你不想用 COS,可以跳过上传步骤,直接返回即梦的原始 URL,但要注意时效。
第四,一个支持 MCP 的客户端。我用 Cherry Studio 演示,版本要 1.0 以上才支持 MCP Server。其他如 Cline、Claude Code 也都可以,配置方式类似,都是填 SSE 地址。
配置文件config.ini的结构大概是这样,放在项目根目录:
[common] region = ap-guangzhou secret_id = 你的腾讯云SecretId secret_key = 你的腾讯云SecretKey bucket = 你的COS桶名 video_output_path = ./output [auth] valid_tokens = ["bearer sk-你的MCP访问令牌"] [video_api] cookie = 你的即梦cookie sign = 你的即梦sign注意valid_tokens这里配的是 MCP Server 自己的访问令牌,跟 TaoToken 的 Key 是两回事。MCP Server 用它来校验调用方身份,防止别人随便调你的视频生成接口。TaoToken 的 Key 则是在你通过 MCP 客户端调用模型时使用,两者各司其职。
3. 可复制的 mcp-server 配置与即梦接入代码
这一节是核心,直接给可复制的代码。整个服务基于 FastAPI 构建,用 fastapi_mcp 挂载 MCP 端点,对外暴露一个 SSE 服务。先看主服务文件jimeng_video_service.py的关键部分。
依赖安装:
pip install fastapi uvicorn requests fastapi_mcp cos-python-sdk-v5服务初始化与 MCP 挂载:
from fastapi import FastAPI, HTTPException, Depends, Header from pydantic import BaseModel from fastapi_mcp import add_mcp_server import configparser, logging, time, requests, uuid, json, os, datetime, random from qcloud_cos import CosConfig, CosS3Client logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) app = FastAPI( title="Jimeng Video Service API", description="用于生成AI视频的服务 API", version="1.0.0", ) config = configparser.ConfigParser() config.read('./config.ini', encoding='utf-8') region = config.get('common', 'region') secret_id = config.get('common', 'secret_id') secret_key = config.get('common', 'secret_key') bucket = config.get('common', 'bucket') video_output_path = config.get('common', 'video_output_path') if not os.path.exists(video_output_path): os.makedirs(video_output_path)请求模型与鉴权函数:
class VideoRequest(BaseModel): prompt: str aspect_ratio: str = "16:9" duration_ms: int = 5000 fps: int = 24 def verify_auth_token(authorization: str = Header(None)): if not authorization: raise HTTPException(status_code=401, detail="Missing Authorization Header") scheme, _, token = authorization.partition(" ") if scheme.lower() != "bearer": raise HTTPException(status_code=401, detail="Invalid Authorization Scheme") valid_tokens = json.loads(config.get('auth', 'valid_tokens')) if token not in valid_tokens: raise HTTPException(status_code=403, detail="Invalid or Expired Token") return token视频生成核心逻辑,包含提交任务、轮询状态、下载、上传 COS:
@app.post("/jimeng/generate_video/") async def generate_video(request: VideoRequest, auth_token: str = Depends(verify_auth_token)): try: start_time = time.time() video_api_cookie = config.get('video_api', 'cookie') video_api_sign = config.get('video_api', 'sign') video_api_headers = { 'accept': 'application/json, text/plain, */*', 'content-type': 'application/json', 'cookie': video_api_cookie, 'sign': video_api_sign, 'sign-ver': '1', 'origin': 'https://jimeng.jianying.com', 'referer': 'https://jimeng.jianying.com/ai-tool/video/generate', } video_api_base = "https://jimeng.jianying.com/mweb/v1" submit_id = str(uuid.uuid4()) payload = { "submit_id": submit_id, "http_common_info": {"aid": 513695}, "input": { "video_aspect_ratio": request.aspect_ratio, "seed": 2934141961, "video_gen_inputs": [{ "prompt": request.prompt, "fps": request.fps, "duration_ms": request.duration_ms, "video_mode": 2, "template_id": "" }], "priority": 0, "model_req_key": "dreamina_ic_generate_video_model_vgfm_lite" }, "mode": "workbench", "commerce_info": { "resource_id": "generate_video", "resource_id_type": "str", "resource_sub_type": "aigc", "benefit_type": "basic_video_operation_vgfm_lite" } } resp = requests.post(f"{video_api_base}/generate_video?aid=513695", headers=video_api_headers, json=payload) if resp.status_code != 200: raise HTTPException(status_code=500, detail=f"生成请求失败: {resp.status_code}") data = resp.json() task_id = data["data"]["aigc_data"]["task"]["task_id"] for attempt in range(30): time.sleep(2) r = requests.post(f"{video_api_base}/mget_generate_task?aid=513695", headers=video_api_headers, json={"task_id_list": [task_id]}) task_data = r.json()["data"]["task_map"].get(task_id) if task_data and task_data.get("status") == 50: video_url = task_data["item_list"][0]["video"]["transcoded_video"]["origin"]["video_url"] filename, file_path = download_video(video_url, video_output_path) cos_url = upload_to_cos(region, secret_id, secret_key, bucket, filename, video_output_path) os.remove(file_path) return { "video_url": cos_url, "task_id": task_id, "markdown": f"<video controls><source src='{cos_url}' type='video/mp4'></video>" } raise HTTPException(status_code=500, detail="视频生成超时") except Exception as e: logger.error(f"视频生成失败: {str(e)}") raise HTTPException(status_code=500, detail=str(e))MCP 工具注册,这是让客户端能发现并调用它的关键:
mcp_server = add_mcp_server( app, mount_path="/mcp", name="Jimeng Video MCP", description="集成了智能视频生成功能的 MCP 服务", base_url="http://localhost:8088" ) @mcp_server.tool() async def generate_video_mcp( prompt: str, aspect_ratio: str = "16:9", duration_ms: int = 5000, fps: int = 24, authorization: str = Header(...) ) -> dict: """生成一个基于文本提示的 AI 视频。 Args: prompt: 用于生成视频的文本提示词 aspect_ratio: 视频宽高比,默认 16:9 duration_ms: 视频时长(毫秒),默认 5000 fps: 视频帧率,默认 24 authorization: Bearer token 用于认证(必填) """ request = VideoRequest(prompt=prompt, aspect_ratio=aspect_ratio, duration_ms=duration_ms, fps=fps) return await generate_video(request, auth_token=verify_auth_token(authorization))启动入口:
if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8088, log_level="info", reload=False)这里有个细节要注意:add_mcp_server的base_url要跟你实际启动的地址一致,否则 MCP 客户端拿到的工具描述里 URL 会不对。另外reload=False是故意的,热重载会导致 MCP 初始化重复执行,出现工具重复注册的问题。
关于 TaoToken 的接入,如果你希望 MCP 工具内部调用模型(比如让模型先润色提示词再生成视频),可以在服务里加一个模型调用函数,Base URL 填https://taotoken.net/api,Key 用你在控制台生成的。这样整个链路就是:客户端 → MCP Server → TaoToken 统一通道 → 模型 → 即梦视频生成。凭证集中在一处,换模型不用改业务代码。
4. 启动服务与验证请求的完整动作
代码写完后,启动服务:
python jimeng_video_service.py看到 uvicorn 输出Uvicorn running on http://0.0.0.0:8088就说明起来了。此时 MCP 的 SSE 端点在http://localhost:8088/mcp。
先用 curl 验证 HTTP 接口本身是否正常,这一步能排除掉 MCP 客户端配置的干扰:
curl -X POST http://localhost:8088/jimeng/generate_video/ \ -H "Authorization: Bearer sk-你的MCP访问令牌" \ -H "Content-Type: application/json" \ -d '{"prompt":"小马过河","aspect_ratio":"16:9","duration_ms":5000,"fps":24}'预期返回是一个 JSON,包含video_url、task_id和markdown三个字段。video_url是上传到 COS 后的稳定地址,markdown里是一段<video>标签,方便客户端直接渲染预览。如果返回 401,说明 Authorization 头没带或格式不对;返回 403,说明令牌不在valid_tokens列表里。
接下来在 Cherry Studio 里配置 MCP Server。打开设置,找到 MCP 服务器选项,添加一个新服务器,类型选 SSE,URL 填http://localhost:8088/mcp,保存。保存后客户端会向服务端发起连接,服务端日志里能看到 SSE 连接建立的记录。如果客户端界面显示已连接、并且列出了generate_video_mcp这个工具,说明 MCP 通道打通了。
然后选一个支持 function call 的模型。在 Cherry Studio 的模型设置里,带小工具图标的模型才支持工具调用。我实测用 DeepSeek-V3 可以正常触发。新建一个对话,选中该模型,聊天窗口下方会出现 MCP Server 的小面板,勾选你刚配置的即梦视频服务。
在对话框里输入这样的提示词:
请帮我调用即梦AI文生视频 mcp server 工具,提示词为"小马过河",authorization 为 "bearer sk-你的MCP访问令牌"因为generate_video_mcp有两个必填参数(prompt 和 authorization),一次性把两个值都给模型,它就能直接执行函数调用,不需要多轮交互。发送后,模型会识别意图、触发工具调用,你可以在服务端日志里看到完整的请求过程:提交任务、轮询状态、下载视频、上传 COS,直到返回结果。
预期结果是模型回复里带出视频链接。Cherry Studio 目前对视频预览的支持不太完善,你可能需要把返回的video_url复制到浏览器里打开才能看到效果。这是客户端渲染的限制,不是服务端的问题。视频本身在即梦平台也能看到预览,因为任务是在你的即梦账号下创建的。
整个验证链路的关键节点有三个:HTTP 接口返回 200 且带 video_url、MCP 客户端显示已连接并列出工具、模型对话触发工具调用并返回视频链接。三个都过了,说明从配置到出片的链路完全跑通。
5. 本篇常见错误排查:401、local proxy failed 与 reading choices
实际跑的时候,报错基本集中在几个地方。我按出现频率排一下,对照着查。
401 Missing Authorization Header:这个最常见。MCP 工具定义里authorization: str = Header(...)表示它是必填的 HTTP 头,但通过 MCP 客户端调用时,这个值需要作为工具参数传进去,而不是 HTTP 头。如果你在客户端只填了 prompt 没填 authorization,模型可能不会自动补,导致服务端收到空头。解决办法是在提示词里明确给出 authorization 的值,或者在工具定义里给它一个默认值。另外检查valid_tokens里的格式,必须是"bearer sk-xxx"这种带前缀的完整字符串,跟请求头里的值完全一致。
local proxy failed / connection refused:MCP 客户端连不上http://localhost:8088/mcp。先确认服务真的在跑,curl http://localhost:8088/mcp看有没有响应。如果服务在 Docker 里跑,localhost 在容器内指向容器自己,客户端在宿主机就连不上,要把地址换成宿主机的局域网 IP。还有一种情况是端口被占用,uvicorn 启动时会报Address already in use,换个端口或者杀掉占用进程。
Error reading choices / 返回格式错误:这个通常出现在模型侧,不是 MCP 服务的问题。当模型返回的内容不符合预期结构时,客户端解析会报这个错。原因可能是模型不支持 function call,或者提示词太模糊导致模型没触发工具调用而是直接编了一段文字。换一个明确支持工具调用的模型,提示词里把工具名和参数写清楚。如果服务端日志显示工具被调用了但客户端还是报这个错,检查返回的 JSON 结构是否跟工具定义的返回类型一致。
OAuth 相关报错:有些 MCP 客户端在连接时会尝试 OAuth 流程,如果你的服务没配 OAuth,会卡在这一步。SSE 类型的 MCP Server 一般不需要 OAuth,在客户端配置里确认没有勾选需要 OAuth 的选项。如果客户端强制要求,换用支持无认证 SSE 的客户端版本。
视频生成超时:即梦的任务轮询最多 30 次、每次间隔 2 秒,总共 60 秒。如果 60 秒内没出结果,会抛超时。这通常是即梦侧排队导致的,可以适当加大轮询次数和间隔。另外检查 cookie 和 sign 是否过期,即梦的 cookie 有效期不长,过期后会一直返回任务创建失败。
COS 上传失败:检查config.ini里的 region、secret_id、secret_key、bucket 四个值是否匹配。region 要填ap-guangzhou这种格式,不是gz。bucket 名要带 appid 后缀。如果报权限错误,去腾讯云控制台确认这个 SecretId 有 COS 的写权限。
排查的时候有个通用技巧:先绕过 MCP 客户端,直接用 curl 打 HTTP 接口。curl 通了再查 MCP 客户端配置,这样能把问题范围缩小到一半。服务端日志一定要开着log_level="info",每个关键步骤都有日志,对着日志看卡在哪一步最直接。
6. 统一 Key 通道下的持续使用建议
跑通之后,日常使用还有几个点值得注意。即梦的 cookie 和 sign 会过期,建议把这两个值做成可热更新的配置,而不是硬编码在代码里。可以在服务里加一个重新读取配置的接口,cookie 失效时不用重启服务。TaoToken 侧的 Key 管理也是同理,控制台里可以随时轮换,业务侧只要 Base URL 不变就不用改代码。
如果你要把这个 MCP Server 部署到服务器上给团队用,记得把valid_tokens换成强随机令牌,别用示例里的简单字符串。SSE 端点暴露在公网时,最好加一层反向代理和访问控制。视频输出目录要定期清理,虽然上传 COS 后会删本地文件,但异常情况下可能残留。
想进一步扩展的话,可以在同一个 FastAPI 应用里挂载多个 MCP 工具,比如加一个「查询任务状态」的工具、一个「批量生成」的工具,fastapi_mcp 支持在一个 app 上注册多个工具。模型侧通过 TaoToken 统一通道调用,换模型、加模型都只改一处配置。这样一套下来,你的 Agent 工作流里既有统一的模型调用入口,又有标准化的视频生成工具,扩展起来会顺很多。
需要看更多接入示例和文档的话,可以到https://taotoken.net/doc查;模型对话调试在https://taotoken.net/models;长期跑编码和 Agent 任务的话,https://taotoken.net/coding-plan有对应的方案。API Key 在https://taotoken.net/api-keys管理。把这些地址存下来,下次配新项目直接照着填就行。