mcp-evolution 0.0.0-stage → 0.8.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.
Files changed (211) hide show
  1. package/CHANGELOG.md +62 -0
  2. package/LICENSE +21 -0
  3. package/README.md +377 -2
  4. package/dist/config.d.ts +23 -0
  5. package/dist/config.js +113 -0
  6. package/dist/config.js.map +1 -0
  7. package/dist/errors.d.ts +8 -0
  8. package/dist/errors.js +15 -0
  9. package/dist/errors.js.map +1 -0
  10. package/dist/evolution-client.d.ts +34 -0
  11. package/dist/evolution-client.js +84 -0
  12. package/dist/evolution-client.js.map +1 -0
  13. package/dist/guards/recipients.d.ts +40 -0
  14. package/dist/guards/recipients.js +135 -0
  15. package/dist/guards/recipients.js.map +1 -0
  16. package/dist/guards/tools.d.ts +16 -0
  17. package/dist/guards/tools.js +154 -0
  18. package/dist/guards/tools.js.map +1 -0
  19. package/dist/http.d.ts +19 -0
  20. package/dist/http.js +103 -0
  21. package/dist/http.js.map +1 -0
  22. package/dist/index.d.ts +2 -0
  23. package/dist/index.js +7 -0
  24. package/dist/index.js.map +1 -0
  25. package/dist/registry.d.ts +36 -0
  26. package/dist/registry.js +68 -0
  27. package/dist/registry.js.map +1 -0
  28. package/dist/schemas.d.ts +4 -0
  29. package/dist/schemas.js +16 -0
  30. package/dist/schemas.js.map +1 -0
  31. package/dist/server.d.ts +5 -0
  32. package/dist/server.js +74 -0
  33. package/dist/server.js.map +1 -0
  34. package/dist/tools/accept-invite.d.ts +2 -0
  35. package/dist/tools/accept-invite.js +23 -0
  36. package/dist/tools/accept-invite.js.map +1 -0
  37. package/dist/tools/archive-chat.d.ts +2 -0
  38. package/dist/tools/archive-chat.js +35 -0
  39. package/dist/tools/archive-chat.js.map +1 -0
  40. package/dist/tools/check-number.d.ts +2 -0
  41. package/dist/tools/check-number.js +25 -0
  42. package/dist/tools/check-number.js.map +1 -0
  43. package/dist/tools/connection-state.d.ts +2 -0
  44. package/dist/tools/connection-state.js +19 -0
  45. package/dist/tools/connection-state.js.map +1 -0
  46. package/dist/tools/create-group.d.ts +2 -0
  47. package/dist/tools/create-group.js +31 -0
  48. package/dist/tools/create-group.js.map +1 -0
  49. package/dist/tools/delete-message.d.ts +2 -0
  50. package/dist/tools/delete-message.js +33 -0
  51. package/dist/tools/delete-message.js.map +1 -0
  52. package/dist/tools/download-media.d.ts +2 -0
  53. package/dist/tools/download-media.js +59 -0
  54. package/dist/tools/download-media.js.map +1 -0
  55. package/dist/tools/fetch-business-profile.d.ts +2 -0
  56. package/dist/tools/fetch-business-profile.js +25 -0
  57. package/dist/tools/fetch-business-profile.js.map +1 -0
  58. package/dist/tools/fetch-invite-code.d.ts +2 -0
  59. package/dist/tools/fetch-invite-code.js +23 -0
  60. package/dist/tools/fetch-invite-code.js.map +1 -0
  61. package/dist/tools/fetch-privacy.d.ts +2 -0
  62. package/dist/tools/fetch-privacy.js +19 -0
  63. package/dist/tools/fetch-privacy.js.map +1 -0
  64. package/dist/tools/fetch-profile-picture.d.ts +2 -0
  65. package/dist/tools/fetch-profile-picture.js +25 -0
  66. package/dist/tools/fetch-profile-picture.js.map +1 -0
  67. package/dist/tools/find-chats.d.ts +2 -0
  68. package/dist/tools/find-chats.js +74 -0
  69. package/dist/tools/find-chats.js.map +1 -0
  70. package/dist/tools/find-contacts.d.ts +2 -0
  71. package/dist/tools/find-contacts.js +74 -0
  72. package/dist/tools/find-contacts.js.map +1 -0
  73. package/dist/tools/find-group-by-invite.d.ts +2 -0
  74. package/dist/tools/find-group-by-invite.js +56 -0
  75. package/dist/tools/find-group-by-invite.js.map +1 -0
  76. package/dist/tools/find-labels.d.ts +2 -0
  77. package/dist/tools/find-labels.js +22 -0
  78. package/dist/tools/find-labels.js.map +1 -0
  79. package/dist/tools/find-messages.d.ts +2 -0
  80. package/dist/tools/find-messages.js +55 -0
  81. package/dist/tools/find-messages.js.map +1 -0
  82. package/dist/tools/find-webhook.d.ts +2 -0
  83. package/dist/tools/find-webhook.js +19 -0
  84. package/dist/tools/find-webhook.js.map +1 -0
  85. package/dist/tools/get-chat-history.d.ts +2 -0
  86. package/dist/tools/get-chat-history.js +55 -0
  87. package/dist/tools/get-chat-history.js.map +1 -0
  88. package/dist/tools/get-group-info.d.ts +2 -0
  89. package/dist/tools/get-group-info.js +58 -0
  90. package/dist/tools/get-group-info.js.map +1 -0
  91. package/dist/tools/get-group-resolved-participants.d.ts +2 -0
  92. package/dist/tools/get-group-resolved-participants.js +170 -0
  93. package/dist/tools/get-group-resolved-participants.js.map +1 -0
  94. package/dist/tools/get-settings.d.ts +2 -0
  95. package/dist/tools/get-settings.js +19 -0
  96. package/dist/tools/get-settings.js.map +1 -0
  97. package/dist/tools/handle-label.d.ts +2 -0
  98. package/dist/tools/handle-label.js +30 -0
  99. package/dist/tools/handle-label.js.map +1 -0
  100. package/dist/tools/index.d.ts +2 -0
  101. package/dist/tools/index.js +131 -0
  102. package/dist/tools/index.js.map +1 -0
  103. package/dist/tools/leave-group.d.ts +2 -0
  104. package/dist/tools/leave-group.js +23 -0
  105. package/dist/tools/leave-group.js.map +1 -0
  106. package/dist/tools/list-groups.d.ts +2 -0
  107. package/dist/tools/list-groups.js +53 -0
  108. package/dist/tools/list-groups.js.map +1 -0
  109. package/dist/tools/list-instances.d.ts +2 -0
  110. package/dist/tools/list-instances.js +37 -0
  111. package/dist/tools/list-instances.js.map +1 -0
  112. package/dist/tools/logout-instance.d.ts +2 -0
  113. package/dist/tools/logout-instance.js +19 -0
  114. package/dist/tools/logout-instance.js.map +1 -0
  115. package/dist/tools/mark-as-read.d.ts +2 -0
  116. package/dist/tools/mark-as-read.js +30 -0
  117. package/dist/tools/mark-as-read.js.map +1 -0
  118. package/dist/tools/remove-profile-picture.d.ts +2 -0
  119. package/dist/tools/remove-profile-picture.js +19 -0
  120. package/dist/tools/remove-profile-picture.js.map +1 -0
  121. package/dist/tools/restart-instance.d.ts +2 -0
  122. package/dist/tools/restart-instance.js +19 -0
  123. package/dist/tools/restart-instance.js.map +1 -0
  124. package/dist/tools/revoke-invite-code.d.ts +2 -0
  125. package/dist/tools/revoke-invite-code.js +23 -0
  126. package/dist/tools/revoke-invite-code.js.map +1 -0
  127. package/dist/tools/send-audio.d.ts +2 -0
  128. package/dist/tools/send-audio.js +32 -0
  129. package/dist/tools/send-audio.js.map +1 -0
  130. package/dist/tools/send-button.d.ts +2 -0
  131. package/dist/tools/send-button.js +43 -0
  132. package/dist/tools/send-button.js.map +1 -0
  133. package/dist/tools/send-contact.d.ts +2 -0
  134. package/dist/tools/send-contact.js +36 -0
  135. package/dist/tools/send-contact.js.map +1 -0
  136. package/dist/tools/send-group-invite.d.ts +2 -0
  137. package/dist/tools/send-group-invite.js +29 -0
  138. package/dist/tools/send-group-invite.js.map +1 -0
  139. package/dist/tools/send-list.d.ts +2 -0
  140. package/dist/tools/send-list.js +47 -0
  141. package/dist/tools/send-list.js.map +1 -0
  142. package/dist/tools/send-location.d.ts +2 -0
  143. package/dist/tools/send-location.js +37 -0
  144. package/dist/tools/send-location.js.map +1 -0
  145. package/dist/tools/send-media.d.ts +2 -0
  146. package/dist/tools/send-media.js +45 -0
  147. package/dist/tools/send-media.js.map +1 -0
  148. package/dist/tools/send-poll.d.ts +2 -0
  149. package/dist/tools/send-poll.js +32 -0
  150. package/dist/tools/send-poll.js.map +1 -0
  151. package/dist/tools/send-presence.d.ts +2 -0
  152. package/dist/tools/send-presence.js +33 -0
  153. package/dist/tools/send-presence.js.map +1 -0
  154. package/dist/tools/send-reaction.d.ts +2 -0
  155. package/dist/tools/send-reaction.js +31 -0
  156. package/dist/tools/send-reaction.js.map +1 -0
  157. package/dist/tools/send-status.d.ts +2 -0
  158. package/dist/tools/send-status.js +40 -0
  159. package/dist/tools/send-status.js.map +1 -0
  160. package/dist/tools/send-sticker.d.ts +2 -0
  161. package/dist/tools/send-sticker.js +28 -0
  162. package/dist/tools/send-sticker.js.map +1 -0
  163. package/dist/tools/send-text.d.ts +2 -0
  164. package/dist/tools/send-text.js +31 -0
  165. package/dist/tools/send-text.js.map +1 -0
  166. package/dist/tools/set-settings.d.ts +2 -0
  167. package/dist/tools/set-settings.js +44 -0
  168. package/dist/tools/set-settings.js.map +1 -0
  169. package/dist/tools/set-webhook.d.ts +2 -0
  170. package/dist/tools/set-webhook.js +39 -0
  171. package/dist/tools/set-webhook.js.map +1 -0
  172. package/dist/tools/update-block-status.d.ts +2 -0
  173. package/dist/tools/update-block-status.js +28 -0
  174. package/dist/tools/update-block-status.js.map +1 -0
  175. package/dist/tools/update-group-description.d.ts +2 -0
  176. package/dist/tools/update-group-description.js +24 -0
  177. package/dist/tools/update-group-description.js.map +1 -0
  178. package/dist/tools/update-group-picture.d.ts +2 -0
  179. package/dist/tools/update-group-picture.js +24 -0
  180. package/dist/tools/update-group-picture.js.map +1 -0
  181. package/dist/tools/update-group-setting.d.ts +2 -0
  182. package/dist/tools/update-group-setting.js +25 -0
  183. package/dist/tools/update-group-setting.js.map +1 -0
  184. package/dist/tools/update-group-subject.d.ts +2 -0
  185. package/dist/tools/update-group-subject.js +24 -0
  186. package/dist/tools/update-group-subject.js.map +1 -0
  187. package/dist/tools/update-participants.d.ts +2 -0
  188. package/dist/tools/update-participants.js +26 -0
  189. package/dist/tools/update-participants.js.map +1 -0
  190. package/dist/tools/update-privacy.d.ts +2 -0
  191. package/dist/tools/update-privacy.js +45 -0
  192. package/dist/tools/update-privacy.js.map +1 -0
  193. package/dist/tools/update-profile-name.d.ts +2 -0
  194. package/dist/tools/update-profile-name.js +25 -0
  195. package/dist/tools/update-profile-name.js.map +1 -0
  196. package/dist/tools/update-profile-picture.d.ts +2 -0
  197. package/dist/tools/update-profile-picture.js +25 -0
  198. package/dist/tools/update-profile-picture.js.map +1 -0
  199. package/dist/tools/update-profile-status.d.ts +2 -0
  200. package/dist/tools/update-profile-status.js +25 -0
  201. package/dist/tools/update-profile-status.js.map +1 -0
  202. package/dist/util/db.d.ts +3 -0
  203. package/dist/util/db.js +23 -0
  204. package/dist/util/db.js.map +1 -0
  205. package/dist/util/normalize.d.ts +44 -0
  206. package/dist/util/normalize.js +68 -0
  207. package/dist/util/normalize.js.map +1 -0
  208. package/dist/util/redact.d.ts +11 -0
  209. package/dist/util/redact.js +54 -0
  210. package/dist/util/redact.js.map +1 -0
  211. package/package.json +53 -4
package/CHANGELOG.md ADDED
@@ -0,0 +1,62 @@
1
+ # Changelog
2
+
3
+ ## 0.8.0 - 2026-10-28
4
+
5
+ ### Added
6
+
7
+ - `docker/` kit: one-command stack with Evolution API + Postgres + Redis + this server in
8
+ HTTP mode (`docker compose --env-file .env up -d --build`), plus `scripts/criar-instancia.sh`
9
+ (creates the instance and saves the pairing QR), `.env.example`, `.dockerignore` and a
10
+ PT-BR deployment guide.
11
+ - Multi-stage `docker/Dockerfile` (Node 22 alpine, non-root `node` user, `/health` healthcheck).
12
+ - `docker/scripts/migracao.ps1`: export/restore the whole stack between machines
13
+ (image, Postgres dump, WhatsApp session volume) as one zip.
14
+ - `docker/scripts/novo-cliente.ps1`: provisions an isolated stack per remote client
15
+ (unique passwords, token, ports, compose project) and prints the MCP URL + token.
16
+ - Cloudflare Tunnel support for home/Windows hosting: `docker-compose.tunnel.yml` overlay,
17
+ `TUNNEL.md` guide and `-TunnelToken`/`-Hostname` flags on `novo-cliente.ps1` (HTTPS without
18
+ opening router ports).
19
+ - Published ports now bind to `127.0.0.1` by default; the tunnel reaches the container over
20
+ the internal compose network.
21
+
22
+ ## 0.7.0
23
+
24
+ ### Added
25
+
26
+ - Streamable HTTP transport: `MCP_TRANSPORT=http` serves MCP over HTTP (stateless) so clients
27
+ connect by URL. Requires `MCP_AUTH_TOKEN` (Bearer, min. 32 chars, constant-time check).
28
+ Also `PORT`, `HOST`, `MCP_HTTP_PATH`; `GET /health` answers without auth. stdio stays the default.
29
+ - `*@g.us` in `EVOLUTION_ALLOWED_RECIPIENTS` admits every group (reading and sending) while
30
+ direct chats stay limited to the listed numbers.
31
+
32
+ ## 0.6.0
33
+
34
+ ### BREAKING CHANGES
35
+
36
+ - **Dangerous tools are disabled by default.** They are only registered when named in
37
+ `EVOLUTION_ALLOWED_TOOLS` (or enabled with the `@dangerous` group): `send_status`,
38
+ `delete_message`, `update_privacy`, `update_profile_name`, `update_profile_status`,
39
+ `update_profile_picture`, `remove_profile_picture`, `update_block_status`, `create_group`,
40
+ `update_group_subject`, `update_group_description`, `update_group_picture`,
41
+ `update_group_setting`, `update_participants`, `revoke_invite_code`, `accept_invite`,
42
+ `leave_group`, `restart_instance`, `logout_instance`, `set_settings`, `set_webhook`.
43
+ To restore the previous behaviour: `EVOLUTION_ALLOWED_TOOLS=@default,@dangerous`.
44
+ - Setting both `EVOLUTION_INSTANCE` and `EVOLUTION_INSTANCES` is a startup error.
45
+ - `find_messages` / `get_chat_history` now error on an unrecognised Evolution response
46
+ instead of silently returning an empty list.
47
+
48
+ ### Added
49
+
50
+ - Multiple instances: `EVOLUTION_INSTANCES` (comma list) and `EVOLUTION_DEFAULT_INSTANCE`.
51
+ With more than one instance every tool accepts an optional `instance` (validated against the list).
52
+ - `list_instances` tool (names, default, optional connection state).
53
+ - `EVOLUTION_ALLOWED_TOOLS` with groups `@read`, `@send`, `@default`, `@dangerous`.
54
+ - `EVOLUTION_ALLOWED_RECIPIENTS` and per-instance `EVOLUTION_ALLOWED_RECIPIENTS__<INSTANCE>`;
55
+ listing tools are filtered to the allowlist.
56
+ - Secret redaction (API key, Basic Auth, URL passwords) in every result/error sent to the client.
57
+
58
+ ### Fixed
59
+
60
+ - `find_messages` / `get_chat_history` read Evolution v2 paginated envelopes (`messages.records`).
61
+ - `get_group_resolved_participants` scopes its DB query to the selected instance.
62
+ - Server reports the real package version.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Billy Franklim
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,378 @@
1
- # Temporary Holding Version
1
+ # mcp-evolution
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ [![npm version](https://img.shields.io/npm/v/mcp-evolution.svg)](https://www.npmjs.com/package/mcp-evolution)
4
+ [![license](https://img.shields.io/npm/l/mcp-evolution.svg)](./LICENSE)
5
+ [![CI](https://github.com/billyfranklim1/mcp-evolution/actions/workflows/ci.yml/badge.svg)](https://github.com/billyfranklim1/mcp-evolution/actions/workflows/ci.yml)
6
+
7
+ TypeScript MCP server for [Evolution API](https://github.com/EvolutionAPI/evolution-api) (WhatsApp) with an instance allowlist and server-side guards (tool allowlist, recipient allowlist, secret redaction).
8
+
9
+ ## Architecture
10
+
11
+ This server implements the [Model Context Protocol](https://modelcontextprotocol.io):
12
+
13
+ - **Transport**: stdio — the MCP host (Claude Desktop, Claude Code, etc.) spawns this process and speaks JSON-RPC over stdin/stdout.
14
+ - **Server**: uses the high-level `McpServer` class from the official TypeScript SDK, which handles capability negotiation and session lifecycle automatically.
15
+ - **Tools**: 55 tools registered via `registerTool()` with Zod-validated input schemas — the SDK enforces types before the handler runs.
16
+ - **Guards**: every tool goes through a registry that enforces the tool allowlist, the instance allowlist and the recipient allowlist, and redacts secrets from everything returned to the client.
17
+
18
+ The API URL, API key and the set of allowed instances are fixed at startup via environment variables. The AI caller can only pick an instance **from that list** — it can never address an instance outside it.
19
+
20
+ ## Tools
21
+
22
+ Tools marked **(D)** are [dangerous](#dangerous-tools-disabled-by-default) and disabled unless explicitly enabled.
23
+
24
+ ### Instances
25
+
26
+ | Tool | Description |
27
+ |------|-------------|
28
+ | `list_instances` | List the allowed instances (names only), the default one and, optionally, each connection state |
29
+
30
+ ### Message
31
+
32
+ | Tool | Description |
33
+ |------|-------------|
34
+ | `send_text` | Send a plain text message |
35
+ | `send_media` | Send an image, video, audio, or document |
36
+ | `send_audio` | Send a WhatsApp audio (PTT voice note) |
37
+ | `send_sticker` | Send a sticker (webp) |
38
+ | `send_location` | Send a location pin |
39
+ | `send_contact` | Share one or more contacts (vCards) |
40
+ | `send_reaction` | React to a message with an emoji |
41
+ | `send_poll` | Send a poll message |
42
+ | `send_list` | Send an interactive list/menu message |
43
+ | `send_button` | Send an interactive button message |
44
+ | `send_status` (D) | Post a WhatsApp Status (story) update |
45
+
46
+ ### Chat
47
+
48
+ | Tool | Description |
49
+ |------|-------------|
50
+ | `find_chats` | Find chats, optionally filtered with a Prisma-style `where` clause |
51
+ | `find_contacts` | Find contacts, optionally filtered |
52
+ | `find_messages` | Find messages by remoteJid with optional limit |
53
+ | `get_chat_history` | Get message history for a contact or group JID |
54
+ | `mark_as_read` | Mark one or more messages as read |
55
+ | `archive_chat` | Archive or unarchive a chat |
56
+ | `delete_message` (D) | Delete a message for everyone |
57
+ | `fetch_profile_picture` | Fetch a contact's profile picture URL |
58
+ | `download_media` | Download media from a message to a local file |
59
+ | `send_presence` | Send a presence update (typing, recording, etc.) |
60
+ | `check_number` | Check whether phone numbers have WhatsApp accounts |
61
+
62
+ ### Profile
63
+
64
+ | Tool | Description |
65
+ |------|-------------|
66
+ | `fetch_business_profile` | Fetch a contact's WhatsApp Business profile |
67
+ | `update_profile_name` (D) | Update the instance's display name |
68
+ | `update_profile_status` (D) | Update the instance's about/status text |
69
+ | `update_profile_picture` (D) | Update the instance's profile picture |
70
+ | `remove_profile_picture` (D) | Remove the instance's profile picture |
71
+ | `fetch_privacy` | Fetch current privacy settings |
72
+ | `update_privacy` (D) | Update privacy settings |
73
+ | `update_block_status` (D) | Block or unblock a contact |
74
+
75
+ ### Group
76
+
77
+ | Tool | Description |
78
+ |------|-------------|
79
+ | `list_groups` | List all WhatsApp groups for the selected instance |
80
+ | `get_group_info` | Get detailed info for a specific group by JID |
81
+ | `create_group` (D) | Create a new WhatsApp group |
82
+ | `update_group_subject` (D) | Update a group's name |
83
+ | `update_group_description` (D) | Update a group's description |
84
+ | `update_group_picture` (D) | Update a group's profile picture |
85
+ | `fetch_invite_code` | Fetch the invite code/link for a group |
86
+ | `revoke_invite_code` (D) | Revoke and regenerate a group's invite code |
87
+ | `accept_invite` (D) | Accept a group invite by code |
88
+ | `send_group_invite` | Send a group invite link to specific contacts |
89
+ | `update_participants` (D) | Add, remove, promote, or demote group participants |
90
+ | `update_group_setting` (D) | Update group settings (announcement mode, locked) |
91
+ | `leave_group` (D) | Leave a group |
92
+ | `find_group_by_invite` | Get group info from an invite code without joining |
93
+
94
+ ### Instance
95
+
96
+ | Tool | Description |
97
+ |------|-------------|
98
+ | `connection_state` | Get the current connection state of the instance |
99
+ | `restart_instance` (D) | Restart the instance (reconnects without logging out) |
100
+ | `logout_instance` (D) | Logout the instance (clears session) |
101
+ | `get_settings` | Get current instance settings |
102
+ | `set_settings` (D) | Update instance settings |
103
+
104
+ ### Webhook
105
+
106
+ | Tool | Description |
107
+ |------|-------------|
108
+ | `find_webhook` | Get the current webhook configuration |
109
+ | `set_webhook` (D) | Configure the webhook |
110
+
111
+ ### Label
112
+
113
+ | Tool | Description |
114
+ |------|-------------|
115
+ | `find_labels` | List all labels (requires WhatsApp Business) |
116
+ | `handle_label` | Add or remove a label from a chat |
117
+
118
+ ## Install & run via npx
119
+
120
+ ```bash
121
+ EVOLUTION_API_URL=http://localhost:8080 \
122
+ EVOLUTION_API_KEY=your-key \
123
+ EVOLUTION_INSTANCE=your-instance \
124
+ npx mcp-evolution
125
+ ```
126
+
127
+ ## Configuration
128
+
129
+ | Variable | Required | Description |
130
+ |----------|----------|-------------|
131
+ | `EVOLUTION_API_URL` | Yes | Base URL of your Evolution API (e.g. `http://localhost:8080`) |
132
+ | `EVOLUTION_API_KEY` | Yes | Global API key from Evolution API config |
133
+ | `EVOLUTION_INSTANCE` | One of these two | Single instance name (legacy / simplest mode) |
134
+ | `EVOLUTION_INSTANCES` | One of these two | Comma-separated list of allowed instances, e.g. `personal,support` |
135
+ | `EVOLUTION_DEFAULT_INSTANCE` | No | Instance used when a call omits `instance` (must be in `EVOLUTION_INSTANCES`) |
136
+ | `EVOLUTION_ALLOWED_TOOLS` | No | Comma-separated tool names and/or groups. Unset = every non-dangerous tool |
137
+ | `EVOLUTION_ALLOWED_RECIPIENTS` | No | Comma-separated recipient allowlist (numbers, JIDs, LIDs, group JIDs). Unset = unrestricted |
138
+ | `EVOLUTION_ALLOWED_RECIPIENTS__<INSTANCE>` | No | Per-instance recipient allowlist; overrides the global one for that instance |
139
+ | `EVOLUTION_BASIC_AUTH` | No | Base64 `user:password` sent as `Authorization: Basic …` (e.g. nginx in front of Evolution) |
140
+ | `EVOLUTION_DB_URL` | No | Evolution Postgres URL, only for `get_group_resolved_participants` |
141
+
142
+ Invalid configuration (unknown tool names, default instance outside the list, both `EVOLUTION_INSTANCE` and `EVOLUTION_INSTANCES` set, malformed recipients…) aborts at startup with a message that never includes secret values.
143
+
144
+ ### Instances
145
+
146
+ - **One instance** (`EVOLUTION_INSTANCE=foo`, or `EVOLUTION_INSTANCES=foo`): works exactly like before — no `instance` parameter is added and every call goes to `foo`.
147
+ - **Several instances** (`EVOLUTION_INSTANCES=foo,bar`): every instance-bound tool gets an optional `instance` parameter, validated against the list (a zod `enum`). Omitted → `EVOLUTION_DEFAULT_INSTANCE`; if no default is set the call fails asking for `instance`. Any value outside the list is rejected before any HTTP request is made.
148
+ - `list_instances` returns the configured names and which one is the default; `includeState: true` also queries each connection state.
149
+
150
+ ### Tool allowlist — `EVOLUTION_ALLOWED_TOOLS`
151
+
152
+ When set, **only** the listed tools are registered; everything else does not even show up in `tools/list`. Entries are tool names or groups:
153
+
154
+ | Group | Tools |
155
+ |-------|-------|
156
+ | `@read` | `list_instances`, `connection_state`, `list_groups`, `find_chats`, `find_contacts`, `find_messages`, `find_labels`, `find_webhook`, `find_group_by_invite`, `get_chat_history`, `get_group_info`, `get_group_resolved_participants`, `get_settings`, `check_number`, `download_media`, `fetch_business_profile`, `fetch_invite_code`, `fetch_privacy`, `fetch_profile_picture` |
157
+ | `@send` | `send_text`, `send_media`, `send_audio`, `send_presence`, `mark_as_read` |
158
+ | `@default` | every tool except the dangerous ones (what you get when the variable is unset) |
159
+ | `@dangerous` | every dangerous tool (see below) |
160
+
161
+ Examples: `@read,@send` · `@read,send_text` · `@default,send_status`.
162
+
163
+ ### Dangerous tools (disabled by default)
164
+
165
+ These tools change account/group state irreversibly, broadcast, or can redirect traffic. They are **not registered** unless named explicitly in `EVOLUTION_ALLOWED_TOOLS` (or via `@dangerous`):
166
+
167
+ | Tool | Why |
168
+ |------|-----|
169
+ | `send_status` | Broadcasts to all contacts; known to disconnect every linked device ([evolution-api#2196](https://github.com/EvolutionAPI/evolution-api/issues/2196)) |
170
+ | `delete_message` | Deletes messages for everyone |
171
+ | `update_privacy` | Changes account privacy |
172
+ | `update_profile_name`, `update_profile_status`, `update_profile_picture`, `remove_profile_picture` | Change the public profile |
173
+ | `update_block_status` | Blocks/unblocks contacts |
174
+ | `create_group`, `update_group_subject`, `update_group_description`, `update_group_picture`, `update_group_setting`, `update_participants`, `revoke_invite_code`, `accept_invite`, `leave_group` | Change group state/membership |
175
+ | `restart_instance`, `logout_instance` | Disrupt or destroy the WhatsApp session |
176
+ | `set_settings` | Changes instance behaviour (auto-read, reject calls, always online…) |
177
+ | `set_webhook` | Can redirect every incoming event to an arbitrary URL |
178
+
179
+ To re-enable, list them: `EVOLUTION_ALLOWED_TOOLS=@default,send_status,delete_message` (or `@default,@dangerous` for the pre-0.6 behaviour).
180
+
181
+ ### Recipient allowlist — `EVOLUTION_ALLOWED_RECIPIENTS`
182
+
183
+ When set, any tool argument that identifies a chat — `number`, `numbers[]`, `remoteJid`, `jid`, `groupJid`, `chat`, `participants[]`, `statusJidList[]`, including nested ones such as `readMessages[].remoteJid` or `key.remoteJid` — must match the list, otherwise the call is rejected before reaching Evolution (the error names the rejected value, never the list). In addition:
184
+
185
+ - `find_chats`, `find_contacts` and `list_groups` only return entries in the list; `find_group_by_invite` refuses groups outside it.
186
+ - `send_status` requires an explicit `statusJidList`; `accept_invite` is refused.
187
+
188
+ Matching normalises both sides to digits of the part before `@` (dropping a `:device` suffix). Accepted forms: `5511999999999`, `+55 (11) 99999-9999`, `5511999999999@s.whatsapp.net`, `…@c.us`, `123456789012345@lid`, `120363…@g.us`. A LID is a different identifier from the phone number — if a contact reaches you as `@lid`, list that LID too. Write Brazilian mobiles in full (`55 DD 9XXXXXXXX`); legacy JIDs without the extra `9` then match as well.
189
+
190
+ **All groups:** add `*@g.us` to admit every group (any `…@g.us` JID, for reading and sending) while direct chats stay limited to the numbers you list, e.g. `5511999999999,*@g.us`. Groups must then be addressed by their full `@g.us` JID.
191
+
192
+ **Per instance:** `EVOLUTION_ALLOWED_RECIPIENTS__<INSTANCE>` replaces the global list for that instance. `<INSTANCE>` is the instance name upper-cased with every character outside `A-Z0-9` replaced by `_` (e.g. `billy-franklim.2` → `EVOLUTION_ALLOWED_RECIPIENTS__BILLY_FRANKLIM_2`). Use `*` as the value to leave one instance unrestricted while a global list applies to the others.
193
+
194
+ ### Secret redaction
195
+
196
+ The API key, `EVOLUTION_BASIC_AUTH` (both the base64 value and the decoded `user:password`/password) and passwords embedded in `EVOLUTION_API_URL`/`EVOLUTION_DB_URL` are replaced by `[REDACTED]` in every tool result and error returned to the MCP client, including Evolution error bodies that echo request headers.
197
+
198
+ ## Use with Claude Code / Claude Desktop
199
+
200
+ Keep secrets out of the MCP JSON by putting them in an env file and loading it with Node's `--env-file` (Node ≥ 20.6):
201
+
202
+ ```bash
203
+ # /path/to/credentials.env (chmod 600)
204
+ EVOLUTION_API_URL=https://evolution.example.com
205
+ EVOLUTION_API_KEY=...
206
+ EVOLUTION_BASIC_AUTH=...
207
+ ```
208
+
209
+ Single instance, read + basic send, one test recipient (`.mcp.json` or `claude mcp add-json`):
210
+
211
+ ```json
212
+ {
213
+ "mcpServers": {
214
+ "whatsapp": {
215
+ "command": "node",
216
+ "args": [
217
+ "--env-file=/path/to/credentials.env",
218
+ "/absolute/path/to/mcp-evolution/dist/index.js"
219
+ ],
220
+ "env": {
221
+ "EVOLUTION_INSTANCE": "my-instance",
222
+ "EVOLUTION_ALLOWED_TOOLS": "@read,@send",
223
+ "EVOLUTION_ALLOWED_RECIPIENTS": "5511999999999"
224
+ }
225
+ }
226
+ }
227
+ }
228
+ ```
229
+
230
+ Several instances with a default and per-instance recipients:
231
+
232
+ ```json
233
+ {
234
+ "mcpServers": {
235
+ "whatsapp": {
236
+ "command": "node",
237
+ "args": ["--env-file=/path/to/credentials.env", "/absolute/path/to/mcp-evolution/dist/index.js"],
238
+ "env": {
239
+ "EVOLUTION_INSTANCES": "personal,support",
240
+ "EVOLUTION_DEFAULT_INSTANCE": "personal",
241
+ "EVOLUTION_ALLOWED_TOOLS": "@read,@send",
242
+ "EVOLUTION_ALLOWED_RECIPIENTS__PERSONAL": "5511999999999,123456789012345@lid",
243
+ "EVOLUTION_ALLOWED_RECIPIENTS__SUPPORT": "*"
244
+ }
245
+ }
246
+ }
247
+ }
248
+ ```
249
+
250
+ If a variable is defined both in `env` and in the file, Node keeps the value from `env` (the process environment wins). Keep secrets in the file and the guards in the JSON, where they are easy to review. With `npx` (`"command": "npx", "args": ["mcp-evolution"]`) there is no `--env-file`, so every variable has to go in `env`.
251
+
252
+ ## Run as a remote server (Streamable HTTP)
253
+
254
+ Set `MCP_TRANSPORT=http` to serve MCP over HTTP instead of stdio, so clients connect by URL and nothing runs on their machine. The server is stateless: each request gets a fresh MCP server with the same guards.
255
+
256
+ | Variable | Default | Notes |
257
+ |---|---|---|
258
+ | `MCP_TRANSPORT` | `stdio` | `stdio` or `http` |
259
+ | `MCP_AUTH_TOKEN` | — | **Required** in HTTP mode, at least 32 characters. Clients send `Authorization: Bearer <token>` |
260
+ | `PORT` | `3000` | |
261
+ | `HOST` | `0.0.0.0` | Use `127.0.0.1` behind a reverse proxy |
262
+ | `MCP_HTTP_PATH` | `/mcp` | |
263
+
264
+ `GET /health` answers without auth for uptime checks. Put the server behind HTTPS (nginx, Caddy) and keep the guards (`EVOLUTION_ALLOWED_TOOLS`, `EVOLUTION_ALLOWED_RECIPIENTS`) in its environment: the token only proves who is calling, the guards still decide what they can do.
265
+
266
+ Register it in Claude Code:
267
+
268
+ ```bash
269
+ claude mcp add --transport http evolution https://your-host/mcp --header "Authorization: Bearer $MCP_AUTH_TOKEN"
270
+ ```
271
+
272
+ ## Development
273
+
274
+ ```bash
275
+ # Install dependencies
276
+ npm install
277
+
278
+ # Run in dev mode (no build step)
279
+ npm run dev
280
+
281
+ # Build TypeScript → dist/
282
+ npm run build
283
+
284
+ # Run tests
285
+ npm test
286
+
287
+ # Start from built output
288
+ npm start
289
+ ```
290
+
291
+ ## Evolution API endpoints wrapped
292
+
293
+ | Tool | Method | Path |
294
+ |------|--------|------|
295
+ | `send_text` | POST | `/message/sendText/{instance}` |
296
+ | `send_media` | POST | `/message/sendMedia/{instance}` |
297
+ | `send_audio` | POST | `/message/sendWhatsAppAudio/{instance}` |
298
+ | `send_sticker` | POST | `/message/sendSticker/{instance}` |
299
+ | `send_location` | POST | `/message/sendLocation/{instance}` |
300
+ | `send_contact` | POST | `/message/sendContact/{instance}` |
301
+ | `send_reaction` | POST | `/message/sendReaction/{instance}` |
302
+ | `send_poll` | POST | `/message/sendPoll/{instance}` |
303
+ | `send_list` | POST | `/message/sendList/{instance}` |
304
+ | `send_button` | POST | `/message/sendButtons/{instance}` |
305
+ | `send_status` | POST | `/message/sendStatus/{instance}` |
306
+ | `find_chats` | POST | `/chat/findChats/{instance}` |
307
+ | `find_contacts` | POST | `/chat/findContacts/{instance}` |
308
+ | `find_messages` / `get_chat_history` | POST | `/chat/findMessages/{instance}` |
309
+ | `mark_as_read` | POST | `/chat/markMessageAsRead/{instance}` |
310
+ | `archive_chat` | POST | `/chat/archiveChat/{instance}` |
311
+ | `delete_message` | DELETE | `/chat/deleteMessageForEveryone/{instance}` |
312
+ | `fetch_profile_picture` | POST | `/chat/fetchProfilePictureUrl/{instance}` |
313
+ | `download_media` | POST | `/chat/getBase64FromMediaMessage/{instance}` |
314
+ | `send_presence` | POST | `/chat/sendPresence/{instance}` |
315
+ | `check_number` | POST | `/chat/whatsappNumbers/{instance}` |
316
+ | `fetch_business_profile` | POST | `/chat/fetchBusinessProfile/{instance}` |
317
+ | `update_profile_name` | POST | `/chat/updateProfileName/{instance}` |
318
+ | `update_profile_status` | POST | `/chat/updateProfileStatus/{instance}` |
319
+ | `update_profile_picture` | POST | `/chat/updateProfilePicture/{instance}` |
320
+ | `remove_profile_picture` | DELETE | `/chat/removeProfilePicture/{instance}` |
321
+ | `fetch_privacy` | GET | `/chat/fetchPrivacySettings/{instance}` |
322
+ | `update_privacy` | POST | `/chat/updatePrivacySettings/{instance}` |
323
+ | `update_block_status` | POST | `/chat/updateBlockStatus/{instance}` |
324
+ | `list_groups` | GET | `/group/fetchAllGroups/{instance}` |
325
+ | `get_group_info` | GET | `/group/findGroupInfos/{instance}` |
326
+ | `create_group` | POST | `/group/create/{instance}` |
327
+ | `update_group_subject` | POST | `/group/updateGroupSubject/{instance}?groupJid=` |
328
+ | `update_group_description` | POST | `/group/updateGroupDescription/{instance}?groupJid=` |
329
+ | `update_group_picture` | POST | `/group/updateGroupPicture/{instance}?groupJid=` |
330
+ | `fetch_invite_code` | GET | `/group/inviteCode/{instance}?groupJid=` |
331
+ | `revoke_invite_code` | POST | `/group/revokeInviteCode/{instance}?groupJid=` |
332
+ | `accept_invite` | GET | `/group/acceptInviteCode/{instance}?inviteCode=` |
333
+ | `send_group_invite` | POST | `/group/sendInvite/{instance}` |
334
+ | `update_participants` | POST | `/group/updateParticipant/{instance}?groupJid=` |
335
+ | `update_group_setting` | POST | `/group/updateSetting/{instance}?groupJid=` |
336
+ | `leave_group` | DELETE | `/group/leaveGroup/{instance}?groupJid=` |
337
+ | `find_group_by_invite` | GET | `/group/inviteInfo/{instance}?inviteCode=` |
338
+ | `connection_state` / `list_instances` | GET | `/instance/connectionState/{instance}` |
339
+ | `restart_instance` | POST | `/instance/restart/{instance}` |
340
+ | `logout_instance` | DELETE | `/instance/logout/{instance}` |
341
+ | `get_settings` | GET | `/settings/find/{instance}` |
342
+ | `set_settings` | POST | `/settings/set/{instance}` |
343
+ | `find_webhook` | GET | `/webhook/find/{instance}` |
344
+ | `set_webhook` | POST | `/webhook/set/{instance}` |
345
+ | `find_labels` | GET | `/label/findLabels/{instance}` |
346
+ | `handle_label` | POST | `/label/handleLabel/{instance}` |
347
+
348
+ Requires Evolution API v2.
349
+
350
+ ## Docker — kit completo (Evolution + Postgres + Redis + servidor MCP)
351
+
352
+ The `docker/` folder ships a ready-to-run stack:
353
+
354
+ ```bash
355
+ cd docker
356
+ cp .env.example .env # fill in POSTGRES_PASSWORD, EVOLUTION_API_KEY, MCP_AUTH_TOKEN, EVOLUTION_INSTANCE
357
+ docker compose --env-file .env up -d --build
358
+ ```
359
+
360
+ Services: `postgres:15-alpine`, `redis:7-alpine`, `evoapicloud/evolution-api` (port 8080)
361
+ and this MCP server in HTTP mode (port 8930, `GET /health`, Bearer-protected `/mcp`).
362
+
363
+ Then create the WhatsApp instance and pair a phone:
364
+
365
+ ```bash
366
+ sh scripts/criar-instancia.sh # writes qrcode-instancia.png
367
+ ```
368
+
369
+ Full step-by-step (PT-BR), client configuration examples and troubleshooting:
370
+ [docker/README.md](docker/README.md).
371
+
372
+ ## License
373
+
374
+ MIT — see [LICENSE](LICENSE).
375
+
376
+ ## Disclaimer
377
+
378
+ Community software, not affiliated with Evolution API or any WhatsApp entity.
@@ -0,0 +1,23 @@
1
+ import { ConfigError } from "./errors.js";
2
+ import { type RecipientRule } from "./guards/recipients.js";
3
+ export { ConfigError };
4
+ export interface Config {
5
+ apiUrl: string;
6
+ apiKey: string;
7
+ basicAuth?: string;
8
+ dbUrl?: string;
9
+ /** Allowlist of instances this process may talk to (never empty). */
10
+ instances: readonly string[];
11
+ /** Instance used when a tool call does not pass `instance` (undefined = caller must choose). */
12
+ defaultInstance?: string;
13
+ /** Tool names that will be registered. */
14
+ allowedTools: ReadonlySet<string>;
15
+ /** Global recipient rule (undefined = unrestricted). */
16
+ globalRecipients?: RecipientRule;
17
+ /** Per-instance overrides from EVOLUTION_ALLOWED_RECIPIENTS__<INSTANCE>. */
18
+ instanceRecipients: ReadonlyMap<string, RecipientRule>;
19
+ }
20
+ /** Parse and validate configuration from an env object. Throws ConfigError. */
21
+ export declare function loadConfig(env?: NodeJS.ProcessEnv): Config;
22
+ /** CLI entrypoint helper: exits the process on invalid config. */
23
+ export declare function parseConfig(): Config;
package/dist/config.js ADDED
@@ -0,0 +1,113 @@
1
+ import { z } from "zod";
2
+ import { ConfigError } from "./errors.js";
3
+ import { resolveAllowedTools } from "./guards/tools.js";
4
+ import { parseRecipientList, recipientEnvName } from "./guards/recipients.js";
5
+ export { ConfigError };
6
+ const BaseSchema = z.object({
7
+ EVOLUTION_API_URL: z.string().url("EVOLUTION_API_URL must be a valid URL"),
8
+ EVOLUTION_API_KEY: z.string().min(1, "EVOLUTION_API_KEY is required"),
9
+ EVOLUTION_INSTANCE: z.string().optional(),
10
+ EVOLUTION_INSTANCES: z.string().optional(),
11
+ EVOLUTION_DEFAULT_INSTANCE: z.string().optional(),
12
+ EVOLUTION_BASIC_AUTH: z.string().min(1).optional(),
13
+ EVOLUTION_DB_URL: z.string().url().optional(),
14
+ EVOLUTION_ALLOWED_TOOLS: z.string().optional(),
15
+ EVOLUTION_ALLOWED_RECIPIENTS: z.string().optional(),
16
+ });
17
+ function blankToUndefined(v) {
18
+ const t = v?.trim();
19
+ return t ? t : undefined;
20
+ }
21
+ function splitList(v) {
22
+ return v
23
+ .split(",")
24
+ .map((s) => s.trim())
25
+ .filter(Boolean);
26
+ }
27
+ /** Parse and validate configuration from an env object. Throws ConfigError. */
28
+ export function loadConfig(env = process.env) {
29
+ const cleaned = {};
30
+ for (const key of Object.keys(BaseSchema.shape))
31
+ cleaned[key] = blankToUndefined(env[key]);
32
+ const parsed = BaseSchema.safeParse(cleaned);
33
+ if (!parsed.success) {
34
+ const issues = parsed.error.issues.map((i) => ` - ${i.path.join(".")}: ${i.message}`).join("\n");
35
+ throw new ConfigError(`Missing or invalid environment variables:\n${issues}`);
36
+ }
37
+ const e = parsed.data;
38
+ // ── Instances ──────────────────────────────────────────────────────────────
39
+ let instances;
40
+ if (e.EVOLUTION_INSTANCES) {
41
+ if (e.EVOLUTION_INSTANCE) {
42
+ throw new ConfigError("Set either EVOLUTION_INSTANCE (single instance) or EVOLUTION_INSTANCES (list), not both. " +
43
+ "Use EVOLUTION_DEFAULT_INSTANCE to pick a default among EVOLUTION_INSTANCES.");
44
+ }
45
+ instances = [...new Set(splitList(e.EVOLUTION_INSTANCES))];
46
+ }
47
+ else if (e.EVOLUTION_INSTANCE) {
48
+ instances = [e.EVOLUTION_INSTANCE];
49
+ }
50
+ else {
51
+ throw new ConfigError("EVOLUTION_INSTANCE or EVOLUTION_INSTANCES is required");
52
+ }
53
+ if (instances.length === 0)
54
+ throw new ConfigError("EVOLUTION_INSTANCES must list at least one instance");
55
+ for (const name of instances) {
56
+ if (/[/?#\s]/.test(name))
57
+ throw new ConfigError(`Invalid instance name "${name}" (no '/', '?', '#' or spaces)`);
58
+ }
59
+ let defaultInstance;
60
+ if (e.EVOLUTION_DEFAULT_INSTANCE) {
61
+ if (!instances.includes(e.EVOLUTION_DEFAULT_INSTANCE)) {
62
+ throw new ConfigError("EVOLUTION_DEFAULT_INSTANCE must be one of the configured instances");
63
+ }
64
+ defaultInstance = e.EVOLUTION_DEFAULT_INSTANCE;
65
+ }
66
+ else if (instances.length === 1) {
67
+ defaultInstance = instances[0];
68
+ }
69
+ // ── Tools ──────────────────────────────────────────────────────────────────
70
+ const allowedTools = resolveAllowedTools(e.EVOLUTION_ALLOWED_TOOLS);
71
+ // ── Recipients ─────────────────────────────────────────────────────────────
72
+ const globalRecipients = e.EVOLUTION_ALLOWED_RECIPIENTS
73
+ ? parseRecipientList(e.EVOLUTION_ALLOWED_RECIPIENTS, "EVOLUTION_ALLOWED_RECIPIENTS")
74
+ : undefined;
75
+ const instanceRecipients = new Map();
76
+ const seenEnvNames = new Map();
77
+ for (const name of instances) {
78
+ const envName = recipientEnvName(name);
79
+ const clash = seenEnvNames.get(envName);
80
+ if (clash) {
81
+ throw new ConfigError(`Instances "${clash}" and "${name}" map to the same variable ${envName}; rename one of them`);
82
+ }
83
+ seenEnvNames.set(envName, name);
84
+ const raw = blankToUndefined(env[envName]);
85
+ if (raw)
86
+ instanceRecipients.set(name, parseRecipientList(raw, envName));
87
+ }
88
+ return {
89
+ apiUrl: e.EVOLUTION_API_URL,
90
+ apiKey: e.EVOLUTION_API_KEY,
91
+ basicAuth: e.EVOLUTION_BASIC_AUTH,
92
+ dbUrl: e.EVOLUTION_DB_URL,
93
+ instances,
94
+ defaultInstance,
95
+ allowedTools,
96
+ globalRecipients,
97
+ instanceRecipients,
98
+ };
99
+ }
100
+ /** CLI entrypoint helper: exits the process on invalid config. */
101
+ export function parseConfig() {
102
+ try {
103
+ return loadConfig(process.env);
104
+ }
105
+ catch (err) {
106
+ if (err instanceof ConfigError) {
107
+ console.error(`[mcp-evolution] ${err.message}`);
108
+ process.exit(1);
109
+ }
110
+ throw err;
111
+ }
112
+ }
113
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /** Thrown for invalid configuration. Messages never include secret values. */
2
+ export declare class ConfigError extends Error {
3
+ constructor(message: string);
4
+ }
5
+ /** Thrown when a tool call is rejected by a guard (instance or recipient allowlist). */
6
+ export declare class GuardError extends Error {
7
+ constructor(message: string);
8
+ }
package/dist/errors.js ADDED
@@ -0,0 +1,15 @@
1
+ /** Thrown for invalid configuration. Messages never include secret values. */
2
+ export class ConfigError extends Error {
3
+ constructor(message) {
4
+ super(message);
5
+ this.name = "ConfigError";
6
+ }
7
+ }
8
+ /** Thrown when a tool call is rejected by a guard (instance or recipient allowlist). */
9
+ export class GuardError extends Error {
10
+ constructor(message) {
11
+ super(message);
12
+ this.name = "GuardError";
13
+ }
14
+ }
15
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,MAAM,OAAO,WAAY,SAAQ,KAAK;IACpC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF;AAED,wFAAwF;AACxF,MAAM,OAAO,UAAW,SAAQ,KAAK;IACnC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;IAC3B,CAAC;CACF"}