@lionchat/mcp-server 0.4.2 → 0.4.4
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/CHANGELOG.md +41 -0
- package/dist/docs/instructions.md +11 -6
- package/dist/docs/resources/api-conventions.md +34 -35
- package/dist/docs/resources/best-practices.md +22 -0
- package/dist/docs/resources/conversation-flows.md +31 -1
- package/dist/docs/resources/data-model.md +6 -0
- package/dist/docs/resources/troubleshooting.md +17 -23
- package/endpoints.json +12386 -7093
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,46 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.3 — 2026-05-20
|
|
4
|
+
|
|
5
|
+
### Corrigido
|
|
6
|
+
|
|
7
|
+
- **Doc do wrapper de body** (`api-conventions.md`, `troubleshooting.md`, `instructions.md`): auditoria empirica derrubou o claim falso de "HTTP 500 silencioso sem wrapper". O Rails do projeto roda com `wrap_parameters: [:json]` global, entao body raiz e auto-wrappado na maioria dos endpoints. Doc reescrita com base em testes curl reais contra os controllers (`kanban_config`, `funnels`, `labels`, `custom_attribute_definitions`, `kanban_items` aceitam ambos os formatos).
|
|
8
|
+
- **Pegadinha do `/contacts`**: documentada nova armadilha real — `POST /contacts` com wrapper `{"contact": {...}}` retorna 200 mas cria contato com campos vazios. Causa: `ContactsController` usa `params.permit(:name, ...)` direto, sem `require(:contact)`. **Sempre enviar body raiz pro `/contacts`**.
|
|
9
|
+
- **`findDocsPath` em `src/resources.ts`**: agora cobre 3 layouts (`dist/docs/resources/` publicado, monorepo legado, `src/docs/` dev) pra evitar `null` quando rodado via `npx`.
|
|
10
|
+
|
|
11
|
+
### Mudado
|
|
12
|
+
|
|
13
|
+
- `scripts/extract-endpoints.ts` migrado de `require()` pra `import` (ESM). Adicionadas sub-categorias `Validacao WhatsApp` e `Chat Interno` no mapeamento de slugs.
|
|
14
|
+
|
|
15
|
+
## 0.4.0 / 0.4.1 / 0.4.2 — 2026-05-19
|
|
16
|
+
|
|
17
|
+
### Adicionado
|
|
18
|
+
|
|
19
|
+
- **Completion API** — sugestoes de auto-complete pros parametros das tools (ex: lista `account_id`/`inbox_id` disponiveis). Reduz erro de id inexistente.
|
|
20
|
+
- **Progress notifications** — operacoes longas reportam progresso em tempo real (import de contatos, exports, etc), em vez de ficar em silencio ate terminar.
|
|
21
|
+
- **User-Agent customizado** — requests do MCP agora marcam origem MCP no `audit_log` do LionChat, separando do trafego normal.
|
|
22
|
+
|
|
23
|
+
## 0.3.2 — 2026-05-19
|
|
24
|
+
|
|
25
|
+
### Adicionado
|
|
26
|
+
|
|
27
|
+
- **FlowBuilder enrichment** — Resource `flowbuilder-design-guide` com schema completo de nodes, handles por tipo, layout/positioning e erros comuns + `flowbuilder-patterns` com 10 templates prontos (saudacao, captura, qualificacao, CSAT, IA, etc) + Prompt `create_flow_brainstorm` pra estruturar fluxos antes de criar. LLMs agora tem material concreto pra montar `flow_data` sem chutar.
|
|
28
|
+
|
|
29
|
+
## 0.3.1 — 2026-05-18
|
|
30
|
+
|
|
31
|
+
### Adicionado
|
|
32
|
+
|
|
33
|
+
- **Sprint 3 do MCP Knowledge Enrichment** — +4 Resources (`conversation-flows`, `kanban-deep-dive`, `best-practices`, `troubleshooting`) e +4 Prompts (`inactive_contacts`, `team_load_balance`, `quality_audit`, `whatsapp_template_usage`). Total: 10 Resources + 9 Prompts no servidor.
|
|
34
|
+
|
|
35
|
+
## 0.3.0 — 2026-05-18
|
|
36
|
+
|
|
37
|
+
### Adicionado
|
|
38
|
+
|
|
39
|
+
- **MCP Instructions** carregadas no boot do servidor (~3K tokens) explicando data model, status codes, convenções de API e workflows tipicos pra qualquer LLM que conectar entender o contexto antes de chamar tools.
|
|
40
|
+
- **4 Resources iniciais**: `glossary`, `data-model`, `reports-guide`, `api-conventions`.
|
|
41
|
+
- **4 Prompts iniciais**: `productivity_report`, `stuck_leads`, `weekly_recap`, `customer_health`.
|
|
42
|
+
- **Enriquecimento de 547 descriptions** das tools (48 → 183 chars em media), com `returns`, `common_use_cases` e `related_tools` em cada uma.
|
|
43
|
+
|
|
3
44
|
## 0.2.1 — 2026-05-13
|
|
4
45
|
|
|
5
46
|
### Adicionado
|
|
@@ -78,18 +78,23 @@ Account (conta/empresa)
|
|
|
78
78
|
- `display_id`: número visível na UI da conversa (use este pra falar com humanos)
|
|
79
79
|
- `source_id`: ID externo da plataforma origem (ex: `wamid.xxx` do WhatsApp)
|
|
80
80
|
|
|
81
|
-
### Body wrapper —
|
|
81
|
+
### Body wrapper — use raiz por padrão
|
|
82
82
|
|
|
83
|
-
|
|
83
|
+
O Rails tem `wrap_parameters: [:json]` global. Body JSON raiz é auto-wrapped no nome do recurso, então ambas as formas funcionam na maioria dos endpoints:
|
|
84
84
|
|
|
85
85
|
```json
|
|
86
86
|
PUT /api/v1/accounts/43/kanban_config
|
|
87
|
-
{ "
|
|
88
|
-
|
|
89
|
-
{ "win_reasons": [...] } ❌ 500
|
|
87
|
+
{ "win_reasons": [...] } ✅ raiz (recomendado)
|
|
88
|
+
{ "kanban_config": { "win_reasons": [...] } } ✅ explícito (também OK)
|
|
90
89
|
```
|
|
91
90
|
|
|
92
|
-
|
|
91
|
+
**Exceção importante — `/contacts` SÓ aceita raiz.** Com wrapper, o `name`/`email`/`phone_number` somem silenciosamente e o contato é criado vazio:
|
|
92
|
+
|
|
93
|
+
```json
|
|
94
|
+
POST /api/v1/accounts/43/contacts
|
|
95
|
+
{ "name": "Fulano", "phone_number": "+5511..." } ✅
|
|
96
|
+
{ "contact": { "name": "Fulano" } } ⚠️ cria contato com name vazio
|
|
97
|
+
```
|
|
93
98
|
|
|
94
99
|
Detalhes completos em `lionchat://docs/api-conventions` → "Wrapper de body".
|
|
95
100
|
|
|
@@ -19,62 +19,61 @@ Pra você via MCP: tudo já tá resolvido. O servidor MCP injeta o token correto
|
|
|
19
19
|
|
|
20
20
|
Tokens são **por usuário**, não por conta. O mesmo token funciona em qualquer conta que o usuário tem acesso. O scoping por conta acontece via `account_id` no path.
|
|
21
21
|
|
|
22
|
-
## Wrapper de body —
|
|
22
|
+
## Wrapper de body — como o Rails interpreta
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
O projeto roda com `wrap_parameters format: [:json]` no Rails (config global). Na prática:
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
- Bodies JSON raiz são **auto-wrapped** pelo Rails no nome do recurso (derivado do controller).
|
|
27
|
+
- Mandar `{"enabled": true}` em `PUT /kanban_config` é equivalente a mandar `{"kanban_config": {"enabled": true}}`.
|
|
28
|
+
- Ambas as formas funcionam na maioria dos endpoints. Não existe "HTTP 500 silencioso por falta de wrapper" — esse claim era impreciso.
|
|
29
|
+
|
|
30
|
+
### Padrão recomendado
|
|
31
|
+
|
|
32
|
+
Use **body raiz** (sem wrapper). É mais curto, funciona em todos os endpoints listados abaixo, e evita a pegadinha do `/contacts`.
|
|
27
33
|
|
|
28
34
|
```http
|
|
29
35
|
PUT /api/v1/accounts/43/kanban_config
|
|
30
36
|
Content-Type: application/json
|
|
31
37
|
|
|
32
|
-
{
|
|
33
|
-
"kanban_config": {
|
|
34
|
-
"win_reasons": [...],
|
|
35
|
-
"enabled": true
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
+
{ "win_reasons": [{"id": "wr-1", "title": "Preço competitivo"}] }
|
|
38
39
|
```
|
|
39
40
|
|
|
40
|
-
|
|
41
|
+
### Comportamento por endpoint (validado empiricamente)
|
|
41
42
|
|
|
42
|
-
|
|
43
|
+
| Endpoint | Raiz | Com wrapper | Observação |
|
|
44
|
+
|---|---|---|---|
|
|
45
|
+
| `POST/PUT /kanban_config` | ✅ | ✅ | qualquer um |
|
|
46
|
+
| `POST/PATCH /funnels` | ✅ | ✅ | qualquer um |
|
|
47
|
+
| `POST/PUT /kanban_items` | ✅ | ✅ | controller usa `require(:kanban_item)` mas auto-wrap resolve |
|
|
48
|
+
| `POST/PATCH /labels` | ✅ | ✅ | qualquer um |
|
|
49
|
+
| `POST/PATCH /custom_attribute_definitions` | ✅ | ✅ | qualquer um |
|
|
50
|
+
| `POST/PATCH /contacts` | ✅ | ⚠️ **drop silencioso** | Controller usa `params.permit(...)` na raiz sem `require(:contact)`. Com wrapper, o auto-wrap não duplica e os campos do body raiz ficam ausentes — o contato é criado com `name` vazio. **USE RAIZ.** |
|
|
51
|
+
| `POST/PATCH /conversations` | ✅ | varia | conversa aceita raiz |
|
|
52
|
+
| `POST /captain/copilot_threads` | ✅ | n/a | só raiz (`message`, `assistant_id`, `conversation_id`) |
|
|
53
|
+
| `POST /voip/settings/create_child_account` | ✅ | n/a | só raiz (`nome`, `login`, `senha`) |
|
|
43
54
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
| `POST/PATCH /funnels` | `funnel: {...}` |
|
|
48
|
-
| `POST/PUT /kanban_items` | `kanban_item: {...}` |
|
|
49
|
-
| `POST/PATCH /contacts` | `contact: {...}` |
|
|
50
|
-
| `POST/PATCH /conversations` | `conversation: {...}` ou direto (varia) |
|
|
51
|
-
| `POST/PATCH /custom_attribute_definitions` | sem wrapper (params raiz) |
|
|
52
|
-
| `POST/PATCH /labels` | sem wrapper |
|
|
53
|
-
| `POST /captain/copilot_threads` | sem wrapper (params raiz: `message`, `assistant_id`) |
|
|
54
|
-
| `POST /voip/settings/create_child_account` | sem wrapper (raiz: `nome`, `login`, `senha`) |
|
|
55
|
+
### Quando WRAPPER é obrigatório
|
|
56
|
+
|
|
57
|
+
Praticamente nunca — exceto se você está testando legacy/curl e quer ser explícito. As tools do MCP geram params com nome `recurso.campo` (ex: `kanban_config.win_reasons`) só pra organizar a UI; no body final qualquer formato roda.
|
|
55
58
|
|
|
56
|
-
###
|
|
59
|
+
### Listas substituem, não fazem merge
|
|
57
60
|
|
|
58
|
-
|
|
59
|
-
2. Params nomeados sem ponto (`message`, `phone`, `title`) ficam direto no body raiz.
|
|
60
|
-
3. Em caso de dúvida: tentar **com wrapper primeiro** (mais comum). Se 500, tentar sem.
|
|
61
|
+
`win_reasons`, `loss_reasons`, `stages`, `linked_conversations`, etc. — quando você manda a lista, ela **substitui** a anterior por inteiro. Pra preservar, leia com GET primeiro e mande a lista completa.
|
|
61
62
|
|
|
62
|
-
###
|
|
63
|
+
### Estrutura interna das listas
|
|
63
64
|
|
|
64
|
-
`
|
|
65
|
+
`win_reasons` / `loss_reasons` aceitam array de **objetos** `{id, title}`, NÃO strings:
|
|
65
66
|
|
|
66
67
|
```json
|
|
67
68
|
{
|
|
68
|
-
"
|
|
69
|
-
"
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
]
|
|
73
|
-
}
|
|
69
|
+
"win_reasons": [
|
|
70
|
+
{"id": "wr-1", "title": "Preço competitivo"},
|
|
71
|
+
{"id": "wr-2", "title": "Indicação forte"}
|
|
72
|
+
]
|
|
74
73
|
}
|
|
75
74
|
```
|
|
76
75
|
|
|
77
|
-
|
|
76
|
+
Strings simples (`"win_reasons": ["motivo"]`) causam erro de serialização.
|
|
78
77
|
|
|
79
78
|
## Restrições de formato em campos comuns
|
|
80
79
|
|
|
@@ -95,6 +95,28 @@ Se receber `429 Too Many Requests`:
|
|
|
95
95
|
|
|
96
96
|
IA é boa pra: triagem, classificação, resumo, sugestão de resposta, análise.
|
|
97
97
|
|
|
98
|
+
## Botão de pânico: pausar/retomar AI Agente (2026-05-22)
|
|
99
|
+
|
|
100
|
+
Pra parar IMEDIATAMENTE um AI Agente (todas as conversas dele) sem perder configuração:
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
lionchat_captain_assistants_update id=<id> paused=true
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
O campo `paused` é **top-level** (não vai em `config`). Quando `true`:
|
|
107
|
+
- Jobs de resposta automática são curto-circuitados (não chamam o LLM)
|
|
108
|
+
- Follow-ups agendados não disparam
|
|
109
|
+
- Callbacks agendados são limpos
|
|
110
|
+
|
|
111
|
+
Pra reativar: `paused=false`. Toggle é auditado (`audited only: [:paused]`).
|
|
112
|
+
|
|
113
|
+
**Janela de inconsistência:** ~5-8s. Jobs que já estão dentro do LLM no momento da pausa enviam a resposta mesmo. Use o botão pra parar **novas** respostas, não pra cancelar uma que já saiu.
|
|
114
|
+
|
|
115
|
+
## Limite do prompt e cache OpenAI (2026-05-22)
|
|
116
|
+
|
|
117
|
+
- `config.instructions` (system prompt do agente) aceita até **20.000 caracteres** (antes 10k). Acima de 15k, o frontend mostra aviso "lost in the middle" — prefira colocar instruções críticas no início ou final.
|
|
118
|
+
- **Cache automático** ativo em todos os 15 modelos suportados (GPT-4.1 Nano até GPT-5.2 Pro, o1, o3, o4-mini). Desconto 50-75% no input cachado, sem configuração. Reuso do prompt do agente em múltiplas conversas maximiza a economia.
|
|
119
|
+
|
|
98
120
|
## Variáveis de conta (account_variables)
|
|
99
121
|
|
|
100
122
|
Pra dados que se repetem (slogans, endereços, horários):
|
|
@@ -203,6 +203,36 @@ Conversation
|
|
|
203
203
|
| `conversation_opened` | Status volta pra open (reabertura) |
|
|
204
204
|
| `conversation_resolved` | Agente resolve |
|
|
205
205
|
| `conversation_pending` | Status muda pra pending |
|
|
206
|
-
| `conversation_updated` |
|
|
206
|
+
| `conversation_updated` | Acao na conversa — filtrada por `action_types` (UI: "Acao na conversa") |
|
|
207
207
|
| `message_created` | Nova mensagem (incoming ou outgoing) |
|
|
208
208
|
| `first_reply_created` | Primeira resposta humana |
|
|
209
|
+
|
|
210
|
+
### Subtipos de `conversation_updated` (campo `action_types`)
|
|
211
|
+
|
|
212
|
+
Ao criar/atualizar uma `automation_rule` com `event_name: 'conversation_updated'`, envie tambem
|
|
213
|
+
o campo `action_types` (array de strings) pra filtrar quais mudancas disparam a regra. Vazio/nulo
|
|
214
|
+
mantem comportamento legado (qualquer mudanca dispara — retrocompat com regras antigas).
|
|
215
|
+
|
|
216
|
+
| Subtipo | Detectado quando muda |
|
|
217
|
+
|---|---|
|
|
218
|
+
| `label_added` | `label_list` (apos - antes nao vazio) |
|
|
219
|
+
| `label_removed` | `label_list` (antes - apos nao vazio) |
|
|
220
|
+
| `status_changed` | `status` |
|
|
221
|
+
| `priority_changed` | `priority` |
|
|
222
|
+
| `agent_assigned` | `assignee_id` |
|
|
223
|
+
| `team_assigned` | `team_id` |
|
|
224
|
+
| `custom_attribute_changed` | `custom_attributes` |
|
|
225
|
+
| `language_changed` | `additional_attributes.conversation_language` |
|
|
226
|
+
| `ai_agent_assigned` | `captain_assistant_id` |
|
|
227
|
+
|
|
228
|
+
Exemplo de criacao via API:
|
|
229
|
+
```json
|
|
230
|
+
POST /api/v1/accounts/{account_id}/automation_rules
|
|
231
|
+
{
|
|
232
|
+
"name": "Notificar quando etiqueta VIP entra",
|
|
233
|
+
"event_name": "conversation_updated",
|
|
234
|
+
"action_types": ["label_added"],
|
|
235
|
+
"conditions": [{"attribute_key": "labels", "filter_operator": "contains", "values": ["vip"]}],
|
|
236
|
+
"actions": [{"action_name": "send_email_to_team", "action_params": {"team_ids": [1], "message": "VIP!"}}]
|
|
237
|
+
}
|
|
238
|
+
```
|
|
@@ -216,6 +216,7 @@ Captain::Assistant
|
|
|
216
216
|
├── account_id (FK)
|
|
217
217
|
├── name
|
|
218
218
|
├── description
|
|
219
|
+
├── paused (boolean, default false) — botao de panico (2026-05-22). true = pausa respostas, follow-up e callbacks. Auditado. Top-level, NAO mora em config.
|
|
219
220
|
├── config (jsonb: model, temperature, instructions, feature_memory, feature_faq, ...)
|
|
220
221
|
├── guardrails (string[])
|
|
221
222
|
├── response_guidelines (string[])
|
|
@@ -248,8 +249,13 @@ AutomationRule
|
|
|
248
249
|
├── account_id (FK)
|
|
249
250
|
├── name
|
|
250
251
|
├── event_name (conversation_created, conversation_resolved, message_created, conversation_opened, conversation_updated)
|
|
252
|
+
├── action_types (jsonb array) — subtipos de conversation_updated:
|
|
253
|
+
│ label_added, label_removed, status_changed, priority_changed,
|
|
254
|
+
│ agent_assigned, team_assigned, custom_attribute_changed,
|
|
255
|
+
│ language_changed, ai_agent_assigned. Vazio/nulo = retrocompat (dispara em qualquer)
|
|
251
256
|
├── conditions (jsonb array)
|
|
252
257
|
├── actions (jsonb array)
|
|
258
|
+
├── inbox_id (FK, opcional — usado em event_name=webhook)
|
|
253
259
|
└── active (bool)
|
|
254
260
|
|
|
255
261
|
Macro
|
|
@@ -75,36 +75,30 @@ NÃO retry imediato — só piora.
|
|
|
75
75
|
### 500 Internal Server Error
|
|
76
76
|
Erro do servidor LionChat.
|
|
77
77
|
|
|
78
|
-
**
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
{"win_reasons": [...]} // ❌ 500 silencioso
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
Rails levanta `ActionController::ParameterMissing` que vira 500 sem mensagem útil. A request precisa ser:
|
|
86
|
-
|
|
87
|
-
```http
|
|
88
|
-
PUT /api/v1/accounts/43/kanban_config
|
|
89
|
-
{"kanban_config": {"win_reasons": [...]}} // ✅
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
Veja `api-conventions.md → Wrapper de body` pra tabela completa de quais endpoints exigem wrapper.
|
|
93
|
-
|
|
94
|
-
**Outras causas:**
|
|
95
|
-
- Estrutura do array errada (ex: `win_reasons: ["str"]` em vez de `[{id, title}]`)
|
|
96
|
-
- Validação de modelo falha (cheque se o controller tem `validate :*` que rejeita o input)
|
|
78
|
+
**Causas comuns:**
|
|
79
|
+
- Estrutura interna de lista errada (ex: `win_reasons: ["str"]` em vez de `[{id, title}]`)
|
|
80
|
+
- Tipos errados em campos (string onde espera int, hash onde espera array, etc)
|
|
81
|
+
- Validação de modelo lança exceção não tratada
|
|
97
82
|
- Bug genuíno do servidor
|
|
98
83
|
|
|
99
84
|
**Ação:**
|
|
100
|
-
-
|
|
101
|
-
-
|
|
85
|
+
- Revisar tipos e estrutura do payload contra `api-conventions.md` e `data-model.md`
|
|
86
|
+
- Retry 1x após 2-5 segundos
|
|
102
87
|
- Se persiste: reportar pro usuário com timestamp/request ID
|
|
103
88
|
|
|
89
|
+
> Nota: o Rails do projeto roda com `wrap_parameters: [:json]` global, então body raiz é auto-wrapped no nome do recurso. Falta de wrapper **não** gera 500 silencioso na maioria dos endpoints — descarte essa hipótese e foque em tipos/estrutura. Detalhes em `api-conventions.md → Wrapper de body`.
|
|
90
|
+
|
|
104
91
|
### "param is missing or the value is empty: <recurso>"
|
|
105
|
-
Status: 400 (
|
|
92
|
+
Status: 400 (raro)
|
|
93
|
+
|
|
94
|
+
Aparece em endpoints que rodam `params.require(:algo)` com nome não-padrão (fora da convenção REST que o auto-wrap deduz). Solução: enviar wrapper explícito `{"<recurso>": {...}}`.
|
|
95
|
+
|
|
96
|
+
### Contato criado com `name`/`phone` vazios após POST /contacts
|
|
97
|
+
Não é 5xx — request volta 200, mas o contato fica sem os dados que você mandou.
|
|
98
|
+
|
|
99
|
+
**Causa:** body foi enviado com wrapper (`{"contact": {"name": "..."}}`). O `ContactsController` usa `params.permit(:name, ...)` direto na raiz, sem `require(:contact)`. Como o auto-wrap não duplica quando o wrapper já está presente, os campos ficam só dentro de `params[:contact]` e o `permit` na raiz não pega.
|
|
106
100
|
|
|
107
|
-
|
|
101
|
+
**Solução:** mandar body raiz: `{"name": "Fulano", "phone_number": "+5511..."}`.
|
|
108
102
|
|
|
109
103
|
### 502 Bad Gateway / 503 Service Unavailable
|
|
110
104
|
Indisponibilidade temporária (deploy, manutenção, sobrecarga).
|