wazap-mcp 0.9.8 → 0.11.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/AGENT.md +4 -3
- package/README.md +173 -18
- package/dist/auth-state.js +5 -0
- package/dist/bridge.js +9 -4
- package/dist/cli.js +150 -138
- package/dist/config.js +19 -1
- package/dist/connect.js +113 -19
- package/dist/deps.js +46 -0
- package/dist/doctor.js +82 -11
- package/dist/errors.js +2 -0
- package/dist/expose.js +219 -0
- package/dist/index.js +27 -4
- package/dist/oauth.js +498 -0
- package/dist/pairing.js +157 -0
- package/dist/server.js +90 -15
- package/dist/service.js +441 -0
- package/dist/settings.js +3 -1
- package/dist/setup.js +173 -7
- package/dist/skills.js +118 -27
- package/dist/tools.js +36 -2
- package/dist/ui.js +6 -3
- package/dist/update.js +136 -0
- package/dist/whatsapp.js +101 -16
- package/package.json +4 -3
- package/skills/wazap-setup/SKILL.md +15 -3
package/AGENT.md
CHANGED
|
@@ -6,12 +6,13 @@ wazap keeps stdout for the MCP protocol and writes every human-readable line to
|
|
|
6
6
|
|
|
7
7
|
1. Run `npx wazap-mcp status --json`. If `linked` is true, skip to step 5.
|
|
8
8
|
2. Ask the person for their WhatsApp number in international format (e.g. +15550100) and whether the agent may send messages (default: no).
|
|
9
|
-
3.
|
|
9
|
+
3. If you already have the `whatsapp` tools (the Claude Desktop bundle, or any client wazap is connected to), call `link_account` with the number. It returns the code within ~10 s and needs no terminal. Otherwise start the link IN THE BACKGROUND and keep reading its output:
|
|
10
10
|
`npx wazap-mcp login --phone <number> --no-writes --yes 2>&1` (or `--writes`).
|
|
11
11
|
Within ~10 s the output contains a line `pairing code: XXXX-XXXX`.
|
|
12
|
-
4. Show the person exactly: "On your phone: WhatsApp → Settings → Linked devices → Link a device → Link with phone number instead → enter XXXX-XXXX".
|
|
13
|
-
5. Register wazap with the client you are running in: `npx wazap-mcp connect <client>` where <client> is claude-code, claude-desktop, cursor, codex, vscode or gemini. Tell the person what the command printed as `Next`.
|
|
12
|
+
4. Show the person exactly: "On your phone: WhatsApp → Settings → Linked devices → Link a device → Link with phone number instead → enter XXXX-XXXX". After `link_account`, call `get_status` every 10 seconds until it says `connected` (up to 3 minutes); after the command, keep reading the output until `Linked as …` and then `Synced N chats …` appear. If the code expired, run step 3 again.
|
|
13
|
+
5. If step 1 reported `install.kind: "npx"`, run `npm i -g wazap-mcp` first: Claude Desktop and the background service cannot launch from the npx cache, which npm clears. Register wazap with the client you are running in: `npx wazap-mcp connect <client>` where <client> is claude-code, claude-desktop, cursor, codex, vscode or gemini. Tell the person what the command printed as `Next`. Then, for claude-code, codex, cursor and opencode, run `npx wazap-mcp skills install <client>`, which copies the five workflow skills where that client reads them. The other clients need no such step, because the server hands them the same five workflows as MCP prompts.
|
|
14
14
|
6. Verify: `npx wazap-mcp status --json` must show `linked: true` and no failing check. If the client needs a restart, say so; otherwise call the `get_status` tool and then `learn`.
|
|
15
15
|
7. Done when `get_status` returns `connected`. Then offer: "what did I miss on WhatsApp today?"
|
|
16
|
+
8. Ask whether wazap should keep running after this client closes, and whether cloud agents should reach it. For the first, run `npx wazap-mcp service install`, which writes a launchd agent or a systemd user unit and starts it. For the second, also run `npx wazap-mcp expose`. It opens a tunnel, prints an https URL and a consent password, and restarts the service. Give an agent the URL only. The password is for the person, on their consent page; never paste it into a chat, a config file or a message.
|
|
16
17
|
|
|
17
18
|
Errors: every wazap error prints `✗ message` and `→ fix`; do what the fix says, do not retry blindly. One process owns the session, so while the `login` of step 3 runs, no server and no other wazap command may touch the same data dir; two servers on one data dir refuse to start. Stop the other one first.
|
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
```
|
|
9
9
|
|
|
10
10
|
**WhatsApp for your AI agent.** An MCP server that puts your WhatsApp account —
|
|
11
|
-
chats, messages, media, contacts, groups — behind
|
|
11
|
+
chats, messages, media, contacts, groups — behind 25 tools any MCP client can
|
|
12
12
|
call. Pairing-code login, no browser, no phone-number reseller, ~20 MB of RAM.
|
|
13
13
|
|
|
14
14
|
Built on [Baileys](https://github.com/WhiskeySockets/Baileys), which speaks the
|
|
@@ -23,7 +23,12 @@ npx wazap-mcp setup
|
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
That is the whole install. It links your account, finds the MCP clients
|
|
26
|
-
installed on this machine, writes their config
|
|
26
|
+
installed on this machine, writes their config, copies the five skills where
|
|
27
|
+
that client reads them, and tells you what to restart. When you started through
|
|
28
|
+
`npx`, `setup` offers to install wazap globally so Claude Desktop and the
|
|
29
|
+
background service have a path that does not change. It also offers to
|
|
30
|
+
`brew install` whisper-cpp, ffmpeg or Tailscale when a step needs one and it is
|
|
31
|
+
missing, and to restart Claude Desktop itself once it has connected it.
|
|
27
32
|
|
|
28
33
|
### Or the path your harness prefers
|
|
29
34
|
|
|
@@ -82,7 +87,7 @@ it would write.
|
|
|
82
87
|
| `gemini` | `~/.gemini/settings.json` |
|
|
83
88
|
| `windsurf` | `~/.codeium/windsurf/mcp_config.json` |
|
|
84
89
|
| `opencode` | `mcp.whatsapp` in `~/.config/opencode/opencode.json` |
|
|
85
|
-
| anything remote | client's MCP URL field: `https://your-host/mcp` with header `Authorization: Bearer <token
|
|
90
|
+
| anything remote | client's MCP URL field: `https://your-host/mcp` with header `Authorization: Bearer <token>`, or just the URL once [OAuth](#hosted-agents-oauth) is on (see [Self-host](#self-host)) |
|
|
86
91
|
|
|
87
92
|
### Other MCP clients
|
|
88
93
|
|
|
@@ -159,26 +164,93 @@ Download `wazap-<version>.mcpb` from [Releases](https://github.com/razvangirgiz/
|
|
|
159
164
|
and double-click it. Claude Desktop installs the server, its Node dependencies
|
|
160
165
|
and the icon, and shows two settings: **Read-only**, ticked, and **Data
|
|
161
166
|
directory**, empty. `wazap connect claude-desktop` does the same job by editing
|
|
162
|
-
`claude_desktop_config.json
|
|
167
|
+
`claude_desktop_config.json`. Claude Desktop starts its servers without your
|
|
168
|
+
shell PATH, so that entry is the absolute path to `node` when wazap is installed
|
|
169
|
+
globally, and `npx` otherwise; `wazap setup` checks that the entry it wrote is
|
|
170
|
+
one Claude Desktop can actually launch.
|
|
163
171
|
|
|
164
|
-
|
|
165
|
-
|
|
172
|
+
Then ask Claude to link your WhatsApp. It calls `link_account` with your number,
|
|
173
|
+
hands back an 8-character code, and you type that code into **WhatsApp →
|
|
174
|
+
Settings → Linked devices → Link a device → Link with phone number instead**.
|
|
175
|
+
No terminal at any point. `npx wazap-mcp login` does the same job from a shell
|
|
176
|
+
when you have one.
|
|
166
177
|
|
|
167
178
|
Untick **Read-only** to let Claude send. It ships ticked because a bundle that
|
|
168
179
|
can message people from your number before you have said so is the wrong
|
|
169
180
|
default, and because the setting cannot be left unanswered: the manifest format
|
|
170
181
|
has no way to omit an argument, so the box you see is the answer the server gets.
|
|
182
|
+
`link_account` is registered either way. Read-only exists to stop Claude
|
|
183
|
+
messaging people from your number, and relinking your own dead session messages
|
|
184
|
+
nobody.
|
|
171
185
|
|
|
172
186
|
Build it yourself with `npm run bundle:mcpb`, which stages `dist/`, the
|
|
173
187
|
manifest, the icon and a fresh production `node_modules`, then packs them with
|
|
174
188
|
[`@anthropic-ai/mcpb`](https://github.com/modelcontextprotocol/mcpb).
|
|
175
189
|
|
|
190
|
+
### Keep it running
|
|
191
|
+
|
|
192
|
+
A wazap started by a client lives as long as that client does. Quit Claude Code
|
|
193
|
+
and the session is gone until you open it again. Two commands change that.
|
|
194
|
+
Staying up and being reachable are separate choices.
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
npx wazap-mcp service install
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
That writes a launchd agent on macOS (`~/Library/LaunchAgents/com.wazap.server.plist`)
|
|
201
|
+
or a systemd user unit on Linux (`~/.config/systemd/user/wazap.service`), starts
|
|
202
|
+
it, and waits for `/healthz` to answer. The unit runs `serve --http` on
|
|
203
|
+
`127.0.0.1:8766` with the absolute path of this Node and this install, so it
|
|
204
|
+
survives a reboot and a logout. Point any client at
|
|
205
|
+
`http://127.0.0.1:8766/mcp`, or keep using the stdio entry. A second wazap on
|
|
206
|
+
the same data directory becomes a bridge onto the session this one holds.
|
|
207
|
+
|
|
208
|
+
`service status` prints the pid, the health check and whether the unit still
|
|
209
|
+
runs the version you have installed. `service logs` tails it. `service restart`
|
|
210
|
+
picks up an upgrade; `service uninstall` removes the unit and leaves your
|
|
211
|
+
session and credentials alone. `wazap login` needs the session to itself, so it
|
|
212
|
+
stops the service, pairs, and starts it again on its own.
|
|
213
|
+
|
|
214
|
+
A sleeping Mac is an offline wazap. System Settings → Lock Screen, or Battery →
|
|
215
|
+
Options, has the switch that keeps it awake on power.
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
npx wazap-mcp expose
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
That gives the running service a public `https` URL, for agents that are not on
|
|
222
|
+
this machine: a cloud agent, claude.ai, ChatGPT. It uses Tailscale Funnel if
|
|
223
|
+
`tailscale` is installed, Cloudflare Tunnel if `cloudflared` is, opens the
|
|
224
|
+
tunnel, writes `WAZAP_PUBLIC_URL` and a fresh `WAZAP_OAUTH_PASSWORD` into
|
|
225
|
+
`<data-dir>/.env`, restarts the service and checks the URL from here. It then
|
|
226
|
+
prints the MCP URL and the password once.
|
|
227
|
+
|
|
228
|
+
Give an agent the URL only. It signs in on a consent page on your own host with
|
|
229
|
+
that password and picks read or read-and-send there; `wazap status` lists who
|
|
230
|
+
holds a grant. See [Hosted agents (OAuth)](#hosted-agents-oauth) for what that
|
|
231
|
+
page does. `npx wazap-mcp expose off` takes the tunnel down and keeps the
|
|
232
|
+
password, so the next `expose` hands agents the same one.
|
|
233
|
+
|
|
234
|
+
`npx wazap-mcp setup` asks all of this once, as its fourth step.
|
|
235
|
+
|
|
236
|
+
### Upgrade
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
npx wazap-mcp update
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
One command for what used to be three. It compares this install against the
|
|
243
|
+
registry, installs the new package when wazap is global, restarts the service so
|
|
244
|
+
it runs the new code, and copies the new skills into every harness that keeps
|
|
245
|
+
them. `--dry-run` prints the plan and touches nothing.
|
|
246
|
+
|
|
176
247
|
## Tools
|
|
177
248
|
|
|
178
249
|
| Tool | Kind | What it does |
|
|
179
250
|
| --- | --- | --- |
|
|
180
251
|
| `learn` | read | The guide to every tool, id format and error code. Call it first. |
|
|
181
252
|
| `get_status` | read | Connection status, sync state, linked account, named-contact count, versions, data dir. |
|
|
253
|
+
| `link_account` | read | Pair the account without a terminal: returns the code to type into the phone. Registered in read-only mode too. |
|
|
182
254
|
| `list_chats` | read | Conversations newest-first; filter `all`/`unread`/`groups`/`individual`/`archived`. |
|
|
183
255
|
| `read_messages` | read | Messages in a chat; `before` pages further back, pulling older history from the phone; `types` narrows to one or more message types, e.g. `["call"]`. |
|
|
184
256
|
| `get_recent_messages` | read | Everything from the last N hours, grouped by chat. The catch-up tool. `include_system` adds WhatsApp's own notices, `types` narrows to one or more message types. |
|
|
@@ -238,6 +310,10 @@ wazap transcribe download # fetch and verify the model
|
|
|
238
310
|
wazap transcribe test recording.ogg # prove it before you trust it
|
|
239
311
|
```
|
|
240
312
|
|
|
313
|
+
`wazap setup` and `wazap transcribe download` offer that `brew install`
|
|
314
|
+
themselves when either binary is missing, and go straight on to the model in the
|
|
315
|
+
same run. `--no-brew` turns the offer off everywhere.
|
|
316
|
+
|
|
241
317
|
Models land in `<data-dir>/models/` and are checked against a SHA-256 pinned in
|
|
242
318
|
the source; an interrupted download resumes where it stopped.
|
|
243
319
|
|
|
@@ -300,22 +376,25 @@ wazap ships five [Agent Skills](https://agentskills.io) that teach an agent the
|
|
|
300
376
|
| `whatsapp-groups` | Catch up on a 300-message group: decisions, dates, what is asked of you. Read-only |
|
|
301
377
|
| `whatsapp-send` | Draft in the chat's own register, show recipient and text, send only after the user says yes |
|
|
302
378
|
|
|
303
|
-
|
|
379
|
+
`wazap setup` copies them into every client it connects, so there is usually
|
|
380
|
+
nothing to run. The command behind it, for a harness `setup` never offered or
|
|
381
|
+
for a checkout you want to install by hand:
|
|
304
382
|
|
|
305
|
-
```
|
|
306
|
-
|
|
307
|
-
/plugin install wazap@wazap
|
|
383
|
+
```bash
|
|
384
|
+
npx wazap-mcp skills install codex # or claude-code, cursor, opencode, agents
|
|
308
385
|
```
|
|
309
386
|
|
|
310
|
-
|
|
387
|
+
With no harness named it installs into every client it finds on this machine.
|
|
388
|
+
For Claude Code the other route is the plugin, which carries the server as well:
|
|
311
389
|
|
|
312
|
-
```
|
|
313
|
-
|
|
390
|
+
```
|
|
391
|
+
/plugin marketplace add razvangirgiz/wazap
|
|
392
|
+
/plugin install wazap@wazap
|
|
314
393
|
```
|
|
315
394
|
|
|
316
395
|
| Harness | Where the five directories land |
|
|
317
396
|
| --- | --- |
|
|
318
|
-
| `claude-code` |
|
|
397
|
+
| `claude-code` | `~/.claude/skills/` |
|
|
319
398
|
| `codex` | `~/.agents/skills/`, the directory Codex documents for user skills. Cursor and OpenCode read it too |
|
|
320
399
|
| `cursor` | `~/.cursor/skills/` |
|
|
321
400
|
| `opencode` | `~/.config/opencode/skills/` |
|
|
@@ -324,6 +403,13 @@ npx wazap-mcp skills install codex # or cursor, opencode, agents
|
|
|
324
403
|
Re-running overwrites, so an upgrade is the same command. `--dry-run` lists
|
|
325
404
|
what it would copy.
|
|
326
405
|
|
|
406
|
+
A client with no skills directory is not left out. The server registers each of
|
|
407
|
+
the five as an MCP prompt of the same name, and sends a short `instructions`
|
|
408
|
+
block that names all five and says when each applies, so an agent that never saw
|
|
409
|
+
the skill files still follows them. That is how Claude Desktop, VS Code and
|
|
410
|
+
Windsurf get the workflows. A bridged session and a self-hosted HTTP server
|
|
411
|
+
carry them the same way.
|
|
412
|
+
|
|
327
413
|
## Errors
|
|
328
414
|
|
|
329
415
|
Every failure is a structured `{ error, message, fix }` rather than a stack
|
|
@@ -331,7 +417,8 @@ trace, so an agent can decide whether to retry, ask the user, or stop.
|
|
|
331
417
|
|
|
332
418
|
| Code | Meaning |
|
|
333
419
|
| --- | --- |
|
|
334
|
-
| `NOT_LINKED` | No account linked.
|
|
420
|
+
| `NOT_LINKED` | No account linked. Call `link_account`, or run `npx wazap-mcp login`. |
|
|
421
|
+
| `ALREADY_LINKED` | `link_account` was called on a session that is already linked. Call `get_status`. |
|
|
335
422
|
| `SESSION_EXPIRED` | Unlinked from the phone. Run `npx wazap-mcp login`. |
|
|
336
423
|
| `SESSION_CORRUPT` | Credentials unreadable. Run `npx wazap-mcp logout` then `login`. |
|
|
337
424
|
| `NOT_CONNECTED` | Still connecting or reconnecting. |
|
|
@@ -363,6 +450,7 @@ created `0700` with credentials written `0600`:
|
|
|
363
450
|
store.json chat-list snapshot
|
|
364
451
|
server.lock pid of the running server
|
|
365
452
|
daemon.json loopback endpoint a second wazap bridges to
|
|
453
|
+
oauth.json registered agents and hashed OAuth grants, when OAuth is on
|
|
366
454
|
.env optional settings, see .env.example
|
|
367
455
|
```
|
|
368
456
|
|
|
@@ -410,10 +498,14 @@ WAZAP_WRITE_TOKEN=$(openssl rand -hex 32) \
|
|
|
410
498
|
npx wazap-mcp serve --http --host 0.0.0.0 --port 8766
|
|
411
499
|
```
|
|
412
500
|
|
|
413
|
-
Streamable HTTP at `/mcp`, with a health check at `/healthz`.
|
|
501
|
+
Streamable HTTP at `/mcp`, with a health check at `/healthz`. That check answers
|
|
502
|
+
`{ ok, status, since }`. It turns 503 once the socket has been anything but
|
|
503
|
+
connected for two minutes, so a tunnel or a monitor sees a real outage rather
|
|
504
|
+
than a reconnect in progress. Two bearer tokens:
|
|
414
505
|
the read token gets the read tools, the write token also unlocks the write
|
|
415
506
|
tools, so a leaked read token can never message anyone. wazap refuses to bind a
|
|
416
|
-
non-loopback address without a read token.
|
|
507
|
+
non-loopback address without a read token. Agents that cannot carry a header
|
|
508
|
+
sign in with [OAuth](#hosted-agents-oauth) instead.
|
|
417
509
|
|
|
418
510
|
## Self-host
|
|
419
511
|
|
|
@@ -448,9 +540,70 @@ curl -s http://127.0.0.1:8766/healthz
|
|
|
448
540
|
|
|
449
541
|
The container publishes `8766` on loopback only; add the same TLS proxy in front. Upgrading is `git pull && docker compose up -d --build`; the volume keeps the session.
|
|
450
542
|
|
|
543
|
+
### From a machine without a public address
|
|
544
|
+
|
|
545
|
+
A laptop or a box behind NAT can still serve hosted agents through a tunnel, with no port opened and TLS done at the edge. `npx wazap-mcp expose` does the whole thing with Tailscale Funnel or Cloudflare Tunnel, whichever is installed. See [Keep it running](#keep-it-running).
|
|
546
|
+
|
|
547
|
+
wazap keeps binding loopback either way; only the tunnel reaches it.
|
|
548
|
+
|
|
549
|
+
<details>
|
|
550
|
+
<summary>By hand, with Cloudflare Tunnel and a domain on Cloudflare</summary>
|
|
551
|
+
|
|
552
|
+
```bash
|
|
553
|
+
cloudflared tunnel login
|
|
554
|
+
cloudflared tunnel create wazap
|
|
555
|
+
cloudflared tunnel route dns wazap wazap.example.com
|
|
556
|
+
cloudflared tunnel run --url http://127.0.0.1:8766 wazap
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
Set `WAZAP_PUBLIC_URL=https://wazap.example.com` for OAuth and keep `cloudflared` running the way you keep wazap running (a systemd unit, a launchd agent). Tailscale Funnel or ngrok work the same way: whatever ends at `https://your-host` with `/mcp` behind it.
|
|
560
|
+
|
|
561
|
+
</details>
|
|
562
|
+
|
|
451
563
|
### Which clients can reach it
|
|
452
564
|
|
|
453
|
-
Claude Code, Claude Desktop, Cursor, Codex, VS Code and any client with an "MCP URL + header" field connect with the bearer token.
|
|
565
|
+
Claude Code, Claude Desktop, Cursor, Codex, VS Code, Poke and any client with an "MCP URL + header" field connect with the bearer token. Keep the read token in clients that only need to read; hand out the write token deliberately.
|
|
566
|
+
|
|
567
|
+
claude.ai Connectors, ChatGPT and some hosted agents will not take a static header. They want OAuth, which is the next section.
|
|
568
|
+
|
|
569
|
+
### Hosted agents (OAuth)
|
|
570
|
+
|
|
571
|
+
Two more lines in the same `.env` turn wazap into its own OAuth 2.1 server:
|
|
572
|
+
|
|
573
|
+
```bash
|
|
574
|
+
WAZAP_PUBLIC_URL=https://wazap.example.com
|
|
575
|
+
WAZAP_OAUTH_PASSWORD=$(openssl rand -base64 18)
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
Then give an agent nothing but `https://wazap.example.com/mcp`. It finds the
|
|
579
|
+
authorization server at `/.well-known/oauth-protected-resource/mcp`, registers
|
|
580
|
+
itself (RFC 7591, so there is no client id to paste anywhere), and sends you to
|
|
581
|
+
a page on your own host that asks two things: the password above, and whether
|
|
582
|
+
this agent may only read or also send. A refresh token keeps the agent signed
|
|
583
|
+
in until you revoke it; access tokens rotate every 24 hours on their own.
|
|
584
|
+
|
|
585
|
+
Tested against the flow claude.ai, ChatGPT and Poke use: S256 PKCE, public
|
|
586
|
+
clients, `/token` with refresh, `/revoke`. The bearer tokens keep working next
|
|
587
|
+
to it, so a laptop client on a header and a hosted agent on OAuth share one
|
|
588
|
+
server.
|
|
589
|
+
|
|
590
|
+
What to know before exposing it:
|
|
591
|
+
|
|
592
|
+
- `WAZAP_PUBLIC_URL` must be `https` and a bare origin, no path: the
|
|
593
|
+
endpoints live at its root. The password travels to it.
|
|
594
|
+
- The password is the whole identity layer. Use a long one. A consent page
|
|
595
|
+
takes three wrong guesses and is gone; five from one address lock that
|
|
596
|
+
address out for fifteen minutes; twenty from anywhere close the page for
|
|
597
|
+
everyone for fifteen minutes.
|
|
598
|
+
- With OAuth on, `/mcp` never answers an unauthenticated request, whether or
|
|
599
|
+
not a read token is set.
|
|
600
|
+
- Grants live in `<data-dir>/oauth.json` as hashes. Delete the file to sign
|
|
601
|
+
every agent out at once, running server included; `wazap status` lists who
|
|
602
|
+
holds one. Disconnecting an agent on its side revokes its refresh token and
|
|
603
|
+
every access token it minted. A refresh token unused for ninety days is
|
|
604
|
+
dropped.
|
|
605
|
+
- A read grant never sees a write tool, whatever scope the agent requested.
|
|
606
|
+
The radio button on the consent page is the only thing that decides.
|
|
454
607
|
|
|
455
608
|
## Settings
|
|
456
609
|
|
|
@@ -464,6 +617,8 @@ Claude Code, Claude Desktop, Cursor, Codex, VS Code and any client with an "MCP
|
|
|
464
617
|
| `WAZAP_TRANSPORT` | `stdio` | `stdio` or `http`. |
|
|
465
618
|
| `WAZAP_HOST` / `WAZAP_PORT` | `127.0.0.1` / `8766` | HTTP bind address. |
|
|
466
619
|
| `WAZAP_READ_TOKEN` / `WAZAP_WRITE_TOKEN` | unset | HTTP bearer tokens. |
|
|
620
|
+
| `WAZAP_PUBLIC_URL` | unset | The `https` address agents reach the server at. With the password, turns OAuth on. |
|
|
621
|
+
| `WAZAP_OAUTH_PASSWORD` | unset | What the consent page asks for. At least 8 characters. |
|
|
467
622
|
| `WAZAP_NO_UPDATE_CHECK` | `0` | `1` stops `status` asking npm for a newer version. |
|
|
468
623
|
| `WAZAP_TRANSCRIBE` | `off` | `local`, `openai` or `off`. |
|
|
469
624
|
| `WAZAP_TRANSCRIBE_AUTO` | `1` | Transcribe incoming voice notes in the background. |
|
package/dist/auth-state.js
CHANGED
|
@@ -117,6 +117,11 @@ export function readLinkedAccount(dir) {
|
|
|
117
117
|
export function clearAuth(dir) {
|
|
118
118
|
rmSync(dir, { recursive: true, force: true });
|
|
119
119
|
}
|
|
120
|
+
/** Everything a logout deletes: the credentials, and the store they decrypt. */
|
|
121
|
+
export function clearSession(p) {
|
|
122
|
+
clearAuth(p.authDir);
|
|
123
|
+
rmSync(p.storeFile, { force: true });
|
|
124
|
+
}
|
|
120
125
|
const APP_STATE_SYNC_VERSION = "app-state-sync-version";
|
|
121
126
|
/**
|
|
122
127
|
* The same auth state with the app state sync journal held at zero: reads of it
|
package/dist/bridge.js
CHANGED
|
@@ -2,7 +2,7 @@ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
|
2
2
|
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
3
3
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
4
4
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
|
-
import { CallToolRequestSchema, CallToolResultSchema, ListToolsRequestSchema, ListToolsResultSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
5
|
+
import { CallToolRequestSchema, CallToolResultSchema, GetPromptRequestSchema, GetPromptResultSchema, ListPromptsRequestSchema, ListPromptsResultSchema, ListToolsRequestSchema, ListToolsResultSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
6
6
|
import { WAZAP_VERSION } from "./config.js";
|
|
7
7
|
import { readDaemon } from "./daemon.js";
|
|
8
8
|
import { log } from "./logger.js";
|
|
@@ -31,13 +31,18 @@ export async function runBridge(daemon, daemonFile) {
|
|
|
31
31
|
}));
|
|
32
32
|
const caps = client.getServerCapabilities() ?? {};
|
|
33
33
|
const server = new Server(client.getServerVersion() ?? { name: "wazap", version: daemon.version }, {
|
|
34
|
-
// Only what we forward: the daemon has no resources
|
|
35
|
-
//
|
|
36
|
-
|
|
34
|
+
// Only what we forward: the daemon has no resources, and we have no handler
|
|
35
|
+
// for them. The SDK refuses a handler for a capability we did not declare,
|
|
36
|
+
// so the prompts pair is registered under the same condition.
|
|
37
|
+
capabilities: { tools: caps.tools ?? {}, ...(caps.prompts ? { prompts: caps.prompts } : {}) },
|
|
37
38
|
instructions: client.getInstructions(),
|
|
38
39
|
});
|
|
39
40
|
server.setRequestHandler(ListToolsRequestSchema, (req) => client.request({ method: "tools/list", params: req.params }, ListToolsResultSchema));
|
|
40
41
|
server.setRequestHandler(CallToolRequestSchema, (req) => client.request({ method: "tools/call", params: req.params }, CallToolResultSchema));
|
|
42
|
+
if (caps.prompts) {
|
|
43
|
+
server.setRequestHandler(ListPromptsRequestSchema, (req) => client.request({ method: "prompts/list", params: req.params }, ListPromptsResultSchema));
|
|
44
|
+
server.setRequestHandler(GetPromptRequestSchema, (req) => client.request({ method: "prompts/get", params: req.params }, GetPromptResultSchema));
|
|
45
|
+
}
|
|
41
46
|
client.onclose = () => leave(`the session holder (pid ${daemon.pid}) closed the connection`);
|
|
42
47
|
client.onerror = () => leave(`lost the connection to the session holder (pid ${daemon.pid})`);
|
|
43
48
|
// A dead daemon does not close the client: the transport retries its stream and
|