@paean-ai/wechat-mcp 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +102 -26
- package/dist/cli.js +359 -80
- package/dist/daemon/server.js +200 -14
- package/dist/index.d.ts +58 -5
- package/dist/index.js +115 -7
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @paean-ai/wechat-mcp
|
|
2
2
|
|
|
3
|
-
WeChat MCP middleware — shared WeChat connection for multiple AI agents with @mention routing.
|
|
3
|
+
WeChat MCP middleware — shared WeChat connection for multiple AI agents with @mention routing and multi-mode message delivery.
|
|
4
4
|
|
|
5
5
|
## Problem
|
|
6
6
|
|
|
@@ -23,6 +23,7 @@ WeChat's official iLink protocol only allows **one bot per WeChat account**. If
|
|
|
23
23
|
▼ ▼ ▼
|
|
24
24
|
MCP Server MCP Server MCP Server
|
|
25
25
|
(claude) (openclaw) (paean)
|
|
26
|
+
channel gateway poll
|
|
26
27
|
▲ ▲ ▲
|
|
27
28
|
│ │ │ stdio MCP
|
|
28
29
|
Claude Code OpenClaw Paean CLI
|
|
@@ -31,7 +32,18 @@ WeChat's official iLink protocol only allows **one bot per WeChat account**. If
|
|
|
31
32
|
1. A **background daemon** manages the single WeChat connection (QR login, message polling, token cache)
|
|
32
33
|
2. Each agent connects via its own **MCP stdio server** (thin client)
|
|
33
34
|
3. Incoming messages are **routed by @mention**: `@claude hello` goes to Claude, `@openclaw run task` goes to OpenClaw
|
|
34
|
-
4.
|
|
35
|
+
4. Messages are **delivered differently** based on agent mode (channel / gateway / poll)
|
|
36
|
+
5. Any agent can **send messages** through the shared connection
|
|
37
|
+
|
|
38
|
+
## Message Delivery Modes
|
|
39
|
+
|
|
40
|
+
Different agents consume messages differently. The `--mode` flag controls how incoming WeChat messages reach your agent:
|
|
41
|
+
|
|
42
|
+
| Mode | How It Works | Best For |
|
|
43
|
+
|---|---|---|
|
|
44
|
+
| **channel** | Push via Claude Code's proprietary channel protocol. Messages appear in the agent's active conversation automatically. | Claude Code |
|
|
45
|
+
| **gateway** | Daemon POSTs message to agent's HTTP endpoint, collects SSE response, sends it back through WeChat. Fully automatic bridging. | OpenClaw, 0claw, any HTTP-based agent |
|
|
46
|
+
| **poll** | Agent calls `wechat_read_messages` tool to pull queued messages on demand. | Generic MCP agents, custom bots |
|
|
35
47
|
|
|
36
48
|
## Quick Start
|
|
37
49
|
|
|
@@ -49,37 +61,82 @@ wechat-mcp setup
|
|
|
49
61
|
|
|
50
62
|
Scan the QR code with WeChat. Credentials are saved to `~/.wechat-mcp/`.
|
|
51
63
|
|
|
52
|
-
### 3. Add to
|
|
64
|
+
### 3. Add to Your Agent
|
|
53
65
|
|
|
54
|
-
|
|
66
|
+
Choose the configuration that matches your agent type:
|
|
67
|
+
|
|
68
|
+
**Claude Code** (channel mode — messages arrive automatically):
|
|
69
|
+
|
|
70
|
+
```json
|
|
71
|
+
{
|
|
72
|
+
"mcpServers": {
|
|
73
|
+
"wechat": {
|
|
74
|
+
"command": "npx",
|
|
75
|
+
"args": ["@paean-ai/wechat-mcp", "serve", "--agent", "claude", "--mode", "channel"]
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
```
|
|
55
80
|
|
|
56
|
-
**
|
|
81
|
+
**OpenClaw / 0claw** (gateway mode — auto-bridges to HTTP endpoint):
|
|
57
82
|
|
|
58
83
|
```json
|
|
59
84
|
{
|
|
60
85
|
"mcpServers": {
|
|
61
86
|
"wechat": {
|
|
62
87
|
"command": "npx",
|
|
63
|
-
"args": [
|
|
88
|
+
"args": [
|
|
89
|
+
"@paean-ai/wechat-mcp", "serve",
|
|
90
|
+
"--agent", "openclaw",
|
|
91
|
+
"--mode", "gateway",
|
|
92
|
+
"--gateway-url", "http://localhost:3000"
|
|
93
|
+
]
|
|
64
94
|
}
|
|
65
95
|
}
|
|
66
96
|
}
|
|
67
97
|
```
|
|
68
98
|
|
|
69
|
-
|
|
99
|
+
For OpenAI-compatible endpoints, add `--gateway-type openai`.
|
|
100
|
+
|
|
101
|
+
**Generic MCP agent** (poll mode — agent reads messages via tool):
|
|
70
102
|
|
|
71
103
|
```json
|
|
72
104
|
{
|
|
73
105
|
"mcpServers": {
|
|
74
106
|
"wechat": {
|
|
75
107
|
"command": "npx",
|
|
76
|
-
"args": ["@paean-ai/wechat-mcp", "serve", "--agent", "
|
|
108
|
+
"args": ["@paean-ai/wechat-mcp", "serve", "--agent", "my-agent"]
|
|
77
109
|
}
|
|
78
110
|
}
|
|
79
111
|
}
|
|
80
112
|
```
|
|
81
113
|
|
|
82
|
-
Each agent uses a different `--agent` name.
|
|
114
|
+
Each agent uses a different `--agent` name. The daemon auto-starts when any agent connects.
|
|
115
|
+
|
|
116
|
+
## How Each Mode Works in Detail
|
|
117
|
+
|
|
118
|
+
### Channel Mode (Claude Code)
|
|
119
|
+
|
|
120
|
+
Claude Code supports a proprietary `notifications/claude/channel` protocol. The MCP server long-polls the daemon for messages and pushes them as channel notifications into Claude's active conversation. Claude sees the message and can reply using `wechat_send`.
|
|
121
|
+
|
|
122
|
+
### Gateway Mode (OpenClaw, HTTP agents)
|
|
123
|
+
|
|
124
|
+
The daemon acts as a bridge (similar to [AnyClaw](https://github.com/nicepkg/anyclaw)):
|
|
125
|
+
|
|
126
|
+
1. WeChat user sends `@openclaw help me with code`
|
|
127
|
+
2. Daemon POSTs `{ message: "help me with code" }` to `http://localhost:3000/api/chat`
|
|
128
|
+
3. Reads the SSE response stream from the agent
|
|
129
|
+
4. Sends the complete response back to the WeChat user
|
|
130
|
+
|
|
131
|
+
Supported gateway types:
|
|
132
|
+
- **claw** (default) — `POST /api/chat`, SSE response with `{type: "content", text: "..."}` events
|
|
133
|
+
- **openai** — `POST /v1/chat/completions`, SSE response with OpenAI chunk format
|
|
134
|
+
|
|
135
|
+
The daemon maintains per-user conversation IDs so the agent can track multi-turn conversations.
|
|
136
|
+
|
|
137
|
+
### Poll Mode (Generic)
|
|
138
|
+
|
|
139
|
+
The MCP server exposes an extra tool `wechat_read_messages` that returns any queued messages. The agent decides when and how often to check. Messages queue up in the daemon (bounded to 200 per agent) until read.
|
|
83
140
|
|
|
84
141
|
## Message Routing
|
|
85
142
|
|
|
@@ -93,25 +150,35 @@ Each agent uses a different `--agent` name. That's it — the daemon auto-starts
|
|
|
93
150
|
## CLI Commands
|
|
94
151
|
|
|
95
152
|
```bash
|
|
96
|
-
wechat-mcp setup
|
|
97
|
-
wechat-mcp serve --agent X
|
|
98
|
-
wechat-mcp daemon
|
|
99
|
-
wechat-mcp stop
|
|
100
|
-
wechat-mcp status
|
|
101
|
-
wechat-mcp contacts
|
|
102
|
-
wechat-mcp send --to X --text Y
|
|
103
|
-
wechat-mcp logout
|
|
153
|
+
wechat-mcp setup # QR login
|
|
154
|
+
wechat-mcp serve --agent X [opts] # Start MCP server (used in agent config)
|
|
155
|
+
wechat-mcp daemon # Start daemon in foreground
|
|
156
|
+
wechat-mcp stop # Stop daemon
|
|
157
|
+
wechat-mcp status # Show status (with mode info)
|
|
158
|
+
wechat-mcp contacts # List known contacts
|
|
159
|
+
wechat-mcp send --to X --text Y # One-shot send
|
|
160
|
+
wechat-mcp logout # Remove credentials & stop daemon
|
|
104
161
|
```
|
|
105
162
|
|
|
163
|
+
### `serve` Options
|
|
164
|
+
|
|
165
|
+
| Flag | Description | Default |
|
|
166
|
+
|---|---|---|
|
|
167
|
+
| `-a, --agent <id>` | Agent identifier (required) | — |
|
|
168
|
+
| `-m, --mode <mode>` | Delivery mode: `channel`, `gateway`, `poll` | `poll` |
|
|
169
|
+
| `--gateway-url <url>` | Agent's HTTP endpoint (required for gateway mode) | — |
|
|
170
|
+
| `--gateway-type <type>` | Gateway protocol: `claw` or `openai` | `claw` |
|
|
171
|
+
|
|
106
172
|
## MCP Tools
|
|
107
173
|
|
|
108
174
|
When connected as an MCP server, agents can use these tools:
|
|
109
175
|
|
|
110
|
-
| Tool | Description |
|
|
111
|
-
|
|
112
|
-
| `wechat_send` | Send a text message to a WeChat user |
|
|
113
|
-
| `wechat_get_contacts` | List known WeChat contacts |
|
|
114
|
-
| `wechat_get_status` | Get connection status and registered agents |
|
|
176
|
+
| Tool | Description | Available In |
|
|
177
|
+
|---|---|---|
|
|
178
|
+
| `wechat_send` | Send a text message to a WeChat user | All modes |
|
|
179
|
+
| `wechat_get_contacts` | List known WeChat contacts | All modes |
|
|
180
|
+
| `wechat_get_status` | Get connection status and registered agents | All modes |
|
|
181
|
+
| `wechat_read_messages` | Read pending messages (non-blocking) | Poll mode only |
|
|
115
182
|
|
|
116
183
|
## Proactive Messaging
|
|
117
184
|
|
|
@@ -126,8 +193,9 @@ wechat-mcp send --to "friend@im.wechat" --text "Task completed!"
|
|
|
126
193
|
|
|
127
194
|
## Architecture
|
|
128
195
|
|
|
129
|
-
- **Daemon** (`~/.wechat-mcp/daemon.json`): Auto-started background process that owns the WeChat connection. Listens on `127.0.0.1` only.
|
|
130
|
-
- **MCP Server**: Thin stdio process spawned per-agent. Connects to daemon over local HTTP.
|
|
196
|
+
- **Daemon** (`~/.wechat-mcp/daemon.json`): Auto-started background process that owns the WeChat connection. Listens on `127.0.0.1` only. Handles gateway bridging for HTTP-based agents.
|
|
197
|
+
- **MCP Server**: Thin stdio process spawned per-agent. Connects to daemon over local HTTP. Mode determines message delivery strategy.
|
|
198
|
+
- **Gateway Adapters**: Protocol translators for different agent types (claw SSE, OpenAI completions).
|
|
131
199
|
- **Credentials**: Stored in `~/.wechat-mcp/credentials.json` with `0600` permissions.
|
|
132
200
|
|
|
133
201
|
## Programmatic API
|
|
@@ -138,18 +206,25 @@ import {
|
|
|
138
206
|
DaemonClient,
|
|
139
207
|
loadCredentials,
|
|
140
208
|
parseMention,
|
|
209
|
+
getAdapter,
|
|
141
210
|
} from "@paean-ai/wechat-mcp";
|
|
142
211
|
|
|
143
212
|
// Connect to daemon
|
|
144
213
|
const daemon = await ensureDaemon();
|
|
145
214
|
const client = new DaemonClient(daemon.port);
|
|
146
215
|
|
|
147
|
-
// Register
|
|
148
|
-
await client.registerAgent("my-bot");
|
|
216
|
+
// Register with mode
|
|
217
|
+
await client.registerAgent("my-bot", "My Bot", "poll");
|
|
218
|
+
|
|
219
|
+
// Poll for messages
|
|
149
220
|
const messages = await client.pollMessages("my-bot");
|
|
150
221
|
|
|
151
222
|
// Send
|
|
152
223
|
await client.send("user@wxid", "Hello from my bot!", "my-bot");
|
|
224
|
+
|
|
225
|
+
// Or use a gateway adapter directly
|
|
226
|
+
const adapter = getAdapter("claw");
|
|
227
|
+
const result = await adapter.send("http://localhost:3000", "Hello");
|
|
153
228
|
```
|
|
154
229
|
|
|
155
230
|
## Security
|
|
@@ -158,6 +233,7 @@ await client.send("user@wxid", "Hello from my bot!", "my-bot");
|
|
|
158
233
|
- Daemon listens only on `127.0.0.1` (no network exposure)
|
|
159
234
|
- No secrets in environment variables or logs
|
|
160
235
|
- Token stored locally, never transmitted to third parties
|
|
236
|
+
- Gateway connections are local only (localhost)
|
|
161
237
|
|
|
162
238
|
## License
|
|
163
239
|
|