nbdpsy-mcp

nbdpsy-mcp

MCP server for managing Xiaohongshu (Little Red Book) account matrix operations, including account management, cookie sharing, and note publishing via MCP tools.

Category
访问服务器

README

nbdpsy-api

小红书矩阵账号运营的纯 REST API 后台服务。远程 AI agent 通过 HTTP 调用端点完成 账号托管、cookie 共享、笔记发布;人不直接用 UI,登录只交给一个 chrome 插件。


架构总览

一句话:单进程 FastAPI(REST)服务,apikey 鉴权,把发布/账号/cookie 做成 REST 端点, 登录交给 chrome 插件,全服务只有一套 sync Camoufox 浏览器栈。

远程 agent ──(HTTP, Bearer apikey)───────────────────────▶  /api/*
chrome 插件 ──(HTTP, Bearer apikey)──────────────────────▶  /api/cookies/import
                                        │
                              单进程 FastAPI
                        ├─ apikey 中间件(RBAC 上下文)
                        ├─ REST 端点面(账号/cookie/发布/插件/管理员/自描述)
                        ├─ 发布队列(asyncio.Queue + per-account 锁 + to_thread)
                        │     └─▶ sync Camoufox(Xvfb :99)── xiaohongshu.com
                        └─ 可选 cookie 周期巡检(COOKIE_CHECK_INTERVAL>0 才起)

设计取舍:

  • 去 celery / redis:发布调度的真相源本就是 DB 状态机,单进程用 asyncio 队列 + 内存 per-account 锁等价替代,甩掉两个重依赖。发布状态机 pending → publishing → published | failed,失败按 PUBLISH_RETRY_SCHEDULE 退避重试,进程重启自动恢复 僵死 job。
  • 单套 sync 浏览器栈:只保留发布 + cookie 检测用的 sync Camoufox,采集/AI 栈整包不搬。
  • apikey + 二元 RBAC:每个运营者(operator)一把 apikey;管理员(admin)全见, 普通 operator 只能操作被 grant_account_access 授权的号。cookie 每个小红书账号唯一 一行(共享 cookie),不按 operator 分裂。
  • 登录外置:服务端不做登录,chrome 插件把用户已登录的 cookie 推到 /cookies/import

目录结构

app/
  server.py            # create_app():FastAPI 装配 + lifespan
  core/                # config(Settings) / db(async SQLAlchemy) / security(Fernet + apikey hash)
  auth/                # apikey 中间件 / ContextVar 运营者上下文 / RBAC guards / bootstrap root
  models/              # operator / operator_account_access / xhs_account / publish_job
  services/            # operator_service / account_service / cookie_service(纯业务层)
  http/                # REST 端点:system / manifest / accounts / admin / cookies / publish / extension / downloads
  browser/             # sync_client(Camoufox 发布/检测) / profile_guard / fingerprint / cookie_checker
  publish/             # queue(asyncio 队列 + 锁) / scheduler(状态机 + 恢复) / runtime(调度器单例)
alembic/               # DB 迁移
chrome-extension/      # Manifest V3 插件(推 cookie)
scripts/               # xvfb.sh / run.sh / pack_extension.sh
tests/                 # 单测 + tests/e2e(冒烟,含 slow)

启动步骤

前置:Python 3.12、Xvfbzip 已装(which Xvfb zip)。

# 1. venv(依赖只装在项目 venv 内,不要用系统 python)
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt

# 2. 配置:复制样例并按需改(生产必须换 SECRET_KEY / 设 ROOT_ADMIN_APIKEY)
cp .env.example .env

# 3. 一键起(迁移 DB → 打包插件 → 起 uvicorn;内部会先确保 Xvfb)
bash scripts/run.sh

scripts/run.sh 依次做:xvfb.sh start(确保虚拟显示)→ alembic upgrade head(迁移) → pack_extension.sh(生成 DATA_DIR/extension.zip)→ uvicorn app.server:create_app --factory --host $API_HOST --port $API_PORT。全程用 .venv/bin/ 下的解释器/工具。

也可手动分步:

bash scripts/xvfb.sh start                # 启 Xvfb :99(start/stop/status,幂等)
.venv/bin/alembic upgrade head            # DB 迁移
bash scripts/pack_extension.sh            # 打包插件 zip
.venv/bin/uvicorn app.server:create_app --factory --host 0.0.0.0 --port 8848

服务起来后:健康探活 GET /healthz(免鉴权),自描述接口 GET /api/manifest(需 apikey)。


apikey 与首个管理员

  • 首个 root 管理员由 lifespan 的 bootstrap_admin 引导:
    • 配了 ROOT_ADMIN_APIKEY:用它建/对齐 root(幂等,重启同 key 不重复建)。
    • 没配:仅当库里还没 root 时,自动生成一把并在日志里打印一次明文(务必立即保存)。
  • 之后用 root 的 apikey 调 POST /api/operators 建其它运营者,每次返回一次性明文 apikey (库内只存 SHA256 hash,无法再次读取;忘了用 POST /api/operators/{id}/rotate-apikey 重置)。
  • 远程 agent / 插件带 apikey 的方式:HTTP 头 Authorization: Bearer <apikey> (或 X-API-Key: <apikey>)。

创建更多管理员

用 root(或任一 admin)的 apikey 调管理端点:

  • 新建 admin:POST /api/operators {"name":"小李","role":"admin"} → 返回一次性明文 apikey。
  • 把已有运营者提权:PATCH /api/operators/{id} {"role":"admin"};停用:{"enabled":false}
  • 分配小红书账号使用权:POST /api/operators/{id}/grants {"xhs_account_id":...}; 回收:DELETE /api/operators/{id}/grants/{xhs_account_id}
  • 只有 admin 能调这些;普通 operator 调会被拒(403)。

查看账号 / 运营者状态

本服务无前端,查看都通过带 admin apikey 的请求调 REST 端点:

  • 所有小红书账号 + 登录状态:GET /api/accounts(admin 全见)→ 每个含 status / cookie_status(valid/invalid/captcha/unknown)/ last_check_at / 昵称等(不含 cookie)。
  • 刷新某号实时活性:POST /api/accounts/{id}/cookie-checks 异步——返回 {check_id} 后用 GET /api/cookie-checks/{check_id} 轮询到 valid/invalid/captcha/error,把三态写回。 想自动周期巡检:设 COOKIE_CHECK_INTERVAL(秒,>0 才起,默认 0)。
  • 发布任务状态:GET /api/publish-jobs?account_id=&status=(均可选)。
  • 所有运营者:GET /api/operators → id/name/role/enabled(不含 apikey);某人授权了哪些号: GET /api/operators/{id}/grants

不经 agent 快速瞄一眼(直接查库):

.venv/bin/python -c "import sqlite3;[print(r) for r in sqlite3.connect('data/nbdpsy.db').execute('select id,name,nickname,status,cookie_status,last_check_at from xhs_accounts')]"

插件配置

  1. 带 apikey 调 GET /api/extension 拿到 download_url(指向 /downloads/extension.zip, 免鉴权可直接下)、版本与安装步骤。
  2. 下载解压到固定目录 → chrome://extensions 开「开发者模式」→「加载已解压的扩展程序」。
  3. 在插件弹窗填 serverUrl(本服务地址,即 PUBLIC_BASE_URL)与 apikey(连接本服务的 同一把 key)。
  4. 用户在 chrome 里登录好小红书后,插件把 cookie 推到 POST /api/cookies/import,服务端 sameSite 规范化 + Fernet 加密后 upsert 到该账号唯一一行。

API 端点清单

共 24 个 REST 端点,分 6 组。除白名单(/healthz/downloads/*)外均需 apikey, 且按 RBAC 收窄到 caller 有权的账号(admin 全见)。完整契约(含 params/returns/errors/notes) 以 GET /api/manifest 为准,下表只给概览。

system(2)

方法 + 路径 说明
GET /api/whoami 回显当前运营者身份(诊断)
GET /api/manifest 服务自描述:全部端点契约 + 工作流叙事 + 错误契约 + caller 身份

admin(8,仅管理员)

方法 + 路径 说明
POST /api/operators 建运营者,返一次性明文 apikey
GET /api/operators 列全部运营者(不含 apikey)
PATCH /api/operators/{operator_id} 局部更新 role/enabled/name(留空不改)
DELETE /api/operators/{operator_id} 删运营者并级联清授权
POST /api/operators/{operator_id}/rotate-apikey 重置 apikey,旧 key 立即失效
POST /api/operators/{operator_id}/grants 授权某号(幂等)
DELETE /api/operators/{operator_id}/grants/{xhs_account_id} 回收授权(幂等)
GET /api/operators/{operator_id}/grants 列某运营者已授权的号

accounts(6,RBAC 收窄)

方法 + 路径 说明
GET /api/accounts 列可见账号(不含 cookie)
GET /api/accounts/{account_id} 查单个账号元信息
PATCH /api/accounts/{account_id} 改内部展示名(安全字段)
DELETE /api/accounts/{account_id} 删账号并清其授权
GET /api/accounts/{account_id}/cookies 解密回读该号 cookie(需 access)
GET /api/login/poll 轮询登录完成信号(自 since 起有无新号/新登录)

cookies(3)

方法 + 路径 说明
POST /api/cookies/import 灌 cookie,upsert 唯一号
POST /api/accounts/{account_id}/cookie-checks 异步起浏览器巡检,立即返 check_id
GET /api/cookie-checks/{check_id} 轮询巡检结果

publish(4,RBAC 收窄)

方法 + 路径 说明
POST /api/publish-jobs 建发布任务并入队
GET /api/publish-jobs/{job_id} 查任务状态
GET /api/publish-jobs 列任务(按可见账号过滤,可加 ?account_id=&status=)
POST /api/publish-jobs/{job_id}/cancel 取消(仅 pending 可取消)

POST /api/publish-jobsimages 每项为 http(s) URL / data URI / {b64, ext};不传 schedule_time 立即入队,传 ISO8601 字符串则定时发布(调度器扫到期后自取)。图片在发布 runner 里再物料化成本地文件,端点本身不碰浏览器。

extension(1)

方法 + 路径 说明
GET /api/extension 插件下载地址 + 版本 + 安装引导 + /api/login/poll 起点时间

接入(三步)

远程 agent 接入本服务不需要装任何客户端 / 插件 / SDK——公网地址 + 一把 operator apikey 即可,直接用 HTTP 调 REST 端点。本部署的公网地址为 https://mcp.nbdpsy.com(经反向代理 回源 localhost:8848),下文示例即用它;你自建部署时替换成自己的域名。

  1. 拿 apikey:向管理员索取一把 operator apikey(见「apikey 与首个管理员」)。
  2. 确认可达:
    curl https://mcp.nbdpsy.com/healthz          # 应返回 {"ok":true}
    
  3. 读 manifest 自解释:
    curl -H "Authorization: Bearer <你的-apikey>" https://mcp.nbdpsy.com/api/manifest
    
    返回体一次性给全部端点契约(method/path/params/returns/errors/notes)、工作流叙事 (workflows)、约束(constraints)、错误契约(error_contract)与你的身份(caller)。 agent 读完这一个接口即可自解释地干活,不需要额外文档。

apikey 是密钥:别写进公开仓库 / 截图 / 聊天分享。泄露了让管理员用 POST /api/operators/{id}/rotate-apikey 轮换。

要点:

  • 除白名单(/healthz/downloads/*)外所有调用都要带 operator 的 apikey (Authorization: Bearer <apikey>X-API-Key: <apikey>);访问不属于自己的账号 403。
  • 发布是异步的:POST /api/publish-jobs 只返回 {job_id},结果靠 GET /api/publish-jobs/{job_id} 轮询到 published/failed。
  • 登录没有 REST 端点:小红书登录靠人 + chrome 插件在真实浏览器完成,登录完成判据是 GET /api/login/poll(细节见 manifest 的 workflows)。
  • cookie 是共享的:多个有 access 的 operator 共用同一份账号 cookie,谁更新写同一行。

部署

  • 反向代理PUBLIC_BASE_URL(对外域名)代理到本机 API_PORT(FastAPI 监听)。 REST 端点、插件推 cookie、插件包下载走同一入口。
  • 用 systemd 托管 scripts/run.sh(exec uvicorn 让信号/退出码直通)。
  • Xvfb 由 scripts/run.sh 内的 xvfb.sh start 确保;也可单独用 systemd 常驻。
  • .env / app/core/config.py 后必须重启进程——pydantic BaseSettings 在进程 启动时锁定字段集合,运行中改配置不生效。
  • 可选后台 cookie 巡检:COOKIE_CHECK_INTERVAL 设为 >0(秒)时,lifespan 起一个轻量 协程周期性对 cookie_status=valid 的号逐个跑登录检测并写回状态(号间隔 ≥5s 防频控); 默认 0 关闭。

坑(务必先读)

  • SECRET_KEY 不能换:cookie 用它派生的 Fernet key 加密落库。换了 key,存量 login_cookies 全部解密失败(且 decrypt_cookies 静默返回空串,不报错),等于所有号 掉登录。迁移/换机原样沿用旧 SECRET_KEY
  • Xvfb :99 必须先起:sync Camoufox 需要虚拟显示;XVFB_DISPLAY 改了要与 xvfb.sh 一致。NVIDIA + Xvfb 环境下发布客户端已强制 MOZ_HEADLESS / LIBGL_ALWAYS_SOFTWARE 等,避免 glxtest 卡启动。
  • Camoufox profile 锁:Firefox 系单写锁,同一号并发启动必挂 "Firefox is already running"。服务用 per-account 内存锁串行同号操作;若进程异常残留锁,profile_guard 会清锁 + 精确杀孤儿(argv 精确匹配,account_2 不误杀 account_20)。
  • 发布走服务器 IP:cookie 虽在用户住宅浏览器诞生,发布操作却发生在服务器 IP + 固定 指纹上。个别对 IP 敏感的号可能触发风控(发布中判 failed,可加冷却)。IP 不一致是既有 现实,非本服务新增。
  • 改代码 / prompt 后要重启:uvicorn 进程启动时加载模块,改 .py 不 restart 不生效。

测试

# 全量单测(不含需真号的 slow/e2e,CI 用这条)
.venv/bin/pytest -m "not slow" -v

# e2e 冒烟:RBAC 链默认跑(纯 DB/REST 调用);发布链需真 cookie,缺则自动 skip
.venv/bin/pytest tests/e2e -v
# 手动跑发布链(需 Xvfb + 真 cookie):
NBDPSY_E2E_COOKIES='[{"name":"...","value":"..."}]' \
  .venv/bin/pytest tests/e2e/test_smoke.py -m slow -v

测试全程用隔离临时 sqlite(不碰生产库),slow 标记的用例默认不在 CI 跑。

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选