Segue o README.md pronto, organizado para repositório corporativo.
Consignado MCP Local
Servidor MCP (Model Context Protocol – HTTP Dispatcher) para orquestração da jornada de empréstimo consignado via agente (ex: WhatsApp).
Este serviço:
- Centraliza regras de fluxo
- Resolve identidade (telefone → CPF → token)
- Impõe consistência de jornada via
correlationId - Aplica validações de segurança
- Implementa idempotência na criação de contrato
Ambiente atual: DEV (in-memory).Produção requer persistência, autenticação forte e proteção de PII.
Arquitetura
WhatsApp Agent
↓
POST /call
↓
MCP Server
↓
Mock Core APIs
O agente nunca chama core direto.Toda regra de negócio e validação de sequência passa pelo MCP.
Conceitos
correlationId
Identifica uma jornada.Tudo que acontece fica vinculado a ele.
Regras:
- O
channelnão pode mudar no meio da jornada (409). - O
customerRefnão pode trocar depois de resolvido (409).
Identity Resolution (WhatsApp)
Fluxo obrigatório no canal whatsapp:
- lookup por telefone
- se houver duplicidade → solicitar CPF
- resolver identidade
- só então liberar APIs de crédito
Se tentar pular etapa → 403.
CPF Token
- CPF nunca retorna ao agente.
- Após validação, o servidor gera
cpfToken. get_loan_offersexige esse token.- O token é validado contra a sessão.
DEV usa SHA256 simples.Produção deve usar HMAC com secret + TTL.
Endpoints
GET /tools
Lista tools disponíveis.
Response
{
"tools": [
"lookup_customer_by_phone",
"resolve_identity_by_cpf",
"get_identity_context",
"check_eligibility",
"get_loan_offers",
"create_contract",
"get_formalization_link"
]
}
POST /call
Dispatcher principal.
Request padrão
{
"tool": "string",
"input": {},
"context": {
"correlationId": "string",
"channel": "app|web|whatsapp|agencia",
"subject": "opcional"
}
}
Response padrão
{
"output": {}
}
GET /_debug/session/{cid} (DEV ONLY)
Retorna estado interno da sessão.
⚠ Remover ou proteger fortemente em produção.
Fluxo Oficial (WhatsApp)
- lookup_customer_by_phone
- resolve_identity_by_cpf (se necessário)
- get_identity_context
- check_eligibility
- get_loan_offers
- create_contract
- get_formalization_link
Tools
lookup_customer_by_phone
Resolve cliente por telefone.
Input
{ "phone": "+5511999999999" }
Output (não encontrado)
{ "found": false, "reasonCode": "INVALID_PHONE" }
Output (1 cliente)
{ "found": true, "needsCpf": false }
Output (duplicado)
{ "found": true, "needsCpf": true }
Nunca retorna lista de clientes.
resolve_identity_by_cpf
Valida CPF quando há duplicidade.
Input
{ "cpf": "11122233344" }
Output (ok)
{ "resolved": true }
Output (erro)
{ "resolved": false, "reasonCode": "CPF_MISMATCH" }
get_identity_context
Retorna identidade resolvida.
Output (sem identidade)
{ "hasIdentity": false }
Output (com identidade)
{
"hasIdentity": true,
"customerRef": "cust_tok_302556",
"cpfToken": "sha256..."
}
check_eligibility
Input
{
"customerRef": "cust_tok_302556",
"channel": "whatsapp"
}
Output
{
"eligible": true,
"eligibilityId": "uuid",
"reasonCode": null
}
Valida:
- identidade resolvida (whatsapp)
- channel consistente
- jornada correta
get_loan_offers
Recebe cpfToken + valor solicitado.
Input
{
"customerRef": "cust_tok_302556",
"eligibilityId": "uuid",
"cpfToken": "sha256...",
"requestedAmount": 5000
}
Output
{
"offers": [
{
"offerId": "offer-1",
"requestedAmount": 5000,
"approvedAmount": 5000,
"installments": 24
},
{
"offerId": "offer-2",
"requestedAmount": 5000,
"approvedAmount": 4500,
"installments": 36
}
]
}
Valida:
- eligibilityId pertence à jornada
- cpfToken bate com sessão
- requestedAmount > 0
create_contract
Possui idempotência.
Input
{
"customerRef": "cust_tok_302556",
"offerId": "offer-1",
"idempotencyKey": "uuid",
"acceptance": { "channel": "whatsapp" }
}
Output
{
"contractId": "uuid",
"status": "PENDING_VIDEO"
}
Se repetir idempotencyKey → retorna mesma resposta.
get_formalization_link
Input
{
"customerRef": "cust_tok_302556",
"contractId": "uuid"
}
Output
{
"formalizationUrl": "https://video.plataforma.local/<contractId>",
"expiresAt": "2026-12-31T23:59:59Z"
}
Códigos de Erro
| Código | Motivo |
|---|---|
| 400 | Input inválido ou campo obrigatório ausente |
| 403 | Fluxo inválido / identidade não resolvida / token incorreto |
| 409 | Conflito de jornada (channel, customerRef, eligibilityId, contractId) |
Estados de Sessão
| Estado | Significado |
|---|---|
| NOT_FOUND | Telefone não encontrado |
| PENDING_CPF | Duplicidade, aguardando CPF |
| READY | Identidade resolvida |
Rodando Local
uvicorn server:app --port 8001 --reload
Requisitos de Produção
- Persistência externa (Redis/Dynamo)
- Autenticação forte (JWT + mTLS)
- HMAC real para cpfToken
- Auditoria estruturada por tool
- Rate limit por telefone
- Proteção total de PII
- Remoção do endpoint de debug
Observação Final
Este MCP centraliza:
- Controle de jornada
- Segurança de identidade
- Consistência transacional
- Blindagem do core contra chamadas fora de ordem
Ele não é apenas mock de API.É camada de governança de fluxo.