Douyin Publish MCP
This MCP server provides Douyin (TikTok China) publishing and reading capabilities through 10 tools, with two-step publish confirmation and account login management.
Account: check login status (
douyin_account_status), scan-QR login in a real browser window (douyin_account_login), and reset login state by deleting the stored cookie file (douyin_account_logout).Publish: create video posts (
douyin_publish_video) and image/text posts (douyin_publish_note), with optional tags, schedules, covers, product links, declarations, collections, BGM, and long text from file; publishing requires a preflight plan plusconfirm=true.Read/search: search videos by keyword (
douyin_search_videos), get a video’s details and no-watermark link (douyin_video_detail), view a user profile and recent works (douyin_user_profile), view your own profile (douyin_my_profile), and parse share links into video details (douyin_parse_share_link).Read tools require login, return temporary no-watermark links (hours), and can fall back between direct HTTP and browser channels.
Run modes: stdio (default) or streamable HTTP; HTTP mode adds a local status page, login/logout endpoints, health check, and optional bearer-token auth.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Douyin Publish MCPpublish media/sunset.mp4 with the title "Sunset timelapse""
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
douyin-publish-mcp
把抖音的发布 + 读取能力包成薄 MCP 服务,供本平台的「MCP 商店」安装、启停用。 发布/登录/账号检查是本服务自带的创作者中心自动化(选择器与流程知识参考了 social-auto-upload(MIT,见 NOTICE 署名)), 运行时不再调用外部 CLI;读取则直连抖音 web 接口,见 「读取能力怎么来」。
10 个工具:账号状态、扫码登录(会话式)、重置登录态、发布视频、发布图文; 搜索视频、作品详情、用户主页、我的主页、分享链接解析。
零三方依赖:只用 Python 标准库(协议层与读取通道都自己写,见下); 浏览器驱动按需取、浏览器用系统 Chrome —— exe 因此能保持小。
发布是两步:预检(不碰账号)→ 用户确认 → 执行(见「发布门禁」); 读取不吃 confirm —— 它只看、不动账号,所以不值得多一次往返。
两种形态:
stdio(默认,宿主起子进程)与streamable_http(本机常驻 + 状态页)。
它不重写任何平台逻辑,这一层只做四件事 —— 参数构造、素材白名单、协议适配、确认门禁;读取则由本服务直连抖音 web 接口 (带上用户登录 cookie),把上游几十 KB 的响应裁成几句人真正会看的字段。
两种形态:选哪个
|
| |
启动方式 | 宿主当子进程拉起( | 商店配置给 |
端点 | stdin/stdout,一行一个 JSON-RPC |
|
需要打包 exe | 不需要( | 需要( |
扫码登录 | 会话式工具:弹真窗口扫码,成功后窗口自动关闭 | 同上,外加本机状态页 |
宿主重启 | 子进程跟着死 | 服务不重启(登录态、运行记录都在) |
停用 | 宿主 kill 子进程 | 客户端按进程台账 / 端口归属收进程( |
鉴权 | 无需(父子进程) | 可选 |
适合 | 只想用工具、不想装东西 | 要登录页、要长任务不被宿主重启打断 |
同一份工具实现,两种形态共用;商店里只发布其中一条(两条都发会让同一批工具在注册表里重名)。
Related MCP server: Douyin API New MCP Server
为什么值得包一层
直连 sau CLI 有三个坑,这一层把它们挡在模型之外:
CLI 的参数细节(
--images是 nargs、--tags要逗号分隔、--schedule是YYYY-MM-DD HH:MM本地时间)不该让模型记;记错的表现是"命令跑了一半失败"。素材路径由模型给,属于不可信输入。不加闸 = 能把本机任意文件传到抖音。
发布必须有人点过头。CLI 一旦被调用就是真发布,工具层必须自己带确认门禁 (见下),不能指望模型自觉。
前置:装个浏览器就行(不再需要 social-auto-upload)
v0.3.0 起登录 / 账号检查 / 发布全部自带(就放在本包里,跑在 --creator-helper 子进程里),
所以"先用另一个项目把 sau 装起来、再配两个环境变量"这一步没有了。
运行时要的只有:
一个 Google Chrome(或 msedge)。默认
channel=chrome; 用DOUYIN_CREATOR_CHANNEL可换成msedge。不带 Chromium —— patchright 自带那份要另下约 170MB,与"exe 保持小"冲突。浏览器驱动(patchright)。不进 exe,首次用到时按需取(见 「浏览器通道的依赖怎么来」); 内网机器可用
DOUYIN_BROWSER_DRIVER_ARCHIVE预置本地 zip。登录一次:调
douyin_account_login扫码(弹真窗口,扫完自动关), 凭据落在本服务自己的数据目录(%LOCALAPPDATA%\douyin-publish-mcp\data\)—— 不再依赖别人的cookies/目录。
旧版本把"发什么"交给机器上的
sau命令,于是可用性等于别人项目的可用性。 现在这条路去掉了,代价是本包自己承担自动化流程的维护(选择器改版要跟着改)。
配置(环境变量)
由商店安装时填的 envVars 提供;也可以在 MCP 配置页补填/修改。
★ v0.3.0 起统一 DOUYIN_ 前缀,SAU_* 全部作废。
变量 | 必填 | 说明 |
| 否 | 可选的素材根目录白名单。配了 → 素材路径必须落在它里面;不配 → 不限制目录(只校验文件存在) |
| 否 | 默认账号名(默认 |
| 否 | 单次调用超时秒数,默认 900(上传慢,别调太小) |
| 否 |
|
| 否 | 创作者中心自动化的浏览器通道,默认 |
| 否 | 短信二次验证的验证码文件,默认 |
| 否 | 凭据/二维码/验证码文件的数据目录,默认 |
| 否 |
|
| 否 | 显式指定凭据文件(storage_state 或裸 Cookie 串)。不填就用数据目录里的 |
| 否 | 直接给整串 cookie(容器 / 临时调试用,只能用于读取:发布需要完整 storage_state 文件) |
| HTTP 形态可选 | 填了就要求 |
装完就能发,不需要先配任何变量。 DOUYIN_MEDIA_DIR 是可选的收窄开关:
不填时任何可读文件都能发布,填了就变成一个硬边界(目录外的文件一律拒绝)。
想收窄权限(比如只允许发某个素材目录)再填它。
早先这个变量是"发布必填",没配就拒绝发布。但那意味着装完不配就用不了, 门槛比收益高,已改成可选(v0.3.1)。配错的代价也更小:填了个不存在的路径会明确报错, 不会静默当成"没配"。
只不装浏览器 / 只想读取行吗?
行 —— 读取不依赖浏览器自动化。 实测(Windows,本机,2026-10-08 实测):
能力 | 需要什么 | 说明 |
服务启动 / | 只要 Python | 起得来 |
读取 5 个工具 | 一份 cookie | 设 |
浏览器通道(详情 / 用户作品 / 评论) | 驱动 + Chrome | 驱动按需自取、浏览器用系统 Chrome |
扫码登录 / 账号检查 | 自带自动化 + Chrome | 登录要真窗口;登录态检查是直连探针,不开浏览器 |
发布 5 个工具 | 上面全部 + 素材目录 | 需要完整 storage_state 文件(只给裸 cookie 不够) |
两点代价,先想清楚再走这条路:
cookie 会过期 —— 过期后读取报
no_credential/blocked,得重新导出一份。 长期用还是走douyin_account_login扫码更省事(能续期), 这条路适合"导一次、只读一阵子"。凭据两种格式都认:浏览器 DevTools 里复制的整串 Cookie,或 patchright / Playwright 的
storage_stateJSON。给了文件就优先用它 —— 环境里的残留文件不会盖掉你明确指定的那个。
商店条目里
envVars故意留空也是同一个原因:素材目录与 cookie 路径都是机器相关的, 猜一个写死进去,错了就是"装完直接报找不到文件",比留空更难排查。
十个工具(5 个发布/账号 + 5 个读取)
工具 | 作用 | 模型该怎么用 |
| 查登录态(单个或一次多个) | 判据是直连探针 |
| 扫码登录(会话式) | 弹真窗口(抖音会挑无头浏览器,且可能要输短信验证码),二维码同时以图片返回;扫完窗口自动关闭(没人扫也最多 2 分钟);调用等一段就返回状态,还在等就再调一次继续查(复用同一个会话,不会另开;要换新码传 |
| 重置登录态 | ★ 两步:先回报"将要删除的凭据文件",用户同意后才 |
| 发布视频 | 先不传 confirm 拿计划 → 念给用户 → 带 |
| 发布图文(≤35 张,不支持 GIF) | 同上;长正文用 |
| 关键词搜视频 | 返回 aweme_id、作者(昵称 + sec_user_id)、互动数据、无水印直链。 |
| 单条作品详情 | 也能吃整条链接(内部抽 id);报"没取到"表示 id 不对,或作品已删/私密 |
| 用户主页 + 最近作品 | sec_user_id 从搜索/详情的作者字段里拿( |
| 当前登录账号自己的主页 | 回答「我这个号发了多少、粉丝多少」用它,不用传 id |
| 分享文本 → 作品详情 | 用户贴「…复制打开抖音… https://v.douyin.com/xxxx/」时用它;链接过期或给的是主页/合集链接,会说明原因而不是静默失败 |
读取工具的 account 都可以省略(默认 DOUYIN_ACCOUNT,兜底 main)。
download_url 是有时效的直链(通常几小时),要保存就当场下载;本服务只返回地址,不落盘。
schedule 传本地时间 '2026-03-24 21:30' 即走定时发布;不传 = 立即发布。
多账号:同账号串行、不同账号并行
一个进程可以同时管多个抖音号,每个号一份 douyin_<账号>.json,互不覆盖
(发布 / 登录 / 登出 / 查登录态的 account 本来就是必填;读取类可省略,省略即落到默认账号)。
同账号串行:同一个号的两个操作会排队。两个浏览器带同一份登录态并发操作,平台侧看着就是 "同一设备在并发操作";而且登录成功与发布成功都会回写登录态,后写的会盖掉先写的 (可能拿较旧的 cookie 覆盖较新的)。
不同账号并行:各跑各的(凭据文件、指纹各自独立),所以"同一篇内容发到多个号"是并行的, 不会被排成一条队列。
例外:
douyin_account_status不吃锁 —— 它只打一次直连探针(不开浏览器), 锁住会让"扫完查一下登录态"卡在正在跑的发布后面,正好把最需要它的时候堵死。登录会话也按账号:每个号各等各的 —— 登录
work不会顶掉personal还在等扫码的会话。等扫码不占锁:登录会起一个浏览器等用户扫码(最长几分钟),那段时间不占锁 —— 否则"扫完再调一次确认结果"会被自己堵死。
⚠️ 多账号下读东西建议一律显式传 account,免得读错号。
发布参数(这些不是"锦上添花")
工具参数覆盖创作者中心真实支持的开关:
场景 | 参数 | 少了的后果 |
自定义封面 |
| 用平台自动截的帧当封面 |
带货 |
| 商品没挂上,白发了 |
自主声明 |
| 该声明的没声明,合规风险 |
合集 |
| 作品没进合集,播放路径少一条 |
长正文/背景音乐 |
| 正文只能塞在参数里,容易截断 |
封面与
note_file同样是把本机文件交给平台,所以配了DOUYIN_MEDIA_DIR时 它们也要走同一道白名单(没配则不限制目录)。
登录为什么是"会话"而不是一次调用
扫码登录会一直等到用户扫完码(几十秒到几分钟)。若当成同步调用,会把客户端卡住, 而且中断后没有任何地方能回答"刚才那次登录怎么了"。所以:
每个账号同一时刻只保留一个待扫码会话;已经在等就复用(重复调用只是"继续查 那一个",不会把用户手里那张二维码弄失效)。确实要换一张新码时传
force=true;会话状态(等待中/结束/输出/二维码)留在进程里,工具与状态页读的是同一份;
登录流程结束后自动跑一次检查:流程走完 ≠ 扫上了,用户关心的是后者;
等待扫码期间不做检查(那时已有一个浏览器,再起一个既慢又容易让用户误以为"检查结果是没登录")。
⚠️ 多账号下每个号各等各的:登录
work不会顶掉personal还在等扫码的会话。
重置登录态(唯一的删除操作)
这条链路上"退出登录"就是删掉凭据文件:
<数据目录>/douyin_<账号>.json(DOUYIN_COOKIE_FILE显式指定的那份则删它)。只删这一个文件:不递归、不删目录、不碰其它账号;
confirm=false时只看不删。
发布门禁(本服务最要紧的一条)
第一次:不带 confirm → 只做本地预检(路径/长度/时间格式),返回计划 + plan_id,**绝不碰账号**
第二次:plan_id + confirm=true → 校验 plan_id 与本次参数算出的指纹一致,才真正执行plan_id是计划内容的哈希(账号+类型+素材+标题+正文+标签+时间)。因此"模型忘了确认直接发"和"用户确认的是 A、发出去的是 B"都发不出去。
但这只约束程序流程,不是独立的人工审批:真正的把关是工具描述里"必须先给用户看" 这条要求,以及平台侧的工具审批(若该平台配置了)。
读取能力怎么来(三条通道,逐级回退)
读取不"一刀切用浏览器":先直连,被风控挡住才回退浏览器通道,两者都拿不到才如实报错。
通道 | 用什么 | 覆盖的接口 |
① 直连 | 标准库 | 搜索、用户主页、我的主页(实测各 5/5,亚秒级) |
② 浏览器 | patchright 驱动系统 Chrome:先导航到页面,再抓抖音自己发的响应 | 作品详情、用户作品(这两个接口的墙是 uifid 设备指纹:直连 0/5、带签名同样 403)、评论 |
③ 都没有 | —— | 如实报 |
★ 为什么不是"在页面里发 fetch":实测裸 fetch 回放 → 403 Uifid Not Found;
手工补上抓到的真 uifid(真值 60 字符)→ 403 Signature Not Found。uifid 与 a_bogus
是抖音自己的请求封装注入的,原生 fetch 绕不过去;而它自己发起的请求
(打开 /video/<id>、/user/<sec_uid> 时触发的 XHR)全是 200。
所以浏览器通道的形态是导航 + 抓它自己的响应(且必须在 response 回调里立刻读 body,
晚一步 body 就释放了)。
★ 为什么不做 a_bogus 签名(不引 V8 引擎):评论接口确实需要签名(实测不签名→空响应、 带签名→200),但作品详情/用户作品那堵墙签名救不了(第三方实现带签名同样 403)。 既然浏览器通道本来就要为它俩而建,评论就搭同一条车 —— 省掉一个 V8 引擎和 558KB 混淆 JS 的依赖。
★ 成本:一次浏览器抓取实测 0.4~5 秒(冷启 + 等页面自己发请求,同一页面上的多条需求合并成一次导航);
直连是亚秒。所以回退只在 blocked 时发生,能直连的接口不会平白多等。
工具输出里只在真回退过时附一句"通道:…"。
浏览器通道的依赖怎么来(exe 保持小 + 按需取驱动)
组成 | 从哪来 | 体积 |
宿主 | 本服务自己: | 0 |
驱动 | patchright(纯 Python,含 node driver)—— 取法见下表 | ~90MB,按需 |
浏览器 | 系统 Chrome 优先(实测 153.x 够用);起不来退自带 chromium;都没有才下载 | 0(默认路线) |
★ 冻结(PyInstaller)后有个坑:PYTHONPATH 对 exe 不生效,所以客户端用
DOUYIN_BROWSER_DRIVER_PATH 把驱动目录传给 helper,由 helper 自己插进 sys.path
(实测不这么做就是 No module named 'patchright')。同理,打包时要带上整份标准库,
否则运行期挂上来的 patchright 会 No module named 'uuid'。
驱动的取用顺序(只在真的要用、又真的缺时才动;一个来源都没有就明确报错,不猜、不偷偷拉 PyPI):
来源 | 怎么配 | 说明 |
本机已有 |
| 例如本机某个装了 patchright 的 venv 的 |
运行时目录 | 默认 | 下面两种方式都落到这里,之后就不再重复取 |
本地归档 |
| 离线/内网预置:zip 内含 |
发布源 | 默认已内置(Gitee 附件 | 只信哈希:不匹配就拒装(截断过的来源是真实踩过的坑) |
其它开关:
变量 | 作用 |
| 完全关掉浏览器通道(只留直连) |
|
|
| 有头运行(调试用:看页面到底显示了什么) |
| 禁止任何自动下载(驱动包 / chromium) |
| 等目标接口响应上限(默认 45000) |
静默与边界:默认无头、不弹窗口;helper 起-抓-关,不留常驻进程。
但"无感"≠"无痕" —— 调用那几秒任务管理器里会出现 chrome.exe(用完即退);
本服务不做隐藏进程、不做反检测规避。
内网机器注意:驱动要预置(本地归档或运行时目录),浏览器要有(系统 Chrome 或自带 chromium 任一)。
端到端验收:scripts/verify_flow.py
验收分本地段与真机段 —— 两者的成本差一个数量级,能分开跑就不该捆在一起:
段 | 环节 | 需要什么 |
本地 | 单测 → 协议层 → 发布门禁 → HTTP 形态 | 只要 Python。不联网、不起 helper、不碰账号 |
真机 | 环境前置 → 登录态 → 读取五连 → 浏览器通道 → 发布预检 | 登录态 + 外网 + Chrome(驱动按需取) |
cd E:\项目\AI\douyin-publish-mcp
$env:PYTHONPATH="src"
& ..\.venv\Scripts\python.exe scripts\verify_flow.py --local-only # 只有 Python 就够
& ..\.venv\Scripts\python.exe scripts\verify_flow.py # 本地段 + 真机段
& ..\.venv\Scripts\python.exe scripts\verify_flow.py --keyword 猫 --publish-file a.mp4真机段要的 DOUYIN_* 按现场给(例如复用一份已有 cookie):
$env:DOUYIN_COOKIE_FILE="<凭据 json 的绝对路径>" # 不设就用数据目录里扫码存下的那份
$env:DOUYIN_MEDIA_DIR="<素材目录绝对路径>" # 可选:配了才限制发布目录脚本走的是和客户端完全相同的 Server.handle 路径(不是另写一套调用),每步给
PASS / FAIL / SKIP:
本地段:全部单测;协议握手与 10 个工具的 schema;发布门禁(预检只出计划,
plan_id不符与内容改过都必须被拒,并断言全程 0 个 helper 进程);HTTP 形态 (真起服务、真发请求:/health免鉴权、无 token 401、状态页有「读取通道」行、 无凭据时读取工具给的是可读提示而不是空结果 —— 这个用例会自己清干净凭据环境, 免得被真机段设的DOUYIN_COOKIE_FILE串味)。真机段:登录态(直连探针);读取五连(搜索 → 详情 → 用户主页 → 我的主页 → 分享解析,后三步用前一步真拿到的
aweme_id/sec_user_id串起来); 浏览器通道(单独验详情 + 评论);发布预检(用你自己的素材)。默认不发布任何东西:发布只跑到"预检 + 门禁必须拦住"。要真发得显式加
--confirm-publish。SKIP 不等于通过:脚本最后会单独列出"还没验过的"。本地段全绿只说明服务的壳是对的, 不说明抖音认它 —— 判决点是真机段的「搜索」那一步。
退出码:
0= 没有 FAIL(可以带 SKIP);1= 有 FAIL。
实测留痕(2026-10-08,本机):本地段 4 PASS / 0 FAIL;带
DOUYIN_COOKIE_FILE+DOUYIN_MEDIA_DIR跑完整两段 = 13 PASS / 0 FAIL / 1 SKIP(唯一 SKIP 是"真发", 因为没加--confirm-publish)。读取走直连通道,浏览器通道 17~19 秒拿到详情 + 评论。
没有脚本时的手动版(等价,按顺序来)
douyin_account_status(account="main")—— 期望「已登录」(读取的前置)douyin_search_videos(keyword="美食", count=5)—— 期望有作品;若报 blocked,按上面的排查顺序走douyin_video_detail(aweme_id="<第 2 步拿到的 id>")—— 期望有无水印直链douyin_user_profile(sec_user_id="<作者字段里的 sec_user_id>", limit=5)douyin_my_profile(limit=5)
还没做的(第二批)
互动与通知:发评论 / 回复 / 点赞 / 收藏、通知未读数与通知列表。 它们的接口路径需要在真机上验过再合并 —— 没验过的路径写进来只会变成"永远空结果", 而那是这个项目最不能接受的失败形态:看起来能用,实际读不到。
streamable_http 形态
# 启动(默认只绑 127.0.0.1,port 18080)
douyin-publish-mcp --http --port 18080
# 需要局域网访问时必须给 token(不给会直接拒绝启动)
douyin-publish-mcp --http --host 0.0.0.0 --token <secret>
# 探活(永远免鉴权,供启动器使用)
curl http://127.0.0.1:18080/health
# 走一遍协议
curl -X POST http://127.0.0.1:18080/mcp -H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}'端点一览:
路由 | 说明 |
| MCP JSON-RPC(tool 调用都走这里) |
| 本机状态页:配置摘要、发起/取消扫码登录、重置登录态、最近输出 |
| 发起扫码登录(会话式,页面立刻返回) |
| 检查登录态(后台跑,结果落在 |
| 重置登录态: |
| 取消等待扫码的会话 |
| 当前登录二维码(CLI 落盘了才有;抖音这条链路通常没有,返回 404) |
| 运行状态 JSON(页面轮询用;与工具看到的是同一份会话状态) |
| 探活 |
| 405(本实现不提供 server→client 的 SSE 流,明说比挂着空流诚实) |
打包成独立可执行文件
command 必须是可执行文件(不能是 uvx ... 这种父进程起子进程的包装:
停用时父进程被杀、真正监听端口的子进程会留下):
# 第一次:装 PyInstaller(内网可加 -PipIndexUrl <内网源>)
.\packaging\build_exe.ps1 -InstallPyInstaller
# onedir(推荐:单进程,停用时按台账就能收干净)
.\packaging\build_exe.ps1
# 或 onefile(单文件更省事,但会多一层自解压子进程 —— 靠客户端的端口归属兜底仍能收掉)
.\packaging\build_exe.ps1 -OneFile产物默认拷到 %LOCALAPPDATA%\douyin-publish-mcp\,正好对上商店配置里的 command。
★ 脚本必须带 UTF-8 BOM:Windows 自带的 PowerShell 5.1 对没有 BOM 的
.ps1按 ANSI(GBK) 读,中文注释会变成乱码并以语法错中断(报错里能看到锛堝唴缃?这种乱码)。 脚本内部调 python / PyInstaller 也统一走Invoke-Native—— PS 5.1 会把原生命令写往 stderr 的日志当成致命错误并中断脚本,而 PyInstaller 顺利运行时也会往 stderr 写 INFO (不包的话表现成"打包到一半停了,只看到一行 INFO",很容易被误读成打包失败)。
打包后自检(本机已跑通):
& "$env:LOCALAPPDATA\douyin-publish-mcp\douyin-publish-mcp.exe" --http --port 18080
# /health → {"status":"ok","service":"douyin-publish-mcp","version":"0.3.1"}
# POST /mcp tools/list → 10 个工具onedir 还是 onefile(实测结论,不是推测):
onedir(默认) | onefile(Release 资产用这个) | |
产物 | 一个目录(含 | 单个 exe(约 10.9 MB) |
分发 | 整目录拷过去 | 只拷一个文件 |
启动 | 快(约 1s) | 首次多几百 ms(自解压) |
停用能否收干净 | 单进程,按台账直接收 | ★ 会留下一层同名子进程(自解压的 bootloader),父进程被杀后它可能仍在监听端口 —— 靠客户端的端口归属兜底(映像名 == 配置的 exe 名)收掉 |
所以:发布到 Release 用 onefile(对齐小红书的"裸二进制"资产形态、用户只下一个文件); 本地/内网部署用 onedir 更省心。两者工具实现完全相同。
从 Release 安装(使用者)
发布源(Gitee 镜像,本公司账号):https://gitee.com/pan-wenda/douyin(当前 v0.3.1)
资产 | 用途 |
| 服务本体:PyInstaller onefile 单文件,约 10.9 MB(11,446,135 字节),自带 Python 运行时,不用先装 Python |
| 整包形态(解压即用;onedir 少一层自解压子进程,停用时更好收) |
| 浏览器驱动(不用手动下:真缺时服务自己按需取,见下面「浏览器通道」一节) |
$dst = "$env:LOCALAPPDATA\douyin-publish-mcp"
New-Item -ItemType Directory -Force $dst | Out-Null
Move-Item .\douyin-publish-mcp.exe "$dst\douyin-publish-mcp.exe" -Force
& "$dst\douyin-publish-mcp.exe" --http --port 18080 # 本机常驻,只绑 127.0.0.1目录和文件名不是随便定的:商店配置里的 command 就是
%LOCALAPPDATA%\douyin-publish-mcp\douyin-publish-mcp.exe —— 形态与商店里的小红书 MCP 一致
(%LOCALAPPDATA%\<服务名>\<服务名>.exe,客户端 expand_env 会展开这个占位)。
★ 但 exe 不是全部:它自带 Python 运行时、自带发布/登录自动化,却不自带浏览器驱动 (patchright 那 ~100MB)与浏览器 —— 驱动首次用到时按需取,浏览器用系统 Chrome。 装完即可用:不需要先配任何变量(
DOUYIN_MEDIA_DIR是可选的收窄开关),见上面的前置条件。
本地调试
# 单元测试(零依赖,含 HTTP 形态的端到端:真起服务再打它)
cd douyin-publish-mcp
set PYTHONPATH=src
..\.venv\Scripts\python.exe -m unittest discover -s tests
# stdio 形态手动走一遍
echo {"jsonrpc":"2.0","id":1,"method":"initialize","params":{}} | python -m douyin_publish_mcp
# http 形态冒烟
python -m douyin_publish_mcp --http --port 18080接进本平台(Dr.Q 客户端)
1. 先决定「本包从哪来」
http 形态:
command= 上一步打出来的 exe 绝对路径(如%LOCALAPPDATA%\douyin-publish-mcp\douyin-publish-mcp.exe),args=--http --port 18080。 exe 需要分发到每台机器(拷目录 / 走你们的内部分发)。stdio 形态:
command=uvx,args=--from <内网包来源> douyin-publish-mcp。 包来源三种写法:
写法 |
| 适用 |
内网 GitLab 归档(与商店里 |
| 内网可达 GitLab,不需要 git CLI、不需要 PyPI |
内网 PyPI |
| 已把包发到内网源 |
本地目录 |
| 单机调试/离线演示 |
★ 三个坑(前两个踩过): ①
args在商店表单里是空格分隔字符串(后端按空白切分),路径不能有空格; ②command/args/cwd会展开%LOCALAPPDATA%这类占位(local_service::expand_env, 未定义的变量保持原样,便于排查"变量名写错")——所以command写%LOCALAPPDATA%\douyin-publish-mcp\douyin-publish-mcp.exe就能适配每台机器, 不必写死用户名; ③ 但envVars里的值不会展开(原样透传给子进程,由子进程自己解释),必须写绝对路径。
2. 发布到商店
前置(http 形态):先 .\packaging\build_exe.ps1 打出 exe —— 商店里的 command
就是这个绝对路径,exe 不在,别人装完也起不来(%LOCALAPPDATA%\douyin-publish-mcp\
只在打包的那台机器上有,要分发到每台机器)。
客户端「MCP 商店」页 → 发布服务,字段照抄:
表单字段 | http 形态( | stdio 形态( |
名称 | 抖音发布与读取 | 同(·stdio) |
传输方式 |
|
|
command |
|
|
args |
|
|
url |
| (空) |
envVars |
| 同左,无 AUTH_TOKEN |
status / visibility |
| 同左 |
走
POST /api/mcp-service-config落库tb_mcp_service_config。★ 只发一条:两个形态共用同一批工具名,同时发布会让注册表里重名。
发布前先跑一遍
scripts/verify_flow.py --local-only:确认tools/list里正好 10 个工具、 描述完整、发布门禁拦得住 —— 商店里装的版本和这份配置是同一个东西,别把没验过的发出去。读取工具用到的
DOUYIN_COOKIE_FILE/DOUYIN_COOKIE(见环境变量表)不放进商店默认: 正常路径下凭据来自本服务数据目录(扫码登录时写下的那份),这两个只在 "读取和发布不是一个账号/换机器复用凭据"时才需要,属高级用法。
3. 安装后的行为差异(这段决定运维怎么做)
http 形态:客户端安装时先确保本机进程起来(
local_service::ensure),再连url;进程是 detached 的,宿主重启不影响它。停用时客户端按 进程台账 + 端口归属(映像名必须等于配置的 exe 名) 收掉进程,所以command里的 exe 名要和真正监听端口的进程名一致(这也是不用uvx包装的原因)。stdio 形态:宿主 kill 子进程即可,没有端口、没有遗留;代价是宿主重启后要重新拉起。
4. 换机器/换目录
改 MCP 配置页里的 env(DOUYIN_MEDIA_DIR / DOUYIN_ACCOUNT)再重启该服务即可,不用重装。
凭据默认落在该机器的 %LOCALAPPDATA%\douyin-publish-mcp\data\,换机器要重新扫码;
想复用旧机器的登录态,把那份 json 拷过去并用 DOUYIN_COOKIE_FILE 指过去。
风险与边界(请连同代码一起看)
底层是浏览器自动化 + 用户自己的登录态:违反抖音平台协议,随时可能被改版/风控打断。 真要长期稳定,走开放平台
video.create(合规但需资质与用户授权)。本服务不存储账号密码,但登录态(cookie / storage_state)会落在本机数据目录里 —— 那是凭据,不要提交进任何仓库。★ 读取通道必须读到 cookie 的值(否则发不出请求), 但对外只回显来源与 cookie 名:工具输出、状态页、日志里都不会出现值。 「重置登录态」是唯一的删除动作,且只删
<数据目录>/douyin_<账号>.json一个文件。读取工具会把公开内容与你自己的账号资料带进对话上下文(含无水印直链,几小时后失效)。 只用它读公开内容与自己有权看的账号;把
limit调大、连续多次搜索会显著提高被风控的概率。http 形态默认只绑
127.0.0.1;改绑别处必须配 token —— 这个服务能直接发布内容。每次发布都会真实落到用户账号上;"提交成功"不等于"已公开可见"(平台还有审核)。 ★ 点过「发布」但没等到成功页 →
state=uncertain,这时绝不自动重试(重试就可能发两条), 必须让人去创作者中心「作品管理」核对。短视频平台的标题/正文/图片数量限制会变,本服务里的长度预检(标题 30 字、正文 1000 字) 只用于尽早报错,不代表平台真实限额。
许可
Apache License 2.0 —— 与商店里的小红书 MCP(xpzouying/xiaohongshu-mcp)
采用同一许可,便于两边一起用、一起改。
Available Tools
10 toolsdouyin_account_loginA
让用户扫码登录抖音。★ 会弹出一个真浏览器窗口:登录这一步必须用真窗口 —— 抖音的反自动化会挑无头浏览器,而且可能要求短信二次验证,那只能在窗口里手动输。二维码同时也会作为图片返回(和窗口里是同一个码),展示给用户扫也行。扫码成功后窗口会自动关闭(sau 存完 cookie 就关掉浏览器并退出,约 2 秒后消失);若一直没人扫,窗口最多活 2 分钟也会自己关,不会一直挂在用户屏幕上。调用会等一段(wait_seconds):扫得快就一次拿到结论;还在等就返回「会话仍在等待扫码」,此时再调一次本工具即可继续查,不要重复发起新登录。若发布时触发短信二次验证,把验证码写进项目根目录的 verify_code.txt 再重试发布。
| Name | Required | Description | Default |
|---|---|---|---|
| headed | No | 是否弹出浏览器窗口。默认 true:登录必须用真窗口(抖音的反自动化会挑无头浏览器,且可能要输短信验证码);扫码成功后窗口自动关闭。只在没有桌面会话(CI/服务器)时才传 false。 | |
| account | Yes | 账号名(自定义,用于区分多个抖音号) | |
| wait_seconds | No | 本次调用最多等多少秒(默认 90,上限 600)。超时不中断登录:会话仍在后台等扫码。 |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden and does so: a real browser window pops up, auto-closes about 2s after a successful scan, self-closes after at most 2 minutes if unscanned, and wait_seconds timeouts do not abort the background session. It also discloses the anti-automation and SMS-verification constraints and the verify_code.txt workaround.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the window behavior and timeout semantics that govern how to call it, and nearly every sentence adds operational value. Minor redundancy with the schema's headed description and slightly dense bolding keep it from a 5.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, and the description compensates by describing the return states ('scan succeeded' vs 'session still waiting for scan'), window lifetime, and the SMS-verification recovery path. An agent has everything needed to invoke, poll, and recover.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3; the description nevertheless adds meaning by explaining that wait_seconds' timeout does not interrupt login and that the session keeps waiting in the background, plus the polling consequence. headed is only restated, so it is not a full 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource: logging a user into Douyin via QR scan. The scope (per-account login, distinct from status/logout siblings) is unambiguous, and an agent can tell it is the credential-establishing tool rather than a read or query tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly tells the agent to re-call this same tool when the session is still waiting rather than starting a new login, and gives the condition for setting headed=false (only on CI/servers with no desktop session). It also routes SMS-verification retries through verify_code.txt, which is real alternative-path guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
douyin_account_logoutA
重置某个账号的登录态(相当于小红书 MCP 的 delete_cookies)。本服务只删一个文件:<项目>/cookies/douyin_<账号>.json —— 那是 sau 的登录凭据。★ 两步:不传 confirm 时只回报「将要删除的路径」,什么都不删;用户明确同意后才传 confirm=true。删完该账号变回未登录,发布前要重新扫码。注意这是「退出登录」不是「卸载」:项目目录、素材、已发布的作品都不受影响。
| Name | Required | Description | Default |
|---|---|---|---|
| account | Yes | 账号名 | |
| confirm | No | 用户已明确同意删除凭据时传 true |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does so richly: it names the exact file affected, its role as the login credential, the irreversible effect (account returns to logged-out), and explicitly scopes out collateral damage (project dir, materials, published works unaffected). This is exactly the behavioral context an agent needs before triggering a destructive confirmation flow.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action and outcome, then the workflow, then the scope caveat. Dense but every clause carries operational weight; the ★ markers aid scanning. Slightly long, but justified by the destructive nature of the operation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive, no-output-schema, no-annotation tool, the description covers effect, confirmation discipline, post-condition, and non-effects — everything needed to invoke it safely.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so both params are already documented, giving a baseline of 3. The description adds real semantics beyond the schema by defining confirm's role as a two-phase safety gate rather than a plain boolean.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource (重置某账号登录态) and immediately clarifies the exact mechanism: deleting a single cookies file, not uninstalling. It also distinguishes itself from account_login/account_status by describing the resulting state and the 'logout not uninstall' boundary.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly prescribes the two-step workflow: with no confirm it only reports the intended path (dry run), and confirm=true may only be passed after the user explicitly agrees. It further gives the follow-up condition (must re-scan QR before publishing), leaving nothing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
douyin_account_statusA
查询某个抖音账号在 social-auto-upload 里的登录态(本地 cookie 是否还有效)。发布/登录前先查一次,避免发到一半才发现没登录。account 是登录时用的账号名(不是抖音昵称)。
| Name | Required | Description | Default |
|---|---|---|---|
| account | Yes | 账号名(social-auto-upload 里登录时用的名字) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden and does disclose that this reads local cookie validity state in social-auto-upload, implying a non-mutating local check. It stops short of stating side effects, failure behavior, or what an invalid result looks like.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the core purpose before the usage hint and the parameter caveat. No redundant restatement of the tool name; tight and appropriately sized.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter tool with no annotations, the description covers purpose, timing, and parameter identity well, but there is no output schema and the description never says what the check returns (boolean, expiry, error shape). That leaves a small but real gap for an agent deciding how to consume the result.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds a genuine disambiguation the schema lacks: account is the login name used in social-auto-upload, NOT the Douyin nickname. That extra meaning reduces a real selection error.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (查询/query) and resource (抖音账号登录态), and clarifies the mechanism (本地 cookie 是否还有效 in social-auto-upload). An agent can distinguish it from douyin_account_login/logout/publish without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a clear trigger: check before publishing or logging in to avoid discovering mid-way that you're not logged in. There is no explicit exclusion list or naming of a sibling alternative, but the when-to-use context is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
douyin_my_profileA
看当前登录账号自己的主页信息与作品列表(不需要传 sec_user_id)。适合回答「我发了多少条、最近的播放/点赞如何」「这个号登录的是谁」。
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | 作品条数上限(默认 20,最多 100) | |
| account | No | 账号名(social-auto-upload 里登录时用的名字)。不传则用默认账号(SAU_ACCOUNT,兜底 main)。 | |
| include_videos | No | 是否返回自己的作品列表(默认 true) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. The verb '看' and 'info + work list' make clear this is a non-mutating read scoped to the current login, which is useful, but it says nothing about pagination behavior, output volume limits, or what happens if no account is logged in. Adequate but incomplete for a zero-annotation tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two compact sentences: the first front-loads what is returned and the key constraint, the second supplies concrete answerable questions. No filler or redundancy; every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only, zero-parameter-required tool with no output schema, the description communicates both scope (self profile + works) and the kinds of questions it answers, which effectively conveys the return shape. Missing only edge-case behavior (logged-out state, large result sets), so slightly under complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents limit (default 20, max 100), account (default SAU_ACCOUNT/main), and include_videos (default true). The description adds only the no-sec_user_id point and does not elaborate on any parameter, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific resource (the current account's profile and work list) and a specific actor (the logged-in account itself), and explicitly distinguishes it from the sibling douyin_user_profile by stating sec_user_id is not needed. An agent can immediately tell this is the 'self' read path versus the arbitrary-user path.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It supplies concrete use cases ('how many posts have I made, recent plays/likes', 'which account is logged in'), which gives clear selection context, and the 'no sec_user_id' note implicitly routes non-self queries to douyin_user_profile. It stops short of an explicit when-not/exclusion statement, so a 4 is right.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
douyin_publish_noteA
发布一条抖音图文(多图 + 标题 + 正文)。【必须先确认】不传 confirm 调用时,本工具不会发布任何东西,只返回一份待发布计划;请把这份计划(账号、素材、标题、正文、标签、发布时间)原样念给用户,得到用户明确同意后,再用同一个 plan_id 加上 confirm=true 调用一次。不要自己替用户决定发布,也不要跳过确认直接传 confirm。
| Name | Required | Description | Default |
|---|---|---|---|
| bgm | No | 背景音乐**搜索词**(可选),如「轻快 纯音乐」;不是文件路径。 | |
| note | No | 图文正文(可选)。与 note_file 只能给一个。 | |
| tags | No | 话题标签(可选) | |
| title | Yes | 图文标题(≤30 字,单行) | |
| images | Yes | 图片路径列表(必须在素材目录内),抖音最多 35 张、不支持 GIF | |
| account | Yes | 账号名 | |
| confirm | No | 用户已明确同意发布时传 true | |
| plan_id | No | 上一步预检返回的 plan_id(确认发布时必填) | |
| schedule | No | 定时发布时间(可选),格式 'YYYY-MM-DD HH:MM' | |
| note_file | No | 把正文放在文件里(可选,素材目录内的 .txt/.md 路径)。长正文建议用这个。 |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does disclose the critical behavior: a confirm-less call is a dry run that publishes nothing and returns a plan. However it omits auth/account prerequisites, failure behavior, and what happens to a scheduled post after acceptance.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose and the confirmation constraint are front-loaded, and every sentence carries an instruction. It is slightly verbose and repetitive with the bolded warning markers, which costs a point but not comprehension.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, but the description explains what the first call returns and how to proceed, which is the key gap to fill for a two-phase publisher. Missing pieces such as account/login prerequisites and error handling keep it short of complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is already 100%, so the baseline is 3. The description goes beyond the field-level text by explaining the call-to-call relationship between plan_id and confirm, which the schema states only in isolation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb+resource: 发布一条抖音图文(多图 + 标题 + 正文). The 图文 qualifier cleanly separates it from the sibling douyin_publish_video, so an agent can pick the right publisher without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states the workflow: first call without confirm publishes nothing and returns a plan; read the plan to the user, obtain explicit consent, then call again with the same plan_id plus confirm=true. It also states an exclusion — do not pass confirm=true directly or decide on the user's behalf.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
douyin_publish_videoA
发布一条抖音视频。【必须先确认】不传 confirm 调用时,本工具不会发布任何东西,只返回一份待发布计划;请把这份计划(账号、素材、标题、正文、标签、发布时间)原样念给用户,得到用户明确同意后,再用同一个 plan_id 加上 confirm=true 调用一次。不要自己替用户决定发布,也不要跳过确认直接传 confirm。
| Name | Required | Description | Default |
|---|---|---|---|
| file | Yes | 视频文件路径(必须在素材目录内,可用相对路径) | |
| tags | No | 话题标签(可选),如 运动、训练 | |
| title | Yes | 作品标题(≤30 字,单行) | |
| account | Yes | 账号名 | |
| confirm | No | 用户已明确同意发布时传 true | |
| plan_id | No | 上一步预检返回的 plan_id(确认发布时必填) | |
| schedule | No | 定时发布时间(可选),格式 'YYYY-MM-DD HH:MM'(本地时间);不传=立即发布 | |
| collection | No | 加入已存在的合集名(可选)。合集必须已存在,否则脚本找不到就跳过。 | |
| declaration | No | 作品自主声明(可选),要填平台给出的**原样文案**(如「虚构演绎,仅供娱乐」);不确定就别传。 | |
| description | No | 正文/描述(可选) | |
| product_link | No | 带货商品链接(可选)。★ 必须与 product_title 一起给,只给一个平台不认。 | |
| product_title | No | 带货商品标题(可选,与 product_link 成对) | |
| thumbnail_portrait | No | 竖版封面 3:4(可选,素材目录内的路径)。与 landscape 可同时给。 | |
| thumbnail_landscape | No | 横版封面 4:3(可选,素材目录内的路径)。 |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden, and it discloses the single most important trait: without confirm the tool publishes nothing and only returns a plan. It also scopes what the returned plan contains (account, assets, title, body, tags, publish time). It does not cover auth requirements, failure modes, or what happens if plan_id is stale, so it falls short of a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The critical constraint (does not publish without confirm) is front-loaded in bold, and every sentence serves the confirmation protocol. Slightly long, and the closing '不要自己替用户决定发布' partially restates the earlier consent requirement, but overall tight for a high-risk write tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 14-parameter write tool with no annotations and no output schema, the description supplies the necessary behavioral contract and explicitly enumerates the plan fields the agent will receive, compensating for the missing output schema. Remaining gaps (auth, error handling) are moderate.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds meaning beyond the schema for the confirm/plan_id pair: it explains the idempotent two-step reuse of plan_id and that the plan must be echoed to the user first. Other parameters are left to the schema, which is acceptable at full coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('发布一条抖音视频') that an agent can immediately distinguish from the sibling douyin_publish_note (note vs. video). No ambiguity about what the tool does.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit two-phase protocol: call without confirm to get a plan, read the plan back to the user verbatim, obtain explicit consent, then re-call with the same plan_id and confirm=true. It also states what NOT to do (don't decide for the user, don't skip confirmation). This is textbook when/when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
douyin_search_videosA
按关键词搜索抖音视频(需要已登录)。返回每条作品的 aweme_id、文案、作者(昵称 + sec_user_id)、互动数据和无水印直链。★ 直链有时效(几小时),要保存就当场下载;本工具只返回地址,不落盘。搜到的 aweme_id 可以喂给 douyin_video_detail 看详情,sec_user_id 可以喂给 douyin_user_profile。
| Name | Required | Description | Default |
|---|---|---|---|
| sort | No | 排序:general=综合(默认)、like=最多点赞、latest=最新 | |
| count | No | 返回条数(默认 10,最多 20) | |
| account | No | 账号名(social-auto-upload 里登录时用的名字)。不传则用默认账号(SAU_ACCOUNT,兜底 main)。 | |
| keyword | Yes | 搜索关键词 | |
| publish_time | No | 发布时间范围:all=不限(默认)、day=一天内、week=一周内、half_year=半年内 |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden and does so well: it discloses the login prerequisite, that links are watermark-free and time-limited (几小时), and that the tool only returns URLs without persisting files. This is meaningful operational context an agent needs to act correctly, though it says nothing about rate limits or failure modes.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Single dense paragraph with the core search purpose front-loaded, followed by return fields and the expiry caveat. Every clause earns its place, though the return-field enumeration is slightly list-like and could be trimmed.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, so the description correctly enumerates the return fields (aweme_id, 文案, author, interaction data, watermark-free link) and adds the critical link-expiry caveat. Combined with the login requirement and follow-up routing, an agent has everything needed to call and use the result.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all five parameters (sort, count, account, keyword, publish_time) are already documented with defaults and enum meanings. The description adds no parameter-level detail beyond the schema, making the baseline 3 appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (搜索/search) and resource (抖音视频/Douyin videos) scoped by keyword, and explicitly differentiates from downstream siblings like douyin_video_detail and douyin_user_profile by naming what each returned id feeds into. An agent can identify this as the discovery entry point without opening any other tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear context: it requires an active login, returns only addresses (不落盘), and routes follow-up work to douyin_video_detail and douyin_user_profile. It does not explicitly state when NOT to use it, but since no sibling competes as a search tool, the guidance is effectively complete.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
douyin_user_profileA
看某个抖音用户的主页信息:昵称、抖音号、简介、IP 属地、性别、粉丝/关注/获赞/作品数,并按需返回他最近的作品列表(需要已登录)。sec_user_id 从 douyin_search_videos / douyin_video_detail 的作者字段里拿(形如 MS4wLjABAAAA…)。
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | 作品条数上限(默认 20,最多 100) | |
| account | No | 账号名(social-auto-upload 里登录时用的名字)。不传则用默认账号(SAU_ACCOUNT,兜底 main)。 | |
| sec_user_id | Yes | 用户安全 id(MS4wLjABAAAA… 开头) | |
| include_videos | No | 是否同时返回他的作品列表(默认 true;只看资料传 false 更快) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. It usefully discloses the login requirement ('需要已登录'), which is the key operational trait, but omits whether the call is read-only, pagination/rate-limit behavior, or what happens on a stale/invalid sec_user_id.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single dense sentence, front-loaded with the purpose followed by the return fields and the login caveat. Nothing is wasted, though the chained parentheticals make it slightly less scannable than a two-sentence layout.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description compensates by enumerating the returned profile fields and noting the optional works list plus the login prerequisite. An agent has enough to call it correctly, though read-only status and error/failure behavior remain unstated.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds real value beyond the schema by specifying the sec_user_id format (MS4wLjABAAAA…) and its source in sibling tools, which helps the agent obtain a valid value.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('看某个抖音用户的主页信息') and enumerates the exact fields returned (昵称、抖音号、简介、IP 属地、粉丝/关注/获赞/作品数). It also flags the optional works list. It does not explicitly contrast with the sibling douyin_my_profile, so it falls just short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete context: this needs a login to return the works list, and explains where to obtain sec_user_id (from the author field of douyin_search_videos / douyin_video_detail). It does not state when NOT to use it or name an alternative tool, so no explicit exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
douyin_video_detailA
取单条抖音作品的详情:文案、作者、发布时间、互动数据、封面、无水印播放直链、以及分享页地址(需要已登录)。aweme_id 从 douyin_search_videos / douyin_user_profile / 分享链接里拿。
| Name | Required | Description | Default |
|---|---|---|---|
| account | No | 账号名(social-auto-upload 里登录时用的名字)。不传则用默认账号(SAU_ACCOUNT,兜底 main)。 | |
| aweme_id | Yes | 作品 id(15~25 位数字) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden and does disclose the key trait that login is required before this call succeeds. It also implies a read-only retrieval and highlights a watermark-free direct link as a distinguishing output. It omits failure modes when unauthenticated, rate limits, and pagination/return shape details.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two dense sentences, front-loaded with the returned fields and followed by the prerequisite and ID source. No filler, no restatement of the tool name, and the bolded key output is easy to scan.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read tool with no output schema, the field enumeration substitutes well for a documented return contract, and the login prerequisite is captured. Missing only error/edge behavior (unauthenticated failures, expired login) that an agent would need before invoking.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds meaning beyond the schema by specifying the provenance of aweme_id (from search results, user profile, or a share link), which helps the agent source the required value correctly. The account parameter's default behavior is already documented in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource (retrieve a single Douyin work's details) and enumerates the exact payload: caption, author, publish time, engagement data, cover, watermark-free play link, share page URL. This distinguishes it from siblings like douyin_search_videos and douyin_user_profile, which return lists rather than one work's detail.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Tells the agent the precondition ('需要已登录') and where aweme_id comes from (douyin_search_videos / douyin_user_profile / share link), which is real routing guidance to sibling tools. It stops short of an explicit when-not-to-use or a note on choosing douyin_parse_share_link for URLs, so it is clear but not exhaustive.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
10 tool updates
v0.2.0- First observed
douyin_account_login - First observed
douyin_account_logout - First observed
douyin_account_status - First observed
douyin_my_profile - First observed
douyin_parse_share_link - First observed
douyin_publish_note - First observed
douyin_publish_video - First observed
douyin_search_videos - First observed
douyin_user_profile - First observed
douyin_video_detail
TDQS
Scored across 10 tools
Each tool has a distinct purpose (account ops, publishing, browsing), and descriptions clarify tricky pairs like my_profile vs user_profile (self vs other) and publish_video vs publish_note (video vs image post). Minor overlap remains: douyin_parse_share_link internally duplicates douyin_video_detail's behavior, and the two profile tools could be momentarily confused, but the text disambiguates well.
All names share the douyin_ prefix and snake_case, grouped logically into account_*, publish_*, and entity lookups. The pattern is not uniform though: verb_noun (publish_video, search_videos, parse_share_link), noun_noun (account_status, video_detail, user_profile), and noun_verb (account_login, account_logout) all mix, which is readable but not a single predictable convention.
10 tools is well-scoped for a publish-and-browse server, with each tool earning its place: account lifecycle (3), publishing (2), and content/user browsing (5). No redundancy and no thinness.
Covers the full core lifecycle: login status/login/logout, publish video and image-note (with a safe plan/confirm flow), and rich browsing (search, detail, user/self profiles, share-link parsing). Gaps are minor—no management of already-published works (delete/edit), comments, or interactions—but core agent workflows are covered.
Maintenance
Related MCP Connectors
TikTok search demand, videos, creators, comments and captions for AI agents. OAuth or API key.
Agent social posting via your logged-in Chrome. Remote MCP + OAuth. Not clawpost.dev.
MCP server for QPost — lets AI agents publish video and image posts to YouTube, TikTok, Instagram.
AI social media team for founders: make and publish posts, carousels and short video to LinkedIn, X, Instagram, TikTok, YouTube, Facebook, Threads, Reddit and Bluesky, from any agent. OAuth sign-in, no API key; every draft waits for approval.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables automation of Douyin (TikTok China) tasks including parsing share links to get watermark-free download URLs and uploading videos from specified local paths.14-
- AlicenseDqualityDmaintenanceProvides access to Douyin (TikTok China) API for searching videos, retrieving user profiles, posts, comments, music, challenges, live streams, and hot trends through the Douyin platform.279MIT
- AlicenseNot gradedqualityDmaintenanceEnables automated Douyin video uploads and account management using Playwright for browser simulation. It supports QR code login, cookie persistence, and automated metadata handling for publishing videos through natural language or API commands.24 npm7MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to automatically upload videos to Douyin (TikTok China) creator platform, supporting login, video upload with title/description/tags, and session management.7 npm35MIT