@heartbitai/publish-bots-mcp
v0.1.5
Published
MCP server and automation runtime for media-platform auth and publish workflows
Readme
@heartbitai/publish-bots-mcp
MCP server + TypeScript/Playwright runtime for media-platform auth and publish automation.
Requirements
- Node.js 20+
- pnpm 10+ (for source development)
Install (npm)
# global install
npm install -g @heartbitai/publish-bots-mcp
# install Playwright browser once
npx playwright install chromiumRun MCP server:
bots-mcpWithout global install:
npx -y -p @heartbitai/publish-bots-mcp bots-mcpInstall (Source)
pnpm install
pnpm run buildProject Structure
src/
adapters/
legacy-worker/ # worker protocol bridge and runtime
cli/ # local CLI entry
config/ # runtime selector config
contracts/ # shared types/messages/error codes
core/ # browser session, lifecycle, logging, cancellation
platforms/
shared/ # BaseBot/DOM action/common auth helpers
<platform>/
auth/ # platform auth flow
publish/ # platform publish flow (if supported)
# examples:
# baijiahao/auth
# baijiahao/publish (placeholder)
# toutiao/auth + toutiao/publish
# wechat/auth + wechat/publish
registry.ts # platform factory registryPlatform Support
- Auth:
baijiahao,bilibili,bjh,csdn,douyin,ifeng,juejin,sina,sohu,toutiao,wechat,xhs,zhihu - Publish:
baijiahao,bilibili,bjh,csdn,douyin,juejin,sohu,toutiao,wechat,xhs
Current behavior notes:
- Sohu publish supports article flow (title/body + optional cover upload), and validates publish result via toast or URL transition.
- Baijiahao / CSDN / Juejin / XHS / Douyin publish are available with practical selector fallback logic;
bjhis an alias forbaijiahao. - Bilibili publish targets 专栏链路 (
platform/upload/text/new-article) and includes york-frame precheck handling (level/real-name/phone/daily-limit block reasons). - Toutiao
imagemode uploads images into the editor and publishes as image-rich article flow. - Wechat article mode now auto-detects editor input (
textarea/contenteditable) and writes body text.
Scripts
pnpm run lint
pnpm run typecheck
pnpm run build
pnpm run test
pnpm run smoke
pnpm run clean
pnpm run mcp
pnpm run prepackCLI
pnpm run cli runs dist/cli/index.js, so build first (pnpm run build) after code changes.
# list supported platforms
pnpm run cli list
# auth (interactive; legacy user-data mode)
pnpm run cli auth toutiao --user-data /tmp/toutiao-profile
# verify with configurable timeout/poll
pnpm run cli verify wechat \
--user-data /tmp/wechat-profile \
--timeout-ms 10000 \
--poll-interval-ms 300
# daemon-backed session auth start (recommended for automation)
pnpm run cli auth-start wechat --profile main
# get QR by session id
pnpm run cli auth-qr --session wechat-xxxx
# wait for session status transition
pnpm run cli auth-wait \
--session wechat-xxxx \
--timeout-ms 300000 \
--poll-interval-ms 1000 \
--until LOGGED_IN,FAILED,CANCELLED,TIMEOUT
# publish article
pnpm run cli publish toutiao \
--user-data /tmp/toutiao-profile \
--type article \
--title "Title" \
--body "Body"
# publish article by daemon profile (no --user-data)
pnpm run cli publish wechat \
--profile main \
--type article \
--title "Title" \
--body "Body"
# list known publish accounts / profiles
pnpm run cli publish-accounts --platform wechat --json
# set default publish account for a platform
pnpm run cli publish-set-default wechat --profile main --json
# batch publish to multiple profiles
pnpm run cli publish-batch wechat \
--profiles main,backup \
--type article \
--title "Batch Title" \
--body "Batch Body" \
--json
# dry-run (no browser launch)
pnpm run cli publish wechat --user-data /tmp/wechat-profile --dry-run
# structured JSON output (for scripts/CI)
pnpm run cli auth-start wechat --profile ci-main --dry-run --jsonCLI Usage Guide (中文)
CLI 有两种使用入口:
- npm 全局安装后直接用:
publish-bots-cli ... - 源码仓库内使用:
pnpm run cli ...(先pnpm run build)
两种运行路径:
- Legacy 模式(单命令 + 本地
user-data):auth/verify/publish --user-data - Daemon Profile 模式(推荐自动化):
auth-*会话命令 +publish/publish-batch/publish-accounts/publish-set-default,基于本地 daemon 持久化 profile
推荐流程(Session 模式首次登录):
- 启动登录会话:
publish-bots-cli auth-start wechat --profile main --json - 获取二维码:
publish-bots-cli auth-qr --session <session_id> --json - 轮询状态:
publish-bots-cli auth-wait --session <session_id> --until LOGGED_IN,FAILED,CANCELLED,TIMEOUT --timeout-ms 300000 --json - 登录完成后关闭会话:
publish-bots-cli auth-finish --session <session_id> --json
sohu 建议走手机号/验证码流程(非二维码优先):
- 启动会话:
publish-bots-cli auth-start sohu --profile main --json - 抓取登录页:
publish-bots-cli auth-capture-page --session <session_id> --json - 交互步骤:
auth-step switch_to_sms/fill_phone/send_code/fill_code/submit - 轮询与结束:
auth-wait ...+auth-finish
快速验证账号是否已登录(Legacy verify):
publish-bots-cli verify wechat --user-data /tmp/wechat-profile --timeout-ms 10000 --poll-interval-ms 300 --json
发布(Legacy publish):
publish-bots-cli publish toutiao --user-data /tmp/toutiao-profile --type article --title "Title" --body "Body"- 建议先加
--dry-run做参数检查
发布(Daemon Profile 模式,支持多账号):
- 列出平台可用发布账号:
publish-bots-cli publish-accounts --platform wechat --json - 设置默认账号:
publish-bots-cli publish-set-default wechat --profile main --json - 单账号发布(指定账号):
publish-bots-cli publish wechat --profile main --type article --title "Title" --body "Body" --json - 单账号发布(使用默认账号):
publish-bots-cli publish wechat --type article --title "Title" --body "Body" --json - 批量发布:
publish-bots-cli publish-batch wechat --profiles main,backup --type article --title "Batch" --body "Body" --json
JSON 输出(脚本/CI 推荐):
- 任意命令加
--json - 成功格式:
{ ok: true, command, result } - 失败格式:
{ ok: false, command, error: { code, message, details } }
daemon 管理:
- Daemon Profile 模式会自动拉起 daemon(Unix socket)
- 使用
publish-bots-cli daemon-stop关闭当前 profile-root 对应 daemon
Common options:
--user-data <path>required for legacyauth/verify/publish--session <id>session id forauth,verify, and session-style auth commands--timeout-ms <ms>+--poll-interval-ms <ms>forverify/auth-wait--until LOGGED_IN,FAILED,...forauth-wait--profile <name>for session auth and daemon publish commands--profiles <a,b,c>profile list forpublish-batch--profiles-root <path>override daemonBotsServiceprofile root--task <id>optional task id forpublish--task-start <id>optional start task id forpublish-batch--continue-on-error <true|false>batch publish error strategy (defaulttrue)--limit <n>result size limit forpublish-accounts--type article|image--media /a.png,/b.png--final-params '{"key":"value"}'--ack-timeout <ms>publish ACK timeout (default20000)--dry-run--jsonreturn structured machine-readable output
Session-style auth commands (daemon-backed):
auth-start <platform>auth-qr --session <id>auth-capture-page --session <id>auth-status --session <id>auth-wait --session <id>auth-step --session <id> --action <...> [--value <text>]auth-finish --session <id>auth-cancel --session <id>daemon-stop(stop local auth daemon process)
Daemon-backed publish commands:
publish <platform> [--profile <name>] [--task <id>] ...publish-batch <platform> [--profiles <a,b,c>] [--task-start <id>] ...publish-accounts [--platform <name>] [--limit <n>]publish-set-default <platform> --profile <name>
Worker Bridge
LegacyWorkerBridge accepts inbound worker messages and dispatches to runtime:
START_AUTHFOCUS_AUTHSTOP_AUTHRUN_PUBLISHACKDISPOSE
On failure, bridge emits BRIDGE_ERROR with structured payload:
codemessageinboundTypecontexttimestamp
Core files:
src/adapters/legacy-worker/LegacyWorkerRuntime.tssrc/adapters/legacy-worker/LegacyWorkerBridge.tssrc/platforms/registry.ts
Tests
- Unit tests:
tests/*.test.cjs - Smoke tests:
tests/*.smoke.cjs
Smoke tests use CLI --dry-run to validate command wiring without real account login.
MCP Server
Run MCP server over stdio:
bots-mcpIf not globally installed:
npx -y -p @heartbitai/publish-bots-mcp bots-mcpSource mode:
pnpm run build
pnpm run mcpConfigure MCP Client
Claude / OpenClaude-like JSON config (recommended via npx):
{
"mcpServers": {
"bots": {
"command": "npx",
"args": ["-y", "-p", "@heartbitai/publish-bots-mcp", "bots-mcp"],
"env": {
"BOTS_PROFILES_ROOT": "/absolute/path/bots-profiles"
}
}
}
}Codex desktop (~/.codex/config.toml) example:
[mcp_servers.bots]
type = "stdio"
command = "npx"
args = ["-y", "-p", "@heartbitai/publish-bots-mcp", "bots-mcp"]
[mcp_servers.bots.env]
BOTS_PROFILES_ROOT = "/absolute/path/bots-profiles"If your MCP host cannot resolve npx/node from PATH, use absolute binary paths.
Available tools:
bots_list_platformsbots_auth_listbots_account_checkbots_auth_startbots_auth_get_qrbots_auth_focusbots_auth_capture_pagebots_auth_stepbots_auth_refresh_qrbots_auth_statusbots_auth_waitbots_auth_finishbots_auth_cancelbots_publish_accounts_listbots_publish_accounts_set_defaultbots_publishbots_publish_batch
Available resources:
bots://platformsbots://auth/sessions/recentbots://mcp/policy
Available resource templates:
bots://auth/sessions/{platform}bots://auth/sessions/{platform}/{profile}
bots_account_check returns state=LOGGED_IN|NEED_QR|FAILED and can include QR snapshot (qr) when login is required.
Tool usage notes:
bots_account_checkis a quick check helper (start -> wait -> finish) and is best for "already logged in?" checks.- For first-time login with human interaction, prefer session-style auth tools:
bots_auth_startbots_auth_get_qr/bots_auth_refresh_qrbots_auth_focus(bring auth window to front)bots_auth_capture_page(full-page snapshot when QR is not the right artifact)bots_auth_step(switch_to_sms|fill_phone|send_code|fill_code|submit)bots_auth_status/bots_auth_waitbots_auth_finish(orbots_auth_cancel)
Agent Call Templates
Health check (MCP connectivity):
- call
bots_list_platforms - call
bots_auth_list(optional) - call MCP
resources/listand confirmbots://platformsexists (optional) - call
bots_publishwithdry_run=true(optional)
First-time login (human scans QR):
bots_auth_startwithplatform+profilebots_auth_get_qrwith returnedsession_id- show
qr.imagePathimage to user for scanning - poll
bots_auth_status(or usebots_auth_wait) - if QR expired, call
bots_auth_refresh_qrand re-show QR - when status reaches
LOGGED_IN, callbots_auth_finish - if status becomes
FAILED/TIMEOUT/CANCELLED, callbots_auth_cancel
Example first-time login tool arguments:
{
"platform": "wechat",
"profile": "real-main"
}{
"session_id": "wechat-xxxx",
"include_base64": false
}{
"session_id": "wechat-xxxx",
"timeout_ms": 300000,
"poll_interval_ms": 1500,
"until": ["LOGGED_IN", "FAILED", "CANCELLED", "TIMEOUT"]
}Publish with existing profile (already logged in):
- call
bots_publishwithplatform+profile+ content - recommend
dry_run=truefirst, then real publish
Multiple accounts / default account / batch publish:
- call
bots_publish_accounts_listto view known profiles for a platform - call
bots_publish_accounts_set_defaultto set default profile - call
bots_publishwithoutprofileto use default profile - call
bots_publish_batchwithprofilesarray for bulk publish
Example publish arguments:
{
"platform": "wechat",
"profile": "real-main",
"type": "article",
"title": "Demo Title",
"body": "Demo Body",
"media": ["/Users/troy/Desktop/projects/bots/auto-publish-bot/cover.jpg"]
}Dry-run example:
{
"platform": "wechat",
"profile": "real-main",
"dry_run": true
}Batch publish example:
{
"platform": "wechat",
"profiles": ["real-main", "backup-account"],
"type": "article",
"title": "Batch Demo Title",
"body": "Batch Demo Body",
"continue_on_error": true
}Error contract (tools/call result with isError: true):
{
"isError": true,
"content": [{ "type": "text", "text": "[ERROR_CODE] readable message" }],
"structuredContent": {
"ok": false,
"error": {
"code": "MCP_INVALID_ARGUMENT | MCP_TOOL_UNSUPPORTED | MCP_TOOL_FORBIDDEN | MCP_INTERNAL_ERROR | BOTS_*",
"message": "readable message",
"tool": "bots_auth_start",
"details": {}
}
}
}MCP permission policy (env vars, optional):
BOTS_MCP_POLICY=full|read_only|auth_only|publish_only|none(defaultfull)BOTS_MCP_ALLOW_TOOLS=bots_list_platforms,bots_auth_list(allowlist, optional)BOTS_MCP_DENY_TOOLS=bots_publish(denylist, optional)BOTS_PROFILES_ROOT=/absolute/path(override MCP profile storage root)
Example:
# deny publish in this process
export BOTS_MCP_POLICY=read_only
bots-mcpAuth QR screenshots are stored under:
resources/auth-qr/
Default profile root used by BotsService:
- when
BOTS_PROFILES_ROOTis set:<BOTS_PROFILES_ROOT>/<platform>/<profile> - when
BOTS_PROFILES_ROOTis not set:<server_package_root>/.profiles/<platform>/<profile> - session index:
<profiles_root>/.service-state/auth-sessions.json(persisted auth session index)- Writes are debounced and atomically replaced via temp-file + rename.
MCP server startup note:
- MCP resolves default profile root from server package location (
<server_package_root>/.profiles) instead of current working directory, so it can start correctly even when host cwd is/. - for npm global installs, always set
BOTS_PROFILES_ROOTto a writable directory.
Profile locking:
- Same profile path is single-owner at a time (auth/publish are mutually exclusive).
- Concurrent conflict returns
BOTS_PROFILE_BUSY.
Common troubleshooting:
- "Tool not found in shell"
- MCP tools (e.g.
bots_list_platforms) are not shell commands; call them via MCPtools/call.
- MCP tools (e.g.
BOTS_PROFILE_BUSY- another auth/publish flow is holding the same profile path; finish/cancel existing session first.
- no QR image in response
- call
bots_auth_get_qragain afterbots_auth_start, or usebots_auth_refresh_qrwhen QR changes.
- call
Publish To npm (Maintainer)
npm login
npm publish --access publicNotes:
prepublishOnlywill runpnpm run clean && pnpm run build.- validate package files before publishing:
npm pack --dry-run.
TUI Release Script (latest / beta)
This repo includes an interactive terminal release helper:
pnpm run release:tuiYou can also force channel selection:
pnpm run release:latest
pnpm run release:betaWhat it does:
- checks
npm whoamiand git working tree status - interactive choose version strategy (
patch/minor/majororpre*) - optional input OTP
- optional pre-publish checks (
lint + typecheck + build) - runs
npm version --no-git-tag-version - publishes:
- stable:
npm publish --access public(latest) - beta:
npm publish --access public --tag beta
- stable:
