WhatsApp MCP服务

一个基于Streamable HTTP传输的WhatsApp MCP服务器,使用Baileys实现WhatsApp连接,提供Web管理界面和双向媒体流(上传+下载)功能。

  • by loglux
  • TypeScript
  • 本地部署
  • 5 星标
  • 更新于
在 GitHub 查看 loglux/whatsapp-mcp-stream

使用说明

WhatsApp MCP流

围绕以下内容构建的WhatsApp MCP服务器 流式HTTP 运输,使用 百利甜酒 用于WhatsApp连接,具有web管理UI和双向媒体流(上传+下载)。

要点:

  • 传输:可流式HTTP /mcp
  • 发动机:Baileys
  • 管理员界面:二维码、状态、注销、运行时设置、聊天历史查看器
  • 媒体:上传端点+ /media 主机+MCP下载工具

快速入门(Docker)

# build and run

docker compose build

docker compose up -d

服务器将在以下位置可用:

  • 管理用户界面: http://localhost:3003/admin
  • MCP端点: http://localhost:3003/mcp
  • 媒体文件: http://localhost:3003/media/<filename>

主机上的DNS --iptables=false

在某些NAS/强化主机上(例如Synology dockerd --iptables=false)Docker的嵌入式DNS代理(127.0.0.11)没有iptables DNAT规则,并拒绝容器内的连接。

修复:复制 resolv.conf.example 到 resolv.conf 并添加音量覆盖:

cp resolv.conf.example resolv.conf

然后添加到本地 docker-compose.override.yml (未承诺):

services:
  mcp-whatsapp:
    volumes:
      - ./resolv.conf:/etc/resolv.conf:ro

docker compose up 自动拾取覆盖。

运行时设置

可以在管理UI中编辑设置,并将其持久化到 SETTINGS_PATH (默认为 MEDIA_DIR/settings.json).

管理用户界面

具有运行时设置、QR链接、聊天历史查看器、导出和状态的管理控制台。

支持的设置:

  • media_public_base_url
  • upload_max_mb
  • upload_enabled
  • max_files_per_upload
  • require_upload_token
  • upload_token
  • auto_download_media
  • auto_download_max_mb

认证

尚未实现内置身份验证。在生产环境中,使用强制认证的网关。这个项目进展顺利 authmcp-gateway:

https://github.com/loglux/authmcp-gateway

媒体上传API

Base64 JSON格式:

curl -X POST http://localhost:3003/api/upload \
  -H "Content-Type: application/json" \
  -d {filename:photo.jpg,mime_type:image/jpeg,data:<base64>}

多部分(建议用于大文件):

curl -X POST http://localhost:3003/api/upload-multipart \
  -F "file=@/path/to/file.jpg"

两人都回来了 url 以及(如果已配置) publicUrl.

通过send_media发送本地文件

这 ./files/ 项目根目录中的目录被绑定挂载到容器中 /app/files.将任何文件放到那里并立即引用它——不需要重新启动容器:

# On host:
cp report.pdf /path/to/whatsapp-mcp-stream/files/

# In send_media:
media_path: /app/files/report.pdf

对于URL源,请传递 media_url 直接到 send_media 或 stage_media --服务器下载文件本身而不使用base64。

上传身份验证(可选)

如果 require_upload_token=true,使用以下任一方式提供令牌:

  • x-upload-token: <token>
  • Authorization: Bearer <token>

MCP传输

服务器在以下位置公开Streamable HTTP /mcp.

典型流程:

  1. POST /mcp 使用JSON-RPC initialize
  2. 使用返回的 mcp-session-id 后续请求的标头
  3. POST /mcp 用于工具调用

注意:客户必须发送 Accept: application/json, text/event-stream 上 initialize.

冒烟测试

MCP工具的快速回归烟雾:

npm run smoke:mcp

可选自定义目标:

MCP_BASE_URL=http://localhost:3003 npm run smoke:mcp

MCP工具

认证

工具 说明
get_qr_code 获取最新的WhatsApp二维码作为图像进行身份验证。
check_auth_status 检查WhatsApp客户端是否已通过身份验证并准备就绪。
logout 退出WhatsApp并清除当前会话。

联系人

工具 说明
search_contacts 按姓名或电话号码搜索联系人。
resolve_contact 按姓名或电话号码解析联系人(最佳匹配)。
get_contact_by_id 通过JID获取联系方式。
get_profile_pic 获取JID的个人资料图片URL。
get_group_info 按组JID获取组元数据和参与者。

聊天

工具 说明
list_chats 列出带有元数据和可选最后一条消息的聊天记录。
get_chat_by_id 通过JID获取聊天元数据。
list_groups 仅列出群聊。
get_direct_chat_by_contact_number 通过电话号码解决直接聊天JID。
get_chat_by_contact 按姓名或电话号码解析联系人,并返回聊天元数据。
analyze_group_overlaps 查找出现在多个组中的成员。
find_members_without_direct_chat 查找没有直接聊天的群成员。
find_members_not_in_contacts 查找联系人中缺少的组成员。
run_group_audit 将组合组审核作为一项常规操作运行。

消息

工具 说明
list_messages 从特定聊天中获取消息。
search_messages 按文本搜索消息(可选范围为聊天)。
get_message_by_id 按ID获取特定消息(jid:id).
get_message_context 获取特定消息的最新消息。
get_last_interaction 获取JID的最新消息。
send_message 向个人或组发送短信。支持可选 idempotency_key.

媒体

工具 说明
send_media 发送媒体(图像/视频/文档/音频)。接受 media_path, media_url,或 media_content (base64)。支持可选 idempotency_key.
stage_media 将文件保存到服务器的媒体目录并返回其本地路径。使用返回的 saved_path 在 send_media (media_path)--当源是URL时避免base64(服务器直接下载),或者允许将同一文件发送给多个收件人而无需重新上传。
download_media 从邮件中下载媒体。

实用

工具 说明
ping 健康检查工具。

恢复说明

此服务包含针对Baileys/WhatsApp会话状态损坏的有意恢复解决方法。

为什么存在:

  • 在生产环境中,我们观察到容器仍然存活,MCP仍然应答,但WhatsApp会话功能中断。
  • 最常见的指标是Baileys的错误,如 failed to find key ... to decode mutation 和 failed to sync state from version.
  • 在这种状态下,手动重启容器通常会恢复服务。

当前行为:

  • 根据应用程序状态损坏信号,该服务首先尝试通过以下方式进行软恢复 forceResync().
  • 如果同一类故障在一个时间窗口内重复出现,则升级为内部WhatsApp客户端重启。
  • 在断开连接时,例如 Connection Terminated,该服务会安排一个断开连接监视器,如果套接字没有返回,则升级为内部重启 open 迟早
  • 重新连接生命周期防止嵌套锁死锁,因此断开连接恢复可以在不需要手动重新启动容器的情况下完成。
  • 最近的生产观察显示插座反复断开(428 Connection Terminated, 503 Stream Errored)正在自动恢复到 open.
  • 一个专用 /healthz 端点报告 503 只有当服务真正卡在允许的恢复窗口之外时。
  • Docker健康检查使用 /healthz,因此只有在进程内恢复有机会工作后,容器才会重新启动。

这些恢复机制减少了运营商的干预,提高了对常见WhatsApp/Baileys会话故障的恢复能力。

许可证

麻省理工学院

坚持

聊天和消息被持久化到会话卷中存储的本地SQLite数据库中。

环境变量:

变量 默认值 描述
DB_PATH <SESSION_DIR>/store.sqlite 用于聊天/消息持久化的SQLite数据库路径。
WA_EVENT_LOG 0 启用详细的WhatsApp事件日志。
WA_EVENT_STREAM 0 将原始Baileys事件流写入文件进行深度调试。
WA_EVENT_STREAM_PATH /app/logs/wa-events.log 事件流日志的文件路径。
WA_RESYNC_RECONNECT 1 强制重新同步后启用重新连接安全网。
WA_RESYNC_RECONNECT_DELAY_MS 15000 强制重新同步后重新连接前的延迟(ms)。
WA_SYNC_RECOVERY_COOLDOWN_MS 300000 自动应用程序状态恢复之间的最小延迟。
WA_SYNC_RECOVERY_WINDOW_MS 900000 用于计算重复应用程序状态损坏失败的时间窗口。
WA_SYNC_SOFT_RECOVERY_LIMIT 2 升级到内部重启之前的软恢复次数。
WA_READINESS_GRACE_MS 180000 恢复/断开连接前的宽限期 /healthz 变得不健康。
WA_DISCONNECT_RECOVERY_DELAY_MS 30000 插座关闭后等待多长时间,断开连接监视器才会强制重新连接/重新启动。
WA_DISCONNECT_RECOVERY_RESTART_CODES 428 逗号分隔的断开状态代码应直接升级到内部重启监视器。
WA_SEND_DEDUP_WINDOW_MS 45000 抑制完全重复 send_message 在此窗口内向同一JID发出请求。
WA_IDEMPOTENCY_TTL_MS 86400000 完成多长时间 send_message 幂等性记录保留在SQLite中,以便安全重试。
WA_MESSAGE_INDEX_MAX 20000 消息索引的最大内存条目数(jid:id ->原始消息)。
WA_MESSAGE_KEY_INDEX_MAX 20000 消息键索引的最大内存条目数(id ->原始消息)。
WA_INITIALIZE_TIMEOUT_MS 120000 让WhatsApp客户端在截止日期前进行初始化;着手 0 禁用。超时,因此恢复可以重试而不是挂起。
WA_AUTO_DOWNLOAD_CONCURRENCY 3 最大并行自动下载。自动下载通过进程内有界队列运行,因此入站媒体的突发不会使I/O饱和
WA_AUTO_DOWNLOAD_QUEUE_MAX 200 排队的自动下载作业最多。多余的FIFO(最旧的先)将被丢弃,并显示警告日志;最近的消息保持优先级。
MCP_HTTP_ENABLE_JSON_RESPONSE 1 默认情况下,对可流式HTTP POST请求使用直接JSON响应。设置为 0 强制使用较旧的SSE风格POST响应处理。

其他运输诊断:

  • /mcp POST请求现在将请求生命周期事件记录在 logs/mcp-whatsapp.log
  • 这包括请求输入、传输调度、传输调度和传输调度, transport.handleRequest 完成和HTTP finish / close
  • 使用这些日志来确定响应离开之前是否发生了延迟 whatsapp-mcp-stream 或者之后在网关/客户端

聊天历史记录API

通过以下方式浏览存储的聊天记录和消息:

GET /api/chats?limit=50&offset=0&q=<search> --分页聊天列表,可选择按姓名过滤。

GET /api/chats/:jid/messages?limit=50&offset=0 --聊天消息分页(最新消息优先)。

这两个端点都由 聊天 管理UI中的选项卡。

出口

通过以下方式导出聊天(JSON+可选下载媒体):

GET /api/export/chat/:jid?include_media=true

如果 include_media=true,ZIP包括已通过下载的文件 download_media。它不会从WhatsApp获取丢失的媒体。