@botozap/mcp 0.1.0 → 0.2.1

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 (44) hide show
  1. package/README.md +111 -43
  2. package/dist/event-bus.d.ts +14 -0
  3. package/dist/event-bus.js +128 -0
  4. package/dist/event-bus.js.map +1 -0
  5. package/dist/http.d.ts +31 -0
  6. package/dist/http.js +280 -0
  7. package/dist/http.js.map +1 -0
  8. package/dist/index.js +47 -4
  9. package/dist/index.js.map +1 -1
  10. package/dist/register.d.ts +18 -4
  11. package/dist/register.js +82 -17
  12. package/dist/register.js.map +1 -1
  13. package/dist/resources/events.d.ts +12 -0
  14. package/dist/resources/events.js +192 -0
  15. package/dist/resources/events.js.map +1 -0
  16. package/dist/schemas.d.ts +4405 -0
  17. package/dist/schemas.js +332 -0
  18. package/dist/schemas.js.map +1 -0
  19. package/dist/server.d.ts +7 -0
  20. package/dist/server.js +13 -2
  21. package/dist/server.js.map +1 -1
  22. package/dist/tools/contacts.d.ts +1 -1
  23. package/dist/tools/contacts.js +8 -6
  24. package/dist/tools/contacts.js.map +1 -1
  25. package/dist/tools/conversations.js +17 -3
  26. package/dist/tools/conversations.js.map +1 -1
  27. package/dist/tools/customers.d.ts +1 -1
  28. package/dist/tools/customers.js +11 -9
  29. package/dist/tools/customers.js.map +1 -1
  30. package/dist/tools/media.d.ts +94 -0
  31. package/dist/tools/media.js +90 -2
  32. package/dist/tools/media.js.map +1 -1
  33. package/dist/tools/messages.js +5 -4
  34. package/dist/tools/messages.js.map +1 -1
  35. package/dist/tools/misc.js +3 -2
  36. package/dist/tools/misc.js.map +1 -1
  37. package/dist/tools/phone-numbers.js +4 -3
  38. package/dist/tools/phone-numbers.js.map +1 -1
  39. package/dist/tools/templates.js +4 -3
  40. package/dist/tools/templates.js.map +1 -1
  41. package/dist/tools/webhooks.d.ts +1 -1
  42. package/dist/tools/webhooks.js +10 -8
  43. package/dist/tools/webhooks.js.map +1 -1
  44. package/package.json +4 -2
package/README.md CHANGED
@@ -4,67 +4,107 @@ Servidor **MCP (Model Context Protocol)** para a API pública do **BotoZap** —
4
4
  plataforma dev-first sobre a WhatsApp Cloud API oficial (multi-tenant, a "Kapso
5
5
  brasileira").
6
6
 
7
- Ele expõe as operações da plataforma (`/api/v1`) como **ferramentas MCP**, para
8
- que assistentes como **Claude Code**, **Cursor** e **Codex** consigam enviar
9
- mensagens, gerenciar contatos/clientes/números, criar templates e webhooks etc.
7
+ Ele expõe as operações da plataforma (`/api/v1`) como **ferramentas MCP** e o
8
+ stream durável de Eventos como **resource assinável**, para que assistentes como
9
+ **Claude Code**, **Cursor** e **Codex** consigam operar o canal e receber um
10
+ sinal de baixa latência quando o WhatsApp mudar.
10
11
 
11
12
  Cada ferramenta MCP mapeia para uma operação do SDK oficial **`@botozap/sdk`**
12
13
  (que autentica com a sua chave `bz_...`, monta a requisição e trata o envelope de
13
- erro). É uma ponte fina: valida os argumentos (zod), delega ao SDK e devolve o
14
- JSON da API.
14
+ erro). É uma ponte fina: valida os argumentos e resultados (zod), delega ao SDK
15
+ e devolve o JSON da API.
15
16
 
16
- > **Status: em preparação — ainda NÃO publicado no npm.** Use a partir do
17
- > monorepo (build local), como abaixo.
17
+ Todas as tools anunciam `outputSchema` e devolvem o resultado em
18
+ `structuredContent`, além do `content[].text` em JSON mantido para clientes
19
+ antigos. Isso inclui paginação por cursor/offset, operações de gestão e os
20
+ `DELETE` sem corpo — estes preservam `null` no texto legado e devolvem
21
+ `{ success: true }` na saída estruturada. Erros preservam `isError` e também
22
+ expõem `{ error: { code, message, status } }` em `structuredContent`, sem
23
+ credenciais.
24
+
25
+ > **Status: preview público `0.x`.** Sem promessa de estabilidade de tools e
26
+ > argumentos até a `1.0`; fixe a versão para integrações reproduzíveis.
18
27
 
19
28
  ## Requisitos
20
29
 
21
- - **Node.js ≥ 20** (ESM).
30
+ - **Node.js ≥ 20.19** (ESM).
22
31
  - Uma chave de API do BotoZap (gere em **/chaves** no painel).
23
32
  - **pnpm** (este monorepo usa pnpm exclusivamente).
24
33
 
25
- ## Build
34
+ ## Instalação
26
35
 
27
- Este pacote vive no monorepo `botozap-js` e depende de `@botozap/sdk`
28
- (`workspace:*`). Instale as dependências na **raiz** do monorepo e então compile:
36
+ O pacote pode ser executado diretamente do npm:
29
37
 
30
38
  ```bash
31
- # na raiz do monorepo botozap-js
32
- pnpm install
33
- pnpm --filter @botozap/mcp build
39
+ pnpm dlx @botozap/mcp@0.1.0
34
40
  ```
35
41
 
36
- > Não use `--ignore-workspace`: o pacote precisa resolver `@botozap/sdk` pelo
37
- > workspace.
38
-
39
- Smoke test (monta o servidor e lista as ferramentas, **sem** chamar a API real):
42
+ Para desenvolver o monorepo localmente:
40
43
 
41
44
  ```bash
45
+ pnpm install
46
+ pnpm build
42
47
  pnpm --filter @botozap/mcp smoke
43
- ```
44
-
45
- Testes (vitest, sem rede):
46
-
47
- ```bash
48
48
  pnpm --filter @botozap/mcp test
49
49
  ```
50
50
 
51
51
  ## Configuração (variáveis de ambiente)
52
52
 
53
- | Variável | Obrigatória | Default | Descrição |
54
- | ------------------- | ----------- | ------------------------------------ | ------------------------------------------ |
55
- | `BOTOZAP_API_KEY` | **Sim** | — | Sua chave `bz_...` (header `Authorization: Bearer`). |
56
- | `BOTOZAP_API_URL` | Não | `https://botozap.com.br/api/v1` | Base da API (útil para staging/local). |
53
+ | Variável | Quando | Default | Descrição |
54
+ | --- | --- | --- | --- |
55
+ | `BOTOZAP_API_KEY` | Obrigatória em stdio | — | Chave `bz_...` usada pelo processo stdio. |
56
+ | `BOTOZAP_API_URL` | Opcional | `https://botozap.com.br/api/v1` | Base da API (útil para staging/local). |
57
+ | `BOTOZAP_MCP_TRANSPORT` | Remoto | `stdio` | Use `streamable-http` para iniciar o endpoint remoto. |
58
+ | `BOTOZAP_MCP_HOST` | Remoto | `127.0.0.1` | Interface TCP do endpoint remoto. |
59
+ | `BOTOZAP_MCP_PORT` | Remoto | `3001` | Porta do endpoint remoto (`0` escolhe uma porta livre). |
60
+ | `BOTOZAP_EVENT_BUS_DATABASE_URL` | Obrigatória no remoto | — | Conexão PostgreSQL de sessão que suporta `LISTEN/NOTIFY`. |
57
61
 
58
- Sem `BOTOZAP_API_KEY` o servidor falha imediatamente com uma mensagem clara.
62
+ Sem a configuração obrigatória do transporte escolhido, o servidor falha
63
+ imediatamente com uma mensagem clara e sem imprimir o valor recebido.
64
+
65
+ ### Streamable HTTP (operador da plataforma)
66
+
67
+ O mesmo binário pode manter sessões remotas stateful em `/mcp`. Nesse modo cada
68
+ cliente envia sua própria chave BotoZap no header `Authorization: Bearer`; a
69
+ sessão fica vinculada a essa credencial e a Conta/ambiente continuam derivados
70
+ pela API. A chave nunca entra na URL do endpoint, URI do resource ou
71
+ notification.
72
+
73
+ ```bash
74
+ BOTOZAP_MCP_TRANSPORT=streamable-http \
75
+ BOTOZAP_MCP_HOST=0.0.0.0 \
76
+ BOTOZAP_MCP_PORT=3001 \
77
+ BOTOZAP_EVENT_BUS_DATABASE_URL=postgresql://... \
78
+ pnpm dlx @botozap/mcp@0.1.0
79
+ ```
80
+
81
+ Use uma conexão PostgreSQL persistente/direta ou pooler em modo de sessão;
82
+ pooler em modo de transação não preserva `LISTEN`. O bus carrega somente um
83
+ sinal vazio. Ao recebê-lo, cada sessão consulta `/events` com sua própria chave
84
+ e só envia `notifications/resources/updated` se houver Evento no cursor
85
+ autorizado. O payload autoritativo permanece no stream durável.
86
+
87
+ Se o bus cair — inclusive durante o boot — o servidor continua disponível em
88
+ modo degradado, reconecta com backoff de 250 ms a 10 s e mantém um heartbeat de
89
+ reconciliação pelo cursor a cada 15 s. Um sinal que chega enquanto outra leitura
90
+ está em voo fica pendente para um novo probe imediato; não depende do próximo
91
+ heartbeat.
92
+
93
+ O processo mantém no máximo 1.000 sessões, 5 sessões por chave e 8 resources de
94
+ Eventos por sessão. `resources/unsubscribe` interrompe o consumo daquele
95
+ resource; `DELETE /mcp` encerra a sessão e libera listeners/timers. Uma sessão
96
+ que perde o transporte sem enviar `DELETE` é recolhida após 5 minutos sem
97
+ request ativo (varredura a cada 30 s). Esses limites são conservadores para o
98
+ preview `0.x` e podem mudar antes da `1.0`.
59
99
 
60
100
  ## Usar com Claude Code
61
101
 
62
- Via CLI (caminho **absoluto** para o `dist/index.js` compilado):
102
+ Via CLI:
63
103
 
64
104
  ```bash
65
105
  claude mcp add botozap \
66
106
  --env BOTOZAP_API_KEY=bz_live_suachaveaqui \
67
- -- node /caminho/absoluto/para/botozap-js/packages/mcp/dist/index.js
107
+ -- pnpm dlx @botozap/mcp@0.1.0
68
108
  ```
69
109
 
70
110
  Ou no JSON do MCP (`.mcp.json` do projeto ou config do usuário):
@@ -73,8 +113,8 @@ Ou no JSON do MCP (`.mcp.json` do projeto ou config do usuário):
73
113
  {
74
114
  "mcpServers": {
75
115
  "botozap": {
76
- "command": "node",
77
- "args": ["/caminho/absoluto/para/botozap-js/packages/mcp/dist/index.js"],
116
+ "command": "pnpm",
117
+ "args": ["dlx", "@botozap/mcp@0.1.0"],
78
118
  "env": {
79
119
  "BOTOZAP_API_KEY": "bz_live_suachaveaqui"
80
120
  }
@@ -91,8 +131,8 @@ Edite `~/.cursor/mcp.json` (global) ou `.cursor/mcp.json` (no projeto):
91
131
  {
92
132
  "mcpServers": {
93
133
  "botozap": {
94
- "command": "node",
95
- "args": ["/caminho/absoluto/para/botozap-js/packages/mcp/dist/index.js"],
134
+ "command": "pnpm",
135
+ "args": ["dlx", "@botozap/mcp@0.1.0"],
96
136
  "env": {
97
137
  "BOTOZAP_API_KEY": "bz_live_suachaveaqui"
98
138
  }
@@ -103,13 +143,13 @@ Edite `~/.cursor/mcp.json` (global) ou `.cursor/mcp.json` (no projeto):
103
143
 
104
144
  ## Ferramentas disponíveis
105
145
 
106
- Transporte: **stdio**. Nomes em inglês (snake_case, melhor para tool-calling);
107
- descrições em PT-BR.
146
+ Transportes: **stdio** (padrão, local) e **Streamable HTTP** (remoto stateful).
147
+ Nomes em inglês (snake_case, melhor para tool-calling); descrições em PT-BR.
108
148
 
109
149
  **Mensagens** — `send_message`, `list_messages`, `get_message`
110
- **Conversas** — `list_conversations`, `get_conversation`, `update_conversation`
150
+ **Conversas** — `reply_to_conversation`, `list_conversations`, `get_conversation`, `update_conversation`
111
151
  **Contatos** — `list_contacts`, `get_contact`, `create_contact`, `update_contact`, `delete_contact`
112
- **Mídia** — `ingest_media`
152
+ **Mídia** — `send_media_message`, `ingest_media`
113
153
  **Clientes** — `list_customers`, `get_customer`, `create_customer`, `update_customer`, `delete_customer`
114
154
  **Links de setup** — `list_setup_links`, `create_setup_link`, `update_setup_link`
115
155
  **Números** — `list_phone_numbers`, `get_phone_number`, `phone_number_health`
@@ -119,16 +159,44 @@ descrições em PT-BR.
119
159
  **Logs** — `list_api_logs`
120
160
  **Usuários** — `list_users`
121
161
 
162
+ ## Resource de Eventos
163
+
164
+ Os dois transportes anunciam `resources.subscribe` e o template
165
+ `botozap://events{?after,limit}`. Um cliente persistente pode assinar, por
166
+ exemplo, `botozap://events?after=42&limit=100` e receber
167
+ `notifications/resources/updated` quando existir um Evento posterior ao cursor
168
+ 42. O tail da API existe somente enquanto há assinatura ativa; clientes que usam
169
+ apenas tools não iniciam consultas de Eventos. A chave usada pelo servidor
170
+ precisa incluir o escopo `events:read`.
171
+
172
+ A notification é deliberadamente só um sinal e não carrega mensagem, Contato
173
+ ou credencial. Ao recebê-la, releia o mesmo resource, processe `data` e persista
174
+ `paging.cursor`. Depois de uma desconexão, leia a partir do último cursor salvo e
175
+ drene todas as páginas de catch-up (`paging.next`). Só então assine uma nova URI
176
+ com o cursor final em `after`; o probe inicial da assinatura fecha a corrida com
177
+ um Evento persistido entre a última leitura e o subscribe. Notifications são
178
+ hints at-least-once e podem se repetir; deduplique por `event.id` antes de
179
+ produzir qualquer resposta. O mesmo Evento conserva `id`, `cursor` e identidade
180
+ de mensagem em retries e replay.
181
+
182
+ No stdio, o tail usa intervalo padrão de 1,5 segundo e para no `unsubscribe` ou
183
+ no fim da sessão. No remoto, o PostgreSQL acorda o processo MCP mesmo quando o
184
+ Evento foi persistido por outra instância; a consulta escopada continua sendo a
185
+ fonte do payload e o heartbeat cobre sinais perdidos. Receber a notification não
186
+ significa que todo host inicia automaticamente uma nova execução do agente.
187
+
122
188
  Em caso de erro da API, a ferramenta devolve um resultado de erro (`isError`) com
123
189
  a mensagem PT-BR do envelope `{ error: { code, message } }` no formato
124
- `Erro [code]: message`.
190
+ `Erro [code]: message`. `code`, `message` e o status HTTP também ficam
191
+ disponíveis de forma programática em todas as tools.
125
192
 
126
193
  ## Chaves de sandbox
127
194
 
128
- Uma chave de **sandbox** (prefixo `bz_sandbox_`) só habilita as ferramentas de
129
- mensagem: `send_message`, `list_messages` e `get_message`. Qualquer outra
130
- ferramenta responde `403 sandbox_forbidden` (vindo da API) — útil para testar a
131
- integração de envio sem tocar dados reais.
195
+ Uma chave de **sandbox** (prefixo `bz_sandbox_`) habilita as ferramentas de
196
+ mensagem (`send_message`, `send_media_message`, `list_messages` e `get_message`) e o resource de
197
+ Eventos do próprio Sandbox. Qualquer outra ferramenta responde
198
+ `403 sandbox_forbidden` (vindo da API) — útil para testar a integração sem tocar
199
+ dados reais.
132
200
 
133
201
  **Números mágicos** (destinatários simulados, sem custo, sem número real):
134
202
 
@@ -0,0 +1,14 @@
1
+ import type { EventSignalSource } from "./resources/events.js";
2
+ export interface CloseableEventSignalSource extends EventSignalSource {
3
+ close(): Promise<void>;
4
+ }
5
+ export interface PostgresEventSignalOptions {
6
+ maxReconnectDelayMs?: number;
7
+ reconnectDelayMs?: number;
8
+ }
9
+ /**
10
+ * Adapter compartilhado de baixa latência. O NOTIFY não carrega payload nem
11
+ * autoridade: cada sessão acordada relê `/events` com sua própria chave.
12
+ * Quedas do socket refazem a conexão e o LISTEN com backoff limitado.
13
+ */
14
+ export declare function connectPostgresEventSignal(connectionString: string, options?: PostgresEventSignalOptions): Promise<CloseableEventSignalSource>;
@@ -0,0 +1,128 @@
1
+ import pg from "pg";
2
+ const CHANNEL = "botozap_account_events";
3
+ /**
4
+ * Adapter compartilhado de baixa latência. O NOTIFY não carrega payload nem
5
+ * autoridade: cada sessão acordada relê `/events` com sua própria chave.
6
+ * Quedas do socket refazem a conexão e o LISTEN com backoff limitado.
7
+ */
8
+ export async function connectPostgresEventSignal(connectionString, options = {}) {
9
+ const signal = new PostgresEventSignal(connectionString, options);
10
+ await signal.start();
11
+ return signal;
12
+ }
13
+ class PostgresEventSignal {
14
+ connectionString;
15
+ active;
16
+ closed = false;
17
+ connecting;
18
+ listeners = new Set();
19
+ reconnectAttempt = 0;
20
+ reconnectTimer;
21
+ reconnectDelayMs;
22
+ maxReconnectDelayMs;
23
+ constructor(connectionString, options) {
24
+ this.connectionString = connectionString;
25
+ this.reconnectDelayMs = Math.max(1, options.reconnectDelayMs ?? 250);
26
+ this.maxReconnectDelayMs = Math.max(this.reconnectDelayMs, options.maxReconnectDelayMs ?? 10_000);
27
+ }
28
+ async start() {
29
+ await this.connect().catch(() => this.scheduleReconnect());
30
+ }
31
+ subscribe(listener) {
32
+ this.listeners.add(listener);
33
+ return () => this.listeners.delete(listener);
34
+ }
35
+ async close() {
36
+ if (this.closed)
37
+ return;
38
+ this.closed = true;
39
+ this.listeners.clear();
40
+ if (this.reconnectTimer)
41
+ clearTimeout(this.reconnectTimer);
42
+ this.reconnectTimer = undefined;
43
+ const active = this.active;
44
+ if (active) {
45
+ this.detach(active);
46
+ await active.client.end().catch(() => { });
47
+ }
48
+ await this.connecting?.catch(() => { });
49
+ }
50
+ connect() {
51
+ if (this.closed)
52
+ return Promise.resolve();
53
+ if (this.connecting)
54
+ return this.connecting;
55
+ this.connecting = this.openClient().finally(() => {
56
+ this.connecting = undefined;
57
+ });
58
+ return this.connecting;
59
+ }
60
+ async openClient() {
61
+ const client = new pg.Client({
62
+ connectionString: this.connectionString,
63
+ application_name: "botozap-mcp-event-bus",
64
+ });
65
+ const active = {
66
+ client,
67
+ onEnd: () => this.handleDisconnect(active),
68
+ onError: () => this.handleDisconnect(active),
69
+ onNotification: (message) => {
70
+ if (this.active !== active || message.channel !== CHANNEL)
71
+ return;
72
+ for (const listener of [...this.listeners]) {
73
+ try {
74
+ listener();
75
+ }
76
+ catch {
77
+ // Uma sessão defeituosa não impede as demais de receber o sinal.
78
+ }
79
+ }
80
+ },
81
+ };
82
+ this.active = active;
83
+ client.on("error", active.onError);
84
+ client.on("end", active.onEnd);
85
+ client.on("notification", active.onNotification);
86
+ try {
87
+ await client.connect();
88
+ await client.query(`LISTEN ${CHANNEL}`);
89
+ if (this.closed || this.active !== active) {
90
+ this.detach(active);
91
+ await client.end().catch(() => { });
92
+ return;
93
+ }
94
+ this.reconnectAttempt = 0;
95
+ }
96
+ catch (error) {
97
+ this.detach(active);
98
+ await client.end().catch(() => { });
99
+ throw error;
100
+ }
101
+ }
102
+ handleDisconnect(active) {
103
+ if (this.closed || this.active !== active)
104
+ return;
105
+ this.detach(active);
106
+ void active.client.end().catch(() => { });
107
+ this.scheduleReconnect();
108
+ }
109
+ detach(active) {
110
+ active.client.removeListener("error", active.onError);
111
+ active.client.removeListener("end", active.onEnd);
112
+ active.client.removeListener("notification", active.onNotification);
113
+ if (this.active === active)
114
+ this.active = undefined;
115
+ }
116
+ scheduleReconnect() {
117
+ if (this.closed || this.reconnectTimer)
118
+ return;
119
+ const delay = Math.min(this.reconnectDelayMs * 2 ** this.reconnectAttempt, this.maxReconnectDelayMs);
120
+ this.reconnectAttempt += 1;
121
+ this.reconnectTimer = setTimeout(() => {
122
+ this.reconnectTimer = undefined;
123
+ void this.connect().catch(() => this.scheduleReconnect());
124
+ }, delay);
125
+ this.reconnectTimer.unref?.();
126
+ }
127
+ }
128
+ //# sourceMappingURL=event-bus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-bus.js","sourceRoot":"","sources":["../src/event-bus.ts"],"names":[],"mappings":"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"}
package/dist/http.d.ts ADDED
@@ -0,0 +1,31 @@
1
+ import type { EventSignalSource } from "./resources/events.js";
2
+ export type { EventSignalSource } from "./resources/events.js";
3
+ export interface StreamableHttpServerOptions {
4
+ baseUrl: string;
5
+ eventSignal: EventSignalSource;
6
+ /** Reconciliação periódica que cobre sinais perdidos/indisponibilidade do bus. */
7
+ eventPollIntervalMs?: number;
8
+ fetch?: typeof fetch;
9
+ host?: string;
10
+ /** Teto de resources de Eventos por sessão. */
11
+ maxEventSubscriptions?: number;
12
+ /** Teto de sessões stateful mantidas por processo. */
13
+ maxSessions?: number;
14
+ /** Teto de sessões simultâneas ligadas à mesma chave. */
15
+ maxSessionsPerApiKey?: number;
16
+ port?: number;
17
+ /** Tempo sem request ativo antes de recolher uma sessão abandonada. */
18
+ sessionIdleTimeoutMs?: number;
19
+ /** Frequência da varredura de sessões abandonadas. */
20
+ sessionSweepIntervalMs?: number;
21
+ }
22
+ export interface RunningStreamableHttpServer {
23
+ url: URL;
24
+ close(): Promise<void>;
25
+ }
26
+ /**
27
+ * Inicia um endpoint MCP remoto stateful. Cada sessão é criada a partir da
28
+ * chave Bearer do initialize e fica presa ao mesmo fingerprint nos requests
29
+ * seguintes; a autoridade da Conta continua sendo derivada pela API BotoZap.
30
+ */
31
+ export declare function startStreamableHttpServer(options: StreamableHttpServerOptions): Promise<RunningStreamableHttpServer>;