微信公众号(订阅号 / 服务号)服务端 API 的 FastAPI 封装,同时通过 MCP 对 AI Agent 暴露。
Token 自动缓存、鉴权内置、一条 docker compose up 即可部署。
- 37 个 HTTP 接口,覆盖发布端到端:基础接口 6 + 发布能力 5 + 草稿管理 8 + 素材管理 9 + 基础消息 10
- Access Token 自动管理:asyncio 锁去重 + 文件持久化 + 40001/42001 自动刷新
- MCP 暴露(故意收窄):只有 草稿 + 素材 + healthz 共 18 个 tool 走 MCP;发布、群发、订阅消息等保留为 HTTP-only,避免 Agent 误触发。见
main.py里的MCP_TOOLS白名单 - API Key 鉴权:保护
/wechat/*与/mcp,可关 - 63 个测试 全绿(httpx + respx + pytest-asyncio)
需要:python >= 3.13 或 Docker。
cp .env.example .env # 填 WECHAT_APPID / WECHAT_APPSECRET
uv sync
uv run uvicorn main:app --reload访问 http://127.0.0.1:8000/docs 查看所有接口。
Compose 直接消费 Docker Hub 上已发布的 multi-arch 镜像 igorwang/wechat-oap-api(linux/amd64 + linux/arm64),不做本地构建:
cp .env.example .env # 填 WECHAT_APPID / WECHAT_APPSECRET / API_KEY
docker compose pull # 拉最新镜像(本机架构自动匹配)
docker compose up -d
docker compose logs -f api- 端口默认
:8000,用.env的PORT可改 - Token 缓存挂载到
token-cachevolume,容器重启不会重新申请 - Healthcheck 每 30s 打
/healthz,docker compose ps能看到healthy状态 - 固定版本:
IMAGE_TAG=0.1.0 docker compose up -d
docker login -u igorwang # 需要写权限的 Docker Hub 账号
scripts/docker-push.sh # 读 pyproject.toml 的 version,打 :latest + :$version
scripts/docker-push.sh v0.2.0 # 或手动指定 tag脚本用 docker buildx --platform linux/amd64,linux/arm64 一次构建两架构并直接 push。
| 变量 | 必填 | 默认 | 说明 |
|---|---|---|---|
WECHAT_APPID |
✓ | — | 公众号 AppID |
WECHAT_APPSECRET |
✓ | — | 公众号 AppSecret |
WECHAT_API_BASE |
https://api.weixin.qq.com |
||
WECHAT_TOKEN_CACHE_PATH |
.wechat_token.json |
置空禁用磁盘缓存 | |
API_KEY |
"" |
保护 /wechat/* 与 /mcp,置空 = 关闭鉴权(本地开发) |
|
API_KEY_HEADER |
X-API-Key |
鉴权 header 名 | |
PORT |
8000 |
compose 对外映射端口 |
启用鉴权只需在 .env 设 API_KEY=some-long-random-string,随后所有 /wechat/* 和 /mcp 请求必须带 header:
X-API-Key: some-long-random-string
放行路径(不需要 key):/healthz, /docs, /redoc, /openapi.json。
核心思路:API Key 配在 MCP 客户端侧一次,之后任何 skill / prompt / subagent 调用工具都不用感知 key。这样:
- Skill 代码里不会出现 secret
- 同一机器上多个 agent 共享同一套 MCP 配置
- 轮换 key 只改一处
本仓库已附带 .mcp.json:
{
"mcpServers": {
"wechat-oap": {
"type": "http",
"url": "http://localhost:8000/mcp",
"headers": {
"X-API-Key": "${WECHAT_OAP_API_KEY}"
}
}
}
}使用步骤:
- 本地/服务器上把服务跑起来(
docker compose up -d) - 在 shell 里 export key:
export WECHAT_OAP_API_KEY=...(建议写进~/.zshrc或 direnv) cd进本仓库,Claude Code 首次会提示"approve project MCP",同意即可claude mcp list能看到wechat-oap
优势:
.mcp.json可安全 commit(只引用 env 变量,不含真 key)- 团队成员 clone 仓库后只需 export 自己的 key 即可
- URL 要改(部署到生产),直接改
.mcp.json并 commit
如果多个仓库都想调这套 MCP,写到用户级配置:
{
"mcpServers": {
"wechat-oap": {
"type": "http",
"url": "https://your-production-host/mcp",
"headers": {
"X-API-Key": "real-key-here"
}
}
}
}claude mcp add \
--transport http \
--header "X-API-Key: your-api-key" \
wechat-oap http://localhost:8000/mcp进入 Claude Code 后问一句:
用 wechat-oap 查一下当前 access_token
Claude 会调用 MCP 工具 get_access_token。如果你配了 key,请求会自动带 X-API-Key 头;没配 key 或配错 → 401。
本仓库在 skills/wechat-api/ 下内置了一个 Skill,指导 Claude 通过 wechat-oap MCP 起草公众号图文、管理素材(scope 仅限草稿,不含发布/群发)。
项目级安装(只在当前项目生效):
mkdir -p .claude/skills
npx -y degit igorwang/wechat-oap-api/skills/wechat-api .claude/skills/wechat-api全局安装(所有项目都能用):
npx -y degit igorwang/wechat-oap-api/skills/wechat-api ~/.claude/skills/wechat-api安装完成后,在 Claude Code 里输入类似 "帮我起草一篇公众号图文" / "上传一张封面图" 就会自动触发;也可以 /wechat-api 显式调用。
前置:先完成上一节的 MCP 接入(方式 A/B/C 任一),否则 Skill 找不到
draft_add、material_add等工具。
Skill 里不用写 key。直接调 MCP 工具名即可:
---
name: 微信发布
description: 从草稿 media_id 发布图文到公众号
---
1. 调 `freepublish_submit`,传入用户给的 `media_id`
2. 轮询 `freepublish_get` 直到 `publish_status` 终态
3. 把结果返回给用户MCP 客户端在调用 freepublish_submit 时会自动带上 X-API-Key,skill 本体见不到也不需要传递。
| 分组 | 路由前缀 | operation_id 前缀 | 数量 |
|---|---|---|---|
| 基础接口 | /wechat/{token,stable-token,callback/check,api-domain-ip,callback-ip,clear-quota} |
— | 6 |
| 发布能力 | /wechat/freepublish/* |
freepublish_* |
5 |
| 草稿管理 | /wechat/draft/* |
draft_* |
8 |
| 素材管理 | /wechat/material/{permanent,temporary}/* |
material_* |
9 |
| 基础消息 | /wechat/message/{mass,subscribe,autoreply}/* |
message_* |
10 |
完整 schema 见 http://localhost:8000/docs 。
uv sync # 含 dev group
uv run pytest # 63 tests
uv run pytest -v tests/test_auth.py # 单文件结构:
app/
├── config.py # pydantic-settings, 读 .env
├── wechat.py # WeChatClient: token 缓存 + call_json / call_multipart
├── auth.py # X-API-Key 中间件
└── routers/
├── freepublish.py
├── draft.py
├── material.py
└── message.py
main.py # FastAPI app + FastApiMCP 挂载
tests/ # respx mock,不打真微信
MIT