内容
# WhatsApp MCP
通过输入到您的AI助手发送WhatsApp消息 - 例如“告诉Lior我会迟点到” - 并读取最近聊天的总结。作为一个伴侣设备,它链接到您真实的WhatsApp(像WhatsApp网页版一样),所以消息来自**您本人**,而不是一个单独号码上的机器人。
它完全在您的Mac上本地运行,并作为一个标准的 **MCP服务器通过stdio** 暴露,因此任何MCP客户端(Claude Desktop,Claude Code等)都可以使用它。
> ⚠️ **诚实的提醒**。该工具通过非官方库([Baileys](https://github.com/WhiskeySockets/Baileys))自动化了一个个人WhatsApp账户,这违反了WhatsApp的服务条款,并存在您的号码被标记的风险。该工具专门为**轻量级、低频、个人使用**而构建,并在每次发送时都需要人类参与。不要用于批量或向陌生人发送消息。您已知晓并接受此风险。
---
## 功能
- **发送文本** 给联系人或群组,输入名称后确认收件人和文本。
- **发送照片或文件** 从Mac到联系人/群组,确认后。
- **读取和总结** 聊天中的最近消息。只读;从不发送。
- **发送前确认由服务器强制执行** ,而不仅仅是助手:发送在结构上是无法实现的,除非有一个预览的、一次性使用的草稿,您已经批准。
- 安全防护措施:每次发送前有类似人类的延迟,每分钟/每天的速率限制,仅限联系人解析(未知号码需要额外确认),本地发送日志和暂停开关。
## 两个部分
1. **网关** (`npm start`)- 一个小型常驻进程,持有WhatsApp连接,记录最近的消息,并强制执行防护措施。您启动它一次,然后让它运行。
2. **MCP适配器** - 一个薄stdio服务器,您的MCP客户端自动启动。它通过本地、令牌保护的`127.0.0.1` API与网关通信。
您保持网关运行;助手通过适配器与它通信。
---
## 1. 要求
- macOS, **Node.js 20+** (在Node 22上开发)。
- 带有WhatsApp的手机,扫描一次二维码。
## 2. 安装和构建
```bash
git clone <此仓库> whatsapp-mcp
cd whatsapp-mcp
npm install
npm run build
```
## 3. 链接您的WhatsApp(一次)
在终端中:
```bash
npm start
```
出现一个 **二维码**。在您的手机上:**WhatsApp → 设置 → 已链接设备 → 链接设备**,然后扫描它。您将看到:
```
✅ 已连接为 +9725........ . 会话已保存 - 重启后无需重新链接。
```
让这个终端保持运行 - 这是网关。会话保存在`~/.whatsapp-mcp`下,因此重启网关后 **无需** 重新链接。
> 更喜欢 **配对代码** 而不是二维码?启动时设置`WHATSAPP_MCP_PAIR_NUMBER=<您的号码,仅限数字>`,例如`WHATSAPP_MCP_PAIR_NUMBER=15551234567 npm start`,然后在手机上使用 *"改为使用电话号码链接"*。
## 4. 连接到您的MCP客户端
工具运行时,网关必须运行(步骤3)。
### Claude Desktop
编辑 `~/Library/Application Support/Claude/claude_desktop_config.json` (如果丢失则创建):
```json
{
"mcpServers": {
"whatsapp": {
"command": "node",
"args": ["/ABSOLUTE/PATH/TO/whatsapp-mcp/dist/mcp/index.js"]
}
}
}
```
使用 `dist/mcp/index.js` 的**绝对路径**。如果Claude Desktop找不到`node`,请将其替换为`which node`的绝对路径。重启Claude Desktop。
### Claude Code
```bash
claude mcp add whatsapp -- node /ABSOLUTE/PATH/TO/whatsapp-mcp/dist/mcp/index.js
```
> 适配器会自动找到网关(默认`127.0.0.1:8787`,数据在`~/.whatsapp-mcp`中)。仅当您覆盖网关的`WHATSAPP_MCP_PORT`或`WHATSAPP_MCP_DATA_DIR`时,请在此处设置**相同**的值,放在`"env": { … }`块中。
## 5. 使用它
只需与您的助手对话。它将始终显示预览并在发送任何内容之前等待您的“是”。
| 您说的话 | 发生的情况 |
|---|---|
| *"告诉Lior我会迟点到。"* | 找到联系人 **Lior**,显示号码 + 文本 → 您确认 → 已发送。 |
| *"告诉足球队练习取消了。"* | 按名称查找 **群组**,显示主题 + 大小 → 您确认 → 已发送。 |
| *"发送这张照片给我的妻子:/Users/me/pics/beach.jpg"* | 附加图像 → 您确认 → 已发送。 |
| *"Lior有新消息吗?"* / *"足球队今天说了什么?"* | 读取最近的消息并总结。不会发送任何内容。 |
典型的确认流程如下:
> **您:** 告诉Dana我会迟10分钟
> **助手:** 这里是草稿 - **收件人:** Dana (+972‑50‑xxx‑xxxx),**消息:** "我会迟10分钟"。发送吗?
> **您:** 是的
> **助手:** ✅ 已发送给Dana。
如果名称 **不明确** (“Lior”匹配两个个人),它会显示匹配结果并询问您选择哪一个。如果 **没有匹配** ,它会告诉您并停止 - 它永远不会猜测。向 **不是已保存联系人** 的号码发送消息需要额外的明确确认。
---
## 状态、暂停、停止
从项目目录(与正在运行的网关通信的薄CLI):
```bash
npm run status # 连接状态、链接号码、今日发送次数、缓存大小
npm run pause # 阻止所有发送(读取仍然有效)
npm run resume # 重新启用发送
npm run link # 重新显示二维码/配对代码(例如,注销后)
npm run stop # 关闭网关
```
您也可以询问助手: *"您的WhatsApp状态如何?"* , *"暂停WhatsApp发送"* , *"恢复。"* 要完全停止网关,请使用 `npm run stop` 或终端中的 `Ctrl‑C` 。
## 安全防护措施及调整方法
所有默认值都在一个地方 - [`src/config.ts`](src/config.ts) ,每个也可以通过环境变量设置:
| 设置 | 默认值 | 环境变量 |
|---|---|---|
| 每次发送前的随机延迟 | 3–12 秒 | `WHATSAPP_MCP_SEND_DELAY_MIN_MS` / `_MAX_MS` |
| 每分钟最大发送次数 | 5 | `WHATSAPP_MCP_MAX_PER_MINUTE` |
| 每日最大发送次数 | 100 | `WHATSAPP_MCP_MAX_PER_DAY` |
| 草稿有效窗口 | 10 分钟 | `WHATSAPP_MCP_DRAFT_TTL_MS` |
| 每个聊天保留的最近消息 | 200 | (编辑 `config.ts`) |
编辑 `config.ts` 后,运行 `npm run build` 并重启网关。
> **联系人 & 历史记录:** 您的地址簿和最近的聊天记录从您链接时 WhatsApp 发送的同步中捕获(这是名称查找功能的工作原理,例如 *"告诉Lior…"* )。仅存储带有电话号码的已保存联系人;WhatsApp 的冗余 `@lid` 别名被忽略。要获取 **整个** 历史记录而不是仅最近的记录,请设置 `WHATSAPP_MCP_SYNC_FULL_HISTORY=true` - 但它更重量级,并且在某些帐户上,WhatsApp 会拒绝连接(您将看到重新连接循环),因此除非需要,否则请关闭它。
## 数据 & 隐私
所有内容都位于本地,位于 `~/.whatsapp-mcp/` 下:
- `auth/` - 您的链接设备会话(像密码一样对待)。
- `store.db` - 缓存的联系人、群组、最近的消息和您的 **发送日志** (`sent_log` 表)。
- `control-token` - 本地 API 机密。
**取消链接/重置:** 停止网关,删除 `~/.whatsapp-mcp/auth` ,然后再次运行 `npm start` 以重新链接。要清除所有内容,请删除整个 `~/.whatsapp-mcp/` 文件夹。除确认发送外,绝不会将任何内容发送到除 WhatsApp 之外的任何地方。
## 可选:登录时自动启动(launchd)
默认情况下,您自己启动网关。如果您希望它在后台登录时运行,请创建 `~/Library/LaunchAgents/com.you.whatsapp-mcp.plist` (替换路径):
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"><dict>
<key>Label</key><string>com.you.whatsapp-mcp</string>
<key>ProgramArguments</key>
<array>
<string>/ABSOLUTE/PATH/TO/node</string>
<string>/ABSOLUTE/PATH/TO/whatsapp-mcp/dist/daemon/index.js</string>
</array>
<key>RunAtLoad</key><true/>
<key>KeepAlive</key><true/>
<key>StandardOutPath</key><string>/tmp/whatsapp-mcp.log</string>
<key>StandardErrorPath</key><string>/tmp/whatsapp-mcp.err</string>
</dict></plist>
```
然后 `launchctl load ~/Library/LaunchAgents/com.you.whatsapp-mcp.plist` 。在启用此功能之前,请先交互式地执行一次 `npm start` 链接,因为二维码需要终端。卸载使用 `launchctl unload …` 。
## 故障排除
- **助手说它无法连接到网关** → 启动它: `npm start` 。工具需要网关运行。
- **卡在“等待链接”** → 运行 `npm run link` 以重新显示二维码,或检查网关终端。
- **“注销 - 需要重新链接”** → WhatsApp 已断开设备。网关清除旧会话并自动显示新的二维码;只需再次扫描。
- **两个客户端** (桌面 + 代码)可以安全地共享一个网关 - 只有网关连接到 WhatsApp,因此没有双重登录冲突。
- **还没有内容可读** → 网关仅在运行时记录它接收到的消息。让它运行以累积最近的历史记录。
- **名称查找无法找到联系人 / `whatsapp_status` 显示 0 个联系人** → 您的地址簿仅在 WhatsApp 的同步中到达 **新鲜链接** 。如果您链接过并且没有联系人,请在手机上取消链接设备(WhatsApp → 已链接设备),然后运行 `npm start` 并扫描新的二维码 - 联系人将在 ~30 秒内填充。您可以在此期间始终按电话号码发送。
## 工作原理(适用于好奇的人)
- **Baileys** 直接使用WhatsApp的多设备协议(无浏览器)。网关拥有一个套接字,使用`useMultiFileAuthState`持久化会话,并从实时事件中构建本地存储。
- **发送前确认:** `prepare_message`解析收件人并写入草稿(绑定到确切的收件人 + 内容,一次性使用,~10分钟过期)并返回预览。 `send_message`仅接受**该**草稿ID - 因此它无法发送未经预览或更改的内容,也无法在没有批准的草稿的情况下发送。
- MCP适配器仅支持stdio,从不记录到stdout(保留用于JSON-RPC);网关在本地控制API后面执行所有WhatsApp工作。
## 不在v1中
预定/延迟发送、自动回复或始终开启的通知、广播/批量/邮件列表发送以及任何Web UI或托管。立即发送,每个收件人一次,仅限本地。