@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.
- package/README.md +111 -43
- package/dist/event-bus.d.ts +14 -0
- package/dist/event-bus.js +128 -0
- package/dist/event-bus.js.map +1 -0
- package/dist/http.d.ts +31 -0
- package/dist/http.js +280 -0
- package/dist/http.js.map +1 -0
- package/dist/index.js +47 -4
- package/dist/index.js.map +1 -1
- package/dist/register.d.ts +18 -4
- package/dist/register.js +82 -17
- package/dist/register.js.map +1 -1
- package/dist/resources/events.d.ts +12 -0
- package/dist/resources/events.js +192 -0
- package/dist/resources/events.js.map +1 -0
- package/dist/schemas.d.ts +4405 -0
- package/dist/schemas.js +332 -0
- package/dist/schemas.js.map +1 -0
- package/dist/server.d.ts +7 -0
- package/dist/server.js +13 -2
- package/dist/server.js.map +1 -1
- package/dist/tools/contacts.d.ts +1 -1
- package/dist/tools/contacts.js +8 -6
- package/dist/tools/contacts.js.map +1 -1
- package/dist/tools/conversations.js +17 -3
- package/dist/tools/conversations.js.map +1 -1
- package/dist/tools/customers.d.ts +1 -1
- package/dist/tools/customers.js +11 -9
- package/dist/tools/customers.js.map +1 -1
- package/dist/tools/media.d.ts +94 -0
- package/dist/tools/media.js +90 -2
- package/dist/tools/media.js.map +1 -1
- package/dist/tools/messages.js +5 -4
- package/dist/tools/messages.js.map +1 -1
- package/dist/tools/misc.js +3 -2
- package/dist/tools/misc.js.map +1 -1
- package/dist/tools/phone-numbers.js +4 -3
- package/dist/tools/phone-numbers.js.map +1 -1
- package/dist/tools/templates.js +4 -3
- package/dist/tools/templates.js.map +1 -1
- package/dist/tools/webhooks.d.ts +1 -1
- package/dist/tools/webhooks.js +10 -8
- package/dist/tools/webhooks.js.map +1 -1
- 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
|
|
8
|
-
|
|
9
|
-
|
|
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
|
|
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
|
-
|
|
17
|
-
|
|
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
|
-
##
|
|
34
|
+
## Instalação
|
|
26
35
|
|
|
27
|
-
|
|
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
|
-
|
|
32
|
-
pnpm install
|
|
33
|
-
pnpm --filter @botozap/mcp build
|
|
39
|
+
pnpm dlx @botozap/mcp@0.1.0
|
|
34
40
|
```
|
|
35
41
|
|
|
36
|
-
|
|
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
|
|
54
|
-
|
|
|
55
|
-
| `BOTOZAP_API_KEY`
|
|
56
|
-
| `BOTOZAP_API_URL`
|
|
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
|
|
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
|
|
102
|
+
Via CLI:
|
|
63
103
|
|
|
64
104
|
```bash
|
|
65
105
|
claude mcp add botozap \
|
|
66
106
|
--env BOTOZAP_API_KEY=bz_live_suachaveaqui \
|
|
67
|
-
--
|
|
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": "
|
|
77
|
-
"args": ["
|
|
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": "
|
|
95
|
-
"args": ["
|
|
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
|
-
|
|
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_`)
|
|
129
|
-
mensagem
|
|
130
|
-
|
|
131
|
-
|
|
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":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AAGpB,MAAM,OAAO,GAAG,wBAAwB,CAAC;AAkBzC;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAC9C,gBAAwB,EACxB,UAAsC,EAAE;IAExC,MAAM,MAAM,GAAG,IAAI,mBAAmB,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC;IAClE,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IACrB,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,mBAAmB;IAWJ;IAVX,MAAM,CAA2B;IACjC,MAAM,GAAG,KAAK,CAAC;IACf,UAAU,CAA4B;IAC7B,SAAS,GAAG,IAAI,GAAG,EAAc,CAAC;IAC3C,gBAAgB,GAAG,CAAC,CAAC;IACrB,cAAc,CAA4C;IACjD,gBAAgB,CAAS;IACzB,mBAAmB,CAAS;IAE7C,YACmB,gBAAwB,EACzC,OAAmC;QADlB,qBAAgB,GAAhB,gBAAgB,CAAQ;QAGzC,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,gBAAgB,IAAI,GAAG,CAAC,CAAC;QACrE,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC,GAAG,CACjC,IAAI,CAAC,gBAAgB,EACrB,OAAO,CAAC,mBAAmB,IAAI,MAAM,CACtC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,KAAK;QACT,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC,CAAC;IAC7D,CAAC;IAED,SAAS,CAAC,QAAoB;QAC5B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC7B,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC/C,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO;QACxB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;QACvB,IAAI,IAAI,CAAC,cAAc;YAAE,YAAY,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC3D,IAAI,CAAC,cAAc,GAAG,SAAS,CAAC;QAEhC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC3B,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACpB,MAAM,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAC5C,CAAC;QACD,MAAM,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACzC,CAAC;IAEO,OAAO;QACb,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;QAC1C,IAAI,IAAI,CAAC,UAAU;YAAE,OAAO,IAAI,CAAC,UAAU,CAAC;QAC5C,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE;YAC/C,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;QAC9B,CAAC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;IAEO,KAAK,CAAC,UAAU;QACtB,MAAM,MAAM,GAAG,IAAI,EAAE,CAAC,MAAM,CAAC;YAC3B,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;YACvC,gBAAgB,EAAE,uBAAuB;SAC1C,CAAC,CAAC;QACH,MAAM,MAAM,GAAiB;YAC3B,MAAM;YACN,KAAK,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC;YAC1C,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC;YAC5C,cAAc,EAAE,CAAC,OAAO,EAAE,EAAE;gBAC1B,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,IAAI,OAAO,CAAC,OAAO,KAAK,OAAO;oBAAE,OAAO;gBAClE,KAAK,MAAM,QAAQ,IAAI,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;oBAC3C,IAAI,CAAC;wBACH,QAAQ,EAAE,CAAC;oBACb,CAAC;oBAAC,MAAM,CAAC;wBACP,iEAAiE;oBACnE,CAAC;gBACH,CAAC;YACH,CAAC;SACF,CAAC;QACF,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;QACnC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;QAC/B,MAAM,CAAC,EAAE,CAAC,cAAc,EAAE,MAAM,CAAC,cAAc,CAAC,CAAC;QAEjD,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;YACvB,MAAM,MAAM,CAAC,KAAK,CAAC,UAAU,OAAO,EAAE,CAAC,CAAC;YACxC,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;gBAC1C,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBACpB,MAAM,MAAM,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;gBACnC,OAAO;YACT,CAAC;YACD,IAAI,CAAC,gBAAgB,GAAG,CAAC,CAAC;QAC5B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACpB,MAAM,MAAM,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YACnC,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAEO,gBAAgB,CAAC,MAAoB;QAC3C,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM;YAAE,OAAO;QAClD,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACpB,KAAK,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACzC,IAAI,CAAC,iBAAiB,EAAE,CAAC;IAC3B,CAAC;IAEO,MAAM,CAAC,MAAoB;QACjC,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;QACtD,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;QAClD,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,cAAc,EAAE,MAAM,CAAC,cAAc,CAAC,CAAC;QACpE,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM;YAAE,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;IACtD,CAAC;IAEO,iBAAiB;QACvB,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,cAAc;YAAE,OAAO;QAC/C,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CACpB,IAAI,CAAC,gBAAgB,GAAG,CAAC,IAAI,IAAI,CAAC,gBAAgB,EAClD,IAAI,CAAC,mBAAmB,CACzB,CAAC;QACF,IAAI,CAAC,gBAAgB,IAAI,CAAC,CAAC;QAC3B,IAAI,CAAC,cAAc,GAAG,UAAU,CAAC,GAAG,EAAE;YACpC,IAAI,CAAC,cAAc,GAAG,SAAS,CAAC;YAChC,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC,CAAC;QAC5D,CAAC,EAAE,KAAK,CAAC,CAAC;QACV,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,EAAE,CAAC;IAChC,CAAC;CACF"}
|
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>;
|