# Twenty CRM MCP Server - Guia de Integração REST API
## Visão Geral
O **Twenty CRM MCP Server v0.2.0** possui endpoints REST simples que podem ser facilmente acessados usando curl, n8n, ou qualquer cliente HTTP. Esta versão foi refatorada com base no schema OpenAPI atual do Twenty CRM.
## Endpoints Disponíveis
### 1. Health Check
**Endpoint:** `GET http://ambienz-twenty-mcp-server:3001/health`
Verifica o status do servidor.
**Exemplo de resposta:**
```json
{
"status": "ok",
"version": "0.2.0"
}
```
### 2. Listar Ferramentas Disponíveis
**Endpoint:** `GET http://ambienz-twenty-mcp-server:3001/tools`
Lista todas as ferramentas (tools) disponíveis no servidor MCP. Retorna apenas nome e descrição para melhor performance.
**Exemplo curl:**
```bash
curl -X GET http://ambienz-twenty-mcp-server:3001/tools
```
**Resposta:**
```json
{
"success": true,
"totalCount": 35,
"tools": [
{
"name": "list_people",
"description": "List people with optional filtering and pagination"
},
{
"name": "create_person",
"description": "Create a new person in Twenty CRM"
}
]
}
```
### 2.1. Obter Detalhes de Uma Ferramenta
**Endpoint:** `GET http://ambienz-twenty-mcp-server:3001/tools/:toolName`
Retorna detalhes completos de uma ferramenta específica, incluindo o inputSchema.
**Exemplo curl:**
```bash
curl -X GET http://ambienz-twenty-mcp-server:3001/tools/create_person
```
**Resposta:**
```json
{
"success": true,
"tool": {
"name": "create_person",
"description": "Create a new person in Twenty CRM",
"inputSchema": {
"type": "object",
"properties": {
"name": {
"type": "object",
"properties": {
"firstName": {"type": "string"},
"lastName": {"type": "string"}
}
}
},
"required": ["name"]
}
}
}
```
### 2.2. Obter Apenas o Schema
**Endpoint:** `GET http://ambienz-twenty-mcp-server:3001/tools/:toolName/schema`
Retorna apenas o inputSchema de uma ferramenta.
**Exemplo curl:**
```bash
curl -X GET http://ambienz-twenty-mcp-server:3001/tools/create_person/schema
```
**Exemplo de resposta (parcial):**
```json
{
"success": true,
"totalCount": 35,
"tools": [
{
"name": "list_people",
"description": "List people with optional filtering and pagination"
},
{
"name": "create_person",
"description": "Create a new person in Twenty CRM"
}
]
}
```
**Ferramentas disponíveis:**
- **People:** list_people, create_person, get_person, update_person, delete_person
- **Companies:** list_companies, create_company, get_company, update_company, delete_company
- **Opportunities:** list_opportunities, create_opportunity, get_opportunity, update_opportunity, delete_opportunity
- **Notes:** list_notes, create_note, get_note, update_note, delete_note
- **Tasks:** list_tasks, create_task, get_task, update_task, delete_task
- **Conversas:** list_conversas, create_conversa, get_conversa, update_conversa, delete_conversa
- **Faturas:** list_faturas, create_fatura, get_fatura, update_fatura, delete_fatura
**💡 Dica de Performance:**
Use `GET /tools/:toolName` para obter o schema de apenas uma ferramenta quando necessário, ao invés de carregar todas de uma vez.
### 3. Executar Ferramenta (Tool)
**Endpoint:** `POST http://ambienz-twenty-mcp-server:3001/tools/{toolName}`
Executa uma ferramenta específica com os parâmetros fornecidos.
**Headers:**
```
Content-Type: application/json
```
**Exemplo curl:**
```bash
curl -X POST http://ambienz-twenty-mcp-server:3001/tools/list_people \
-H "Content-Type: application/json" \
-d '{"limit": 10}'
```
## Exemplos de Uso com curl
### Exemplo 1: Health Check
```bash
curl -X GET http://ambienz-twenty-mcp-server:3001/health
```
### Exemplo 2: Listar Todas as Ferramentas Disponíveis (Resumo)
```bash
curl -X GET http://ambienz-twenty-mcp-server:3001/tools
```
**Resposta:** Retorna um objeto JSON com `success: true`, `totalCount: 35` e lista resumida (apenas nome + descrição) de todas as ferramentas. Response: ~2KB
### Exemplo 2.1: Obter Detalhes de Uma Ferramenta Específica
```bash
curl -X GET http://ambienz-twenty-mcp-server:3001/tools/create_person
```
**Resposta:** Retorna detalhes completos incluindo inputSchema da ferramenta. Response: ~500 bytes
### Exemplo 2.2: Obter Apenas o Schema
```bash
curl -X GET http://ambienz-twenty-mcp-server:3001/tools/create_person/schema
```
**Resposta:** Retorna apenas o inputSchema. Response: ~400 bytes
### Exemplo 3: Listar Pessoas
```bash
curl -X POST http://ambienz-twenty-mcp-server:3001/tools/list_people \
-H "Content-Type: application/json" \
-d '{
"limit": 10,
"filter": "{\"name\": {\"firstName\": {\"ilike\": \"%João%\"}}}",
"orderBy": "createdAt"
}'
```
### Exemplo 4: Criar Pessoa (Nova Estrutura)
```bash
curl -X POST http://ambienz-twenty-mcp-server:3001/tools/create_person \
-H "Content-Type: application/json" \
-d '{
"name": {
"firstName": "João",
"lastName": "Silva"
},
"emails": {
"primaryEmail": "joao.silva@example.com",
"additionalEmails": []
},
"phones": {
"primaryPhoneNumber": "999999999",
"primaryPhoneCountryCode": "+55"
},
"jobTitle": "Developer",
"city": "São Paulo"
}'
```
### Exemplo 5: Buscar Pessoa por ID
```bash
curl -X POST http://ambienz-twenty-mcp-server:3001/tools/get_person \
-H "Content-Type: application/json" \
-d '{
"id": "uuid-da-pessoa",
"depth": 2
}'
```
### Exemplo 6: Atualizar Pessoa
```bash
curl -X POST http://ambienz-twenty-mcp-server:3001/tools/update_person \
-H "Content-Type: application/json" \
-d '{
"id": "uuid-da-pessoa",
"jobTitle": "Senior Developer",
"city": "Rio de Janeiro"
}'
```
### Exemplo 7: Listar Empresas
```bash
curl -X POST http://ambienz-twenty-mcp-server:3001/tools/list_companies \
-H "Content-Type: application/json" \
-d '{
"limit": 10,
"filter": "{\"name\": {\"ilike\": \"%Tech%\"}}",
"depth": 1
}'
```
### Exemplo 8: Criar Empresa (com campos brasileiros)
```bash
curl -X POST http://ambienz-twenty-mcp-server:3001/tools/create_company \
-H "Content-Type: application/json" \
-d '{
"name": "Tech Solutions Ltda",
"razaoSocial": "Tech Solutions Tecnologia LTDA",
"cnpj": "12.345.678/0001-90",
"domainName": "techsolutions.com.br",
"address": "Av. Paulista, 1000",
"employees": 50,
"annualRecurringRevenue": {
"amountMicros": 1000000000000,
"currencyCode": "BRL"
},
"idealCustomerProfile": true
}'
```
### Exemplo 9: Criar Oportunidade
```bash
curl -X POST http://ambienz-twenty-mcp-server:3001/tools/create_opportunity \
-H "Content-Type: application/json" \
-d '{
"name": "Deal XYZ 2024",
"amount": {
"amountMicros": 50000000000,
"currencyCode": "BRL"
},
"stage": "QUALIFICATION",
"closeDate": "2024-12-31T23:59:59Z",
"companyId": "uuid-da-empresa",
"pointOfContactId": "uuid-da-pessoa"
}'
```
### Exemplo 10: Criar Nota
```bash
curl -X POST http://ambienz-twenty-mcp-server:3001/tools/create_note \
-H "Content-Type: application/json" \
-d '{
"title": "Reunião de Follow-up",
"bodyV2": {
"markdown": "Cliente demonstrou interesse no produto premium. Agendar demo para próxima semana."
}
}'
```
### Exemplo 10: Criar Tarefa
```bash
curl -X POST http://ambienz-twenty-mcp-server:3001/tools/create_task \
-H "Content-Type: application/json" \
-d '{
"title": "Enviar proposta comercial",
"bodyV2": {
"markdown": "Preparar proposta técnica e comercial para o cliente"
},
"dueAt": "2024-10-30T17:00:00Z",
"status": "TODO",
"assigneeId": "uuid-do-usuario"
}'
```
### Exemplo 11: Criar Conversa (Objeto Customizado)
```bash
curl -X POST http://ambienz-twenty-mcp-server:3001/tools/create_conversa \
-H "Content-Type: application/json" \
-d '{
"name": "Atendimento Cliente ABC",
"conversasId": "conv-123",
"agent": "Agente 01",
"lead": "Lead Qualificado"
}'
```
### Exemplo 12: Criar Fatura (Objeto Customizado)
```bash
curl -X POST http://ambienz-twenty-mcp-server:3001/tools/create_fatura \
-H "Content-Type: application/json" \
-d '{
"name": "Fatura #001-2024",
"status": "PENDING"
}'
```
### Exemplo 13: Listar com Paginação
```bash
curl -X POST http://ambienz-twenty-mcp-server:3001/tools/list_people \
-H "Content-Type: application/json" \
-d '{
"limit": 20,
"startingAfter": "cursor-uuid-here",
"orderBy": "createdAt",
"depth": 1
}'
```
## Ferramentas Disponíveis
### Gestão de Pessoas
- `list_people` - Listar pessoas com filtros e paginação
- `create_person` - Criar pessoa (campos: name, emails, phones, jobTitle, companyId, linkedinLink, xLink, city, avatarUrl, chatId, position)
- `get_person` - Buscar pessoa por ID (com parâmetro depth)
- `update_person` - Atualizar pessoa
- `delete_person` - Deletar pessoa
### Gestão de Empresas
- `list_companies` - Listar empresas com filtros e paginação
- `create_company` - Criar empresa (campos: name, razaoSocial, cnpj, domainName, address, employees, annualRecurringRevenue, idealCustomerProfile, accountOwnerId, linkedinLink, xLink, position)
- `get_company` - Buscar empresa por ID (com parâmetro depth)
- `update_company` - Atualizar empresa
- `delete_company` - Deletar empresa
### Gestão de Oportunidades
- `list_opportunities` - Listar oportunidades com filtros e paginação
- `create_opportunity` - Criar oportunidade (campos: name, amount, closeDate, stage, companyId, pointOfContactId, position)
- `get_opportunity` - Buscar oportunidade por ID (com parâmetro depth)
- `update_opportunity` - Atualizar oportunidade
- `delete_opportunity` - Deletar oportunidade
### Gestão de Notas
- `list_notes` - Listar notas com filtros e paginação
- `create_note` - Criar nota (campos: title, bodyV2: { markdown, blocknote }, position)
- `get_note` - Buscar nota por ID (com parâmetro depth)
- `update_note` - Atualizar nota
- `delete_note` - Deletar nota
### Gestão de Tarefas
- `list_tasks` - Listar tarefas com filtros e paginação
- `create_task` - Criar tarefa (campos: title, bodyV2: { markdown, blocknote }, dueAt, status, assigneeId, position)
- `get_task` - Buscar tarefa por ID (com parâmetro depth)
- `update_task` - Atualizar tarefa
- `delete_task` - Deletar tarefa
### Gestão de Conversas (Objeto Customizado)
- `list_conversas` - Listar conversas com filtros e paginação
- `create_conversa` - Criar conversa (campos: name, conversasId, agent, lead, position)
- `get_conversa` - Buscar conversa por ID (com parâmetro depth)
- `update_conversa` - Atualizar conversa
- `delete_conversa` - Deletar conversa
### Gestão de Faturas (Objeto Customizado)
- `list_faturas` - Listar faturas com filtros e paginação
- `create_fatura` - Criar fatura (campos: name, status, position)
- `get_fatura` - Buscar fatura por ID (com parâmetro depth)
- `update_fatura` - Atualizar fatura
- `delete_fatura` - Deletar fatura
## Estrutura de Dados Atualizada (v0.2.0)
### Campos com Estrutura de Objeto
#### Person (name, emails, phones)
```json
{
"name": {
"firstName": "João",
"lastName": "Silva"
},
"emails": {
"primaryEmail": "joao@example.com",
"additionalEmails": ["joao.silva@example.com"]
},
"phones": {
"primaryPhoneNumber": "999999999",
"primaryPhoneCountryCode": "+55",
"additionalPhones": []
}
}
```
#### Company (amount, links)
```json
{
"annualRecurringRevenue": {
"amountMicros": 1000000000000, // valor em micros (1.000.000 = 1M BRL)
"currencyCode": "BRL"
},
"linkedinLink": {
"primaryLinkUrl": "https://linkedin.com/company/example",
"primaryLinkLabel": "LinkedIn"
}
}
```
#### Opportunity (amount)
```json
{
"amount": {
"amountMicros": 50000000000, // 50.000 BRL
"currencyCode": "BRL"
}
}
```
### Parâmetros de Paginação
Todos os endpoints `list_*` suportam:
- `filter` (string): Query JSON para filtros complexos
```json
"{\"name\": {\"firstName\": {\"ilike\": \"%João%\"}}}"
```
- `orderBy` (string): Campo para ordenação (ex: "createdAt", "name")
- `limit` (number): Número máximo de resultados (max 100)
- `depth` (number): Profundidade de relações (0-5)
- `startingAfter` (string): Cursor UUID para próxima página
- `endingBefore` (string): Cursor UUID para página anterior
### Exemplo de Resposta com Paginação
```json
{
"success": true,
"data": {
"data": {
"people": [
{...},
{...}
]
},
"pageInfo": {
"hasNextPage": true,
"startCursor": "uuid-start",
"endCursor": "uuid-end"
},
"totalCount": 150
}
}
```
## Formato de Resposta
As respostas seguem o formato:
**Sucesso:**
```json
{
"success": true,
"data": {...}, // ou "message": "..."
}
```
**Erro:**
```json
{
"success": false,
"error": "Mensagem de erro"
}
```
## Dicas de Uso
1. **Headers:** Sempre inclua `Content-Type: application/json` nos requests POST
2. **URL Interna:** Use `http://ambienz-twenty-mcp-server:3001` quando estiver na mesma rede Docker (porta: 3001)
3. **URL Externa:** Use `http://localhost:3001` quando acessar de fora do Docker
4. **Formatação JSON:** Use `-d` para enviar dados JSON no body
5. **Pretty Print:** Adicione `| jq` ao final do comando para formatar a resposta JSON
6. **Estrutura de Objetos:** Atenção aos campos que agora são objetos (name, emails, phones, amount, links)
7. **Paginação:** Use `startingAfter`/`endingBefore` com os cursores retornados em `pageInfo`
8. **Filtros:** Filters são strings JSON que precisam ser escapadas corretamente
9. **Depth:** Use `depth` para carregar relações (0 = sem relações, 1-5 = profundidade das relações)
10. **UUIDs:** Todos os IDs devem ser UUIDs válidos no formato RFC4122
## Campos Brasileiros
O servidor suporta campos específicos para o mercado brasileiro:
- `cnpj` - Cadastro Nacional de Pessoa Jurídica
- `razaoSocial` - Razão Social da empresa
- Valores em `BRL` (Real Brasileiro)
## Verificação de Status
Para verificar se o servidor está funcionando:
```bash
curl -X GET http://ambienz-twenty-mcp-server:3001/health
```
**Resposta:**
```json
{
"status": "ok",
"version": "0.2.0"
}
```
## Troubleshooting
### Erro de conexão
- Verifique se ambos os containers estão na mesma rede Docker
- Verifique se o container está rodando: `docker ps | grep ambienz-twenty-mcp`
- Verifique os logs: `docker logs ambienz-twenty-mcp-server`
- Porta atual: **3001**
### Erro de API
- Verifique se `TWENTY_API_KEY` e `TWENTY_BASE_URL` estão configurados corretamente
- Base URL padrão: `http://ambienz-twenty-server:3000/rest` (rede interna Docker)
- Teste a conexão com: `GET http://ambienz-twenty-mcp-server:3001/health`
### Resposta vazia ou erro 404
- Certifique-se de usar o método POST para executar ferramentas
- Verifique se o nome da ferramenta está correto (case-sensitive)
- Use o novo formato de URL: `/tools/{toolName}` (sem `/api`)
### Erro de validação de dados
- Verifique se os campos obrigatórios estão presentes
- Campos como `name`, `emails`, `phones` agora são objetos
- UUIDs devem estar no formato correto (ex: "550e8400-e29b-41d4-a716-446655440000")
- Valores monetários devem usar `amountMicros` (valor * 1.000.000)
### Erro 400 - Bad Request
- Verifique a estrutura JSON dos dados enviados
- Campos obrigatórios: Person (name), Company (name), Opportunity (name)
- Estrutura de filtro deve ser string JSON escapada
## Integração com n8n
### 1. Listar Ferramentas Disponíveis no n8n
**Configuração do HTTP Request Node:**
1. **Method:** GET
2. **URL:** `http://ambienz-twenty-mcp-server:3001/tools`
**Uso:** Este endpoint retorna todas as 35 ferramentas disponíveis com seus schemas completos, ideal para descobrir quais operações você pode executar. Não requer body ou headers especiais.
### 2. Executar Ferramentas Específicas no n8n
**Configuração do HTTP Request Node:**
1. **Method:** POST
2. **URL:** `http://ambienz-twenty-mcp-server:3001/tools/{{$node["function"].json["toolName"]}}`
3. **Headers:**
- `Content-Type`: `application/json`
4. **Body:** JSON com os parâmetros da ferramenta
### Exemplo de Workflow n8n
```json
{
"nodes": [
{
"parameters": {
"method": "POST",
"url": "http://ambienz-twenty-mcp-server:3001/tools/create_person",
"jsonParameters": true,
"options": {},
"bodyParametersJson": "={\n \"name\": {\n \"firstName\": \"{{ $json[\"firstName\"] }}\",\n \"lastName\": \"{{ $json[\"lastName\"] }}\"\n },\n \"emails\": {\n \"primaryEmail\": \"{{ $json[\"email\"] }}\"\n }\n}"
},
"name": "Create Person in Twenty CRM",
"type": "n8n-nodes-base.httpRequest"
}
]
}
```
## Migração da v0.1.0 para v0.2.0
### Mudanças Breaking
1. **Porta:** Mantida em 3001
2. **Base URL:** Alterada para rede interna Docker: `http://ambienz-twenty-server:3000/rest`
3. **Estrutura de Person:**
- `firstName`, `lastName` → `name: { firstName, lastName }`
- `email` → `emails: { primaryEmail }`
- `phone` → `phones: { primaryPhoneNumber, primaryPhoneCountryCode }`
4. **Estrutura de Valores:**
- `amount: 50000` → `amount: { amountMicros: 50000000000, currencyCode: "BRL" }`
5. **Paginação:**
- `offset` → `startingAfter`/`endingBefore` (cursor-based)
- `search` → `filter` (JSON query)
6. **Removido:**
- `get_metadata_objects`
- `get_object_metadata`
- `search_records`
7. **Adicionado:**
- Objetos customizados: `conversas`, `faturas`
- Parâmetro `depth` para relações
- Campos brasileiros: `cnpj`, `razaoSocial`
### Checklist de Migração
- [ ] Atualizar URL base para rede interna Docker (se necessário)
- [ ] Remover `/api` dos endpoints (agora `/tools/{toolName}`)
- [ ] Converter campos simples em objetos (name, emails, phones)
- [ ] Atualizar valores monetários para usar `amountMicros`
- [ ] Substituir `offset` por `startingAfter`/`endingBefore`
- [ ] Atualizar filtros para usar formato JSON string
- [ ] Verificar campos obrigatórios nas operações create
- [ ] Testar integrações com `depth` parameter para relações