@marcelocorrea/mcp-safrapay 0.2.0
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 +335 -0
- package/dist/index.js +564 -0
- package/package.json +57 -0
package/README.md
ADDED
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
# SafraPay MCP Server
|
|
2
|
+
|
|
3
|
+
Servidor MCP (Model Context Protocol) para integração com a API SafraPay, permitindo que agentes de IA realizem operações completas de pagamento, gestão de clientes, recorrência e muito mais.
|
|
4
|
+
|
|
5
|
+
## 🚀 Versão 0.2.0 - Arquitetura Agrupada com Autenticação Automática
|
|
6
|
+
|
|
7
|
+
Esta versão implementa uma arquitetura agrupada onde **12 ferramentas** cobrem **110+ endpoints** da API SafraPay, ao invés de criar uma ferramenta por endpoint.
|
|
8
|
+
|
|
9
|
+
### ⚡ Autenticação Automática
|
|
10
|
+
|
|
11
|
+
O servidor gerencia a autenticação **completamente de forma automática**:
|
|
12
|
+
- ✅ Gera token automaticamente na primeira requisição
|
|
13
|
+
- ✅ Reautentica automaticamente quando o token expira (erro 401)
|
|
14
|
+
- ✅ Usa as credenciais configuradas via variáveis de ambiente
|
|
15
|
+
- ✅ **Você NUNCA precisa se preocupar com autenticação!**
|
|
16
|
+
|
|
17
|
+
### Benefícios da Arquitetura Agrupada
|
|
18
|
+
|
|
19
|
+
- ✅ **Escalável**: Não há limite de ferramentas para gerenciar
|
|
20
|
+
- ✅ **Organizada**: Ferramentas agrupadas por contexto funcional
|
|
21
|
+
- ✅ **Flexível**: Agente IA monta as requisições baseado na documentação
|
|
22
|
+
- ✅ **Completa**: Acesso a toda a API SafraPay com documentação embarcada
|
|
23
|
+
- ✅ **Automática**: Autenticação e renovação de token transparentes
|
|
24
|
+
|
|
25
|
+
## 📦 Instalação
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install
|
|
29
|
+
npm run build
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## ⚙️ Configuração
|
|
33
|
+
|
|
34
|
+
Crie um arquivo `.env` na raiz do projeto:
|
|
35
|
+
|
|
36
|
+
```env
|
|
37
|
+
# Ambiente: HML ou PROD
|
|
38
|
+
SAFRA_ENV=HML
|
|
39
|
+
|
|
40
|
+
# Credenciais (obtenha no portal SafraPay)
|
|
41
|
+
SAFRA_CLIENT_ID=seu-client-id
|
|
42
|
+
SAFRA_CLIENT_SECRET=seu-merchant-token
|
|
43
|
+
|
|
44
|
+
# Token (opcional - será gerado automaticamente)
|
|
45
|
+
SAFRA_ACCESS_TOKEN=
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## 🔧 Configuração no Claude Code
|
|
49
|
+
|
|
50
|
+
Adicione ao arquivo de configuração do MCP:
|
|
51
|
+
|
|
52
|
+
```json
|
|
53
|
+
{
|
|
54
|
+
"mcpServers": {
|
|
55
|
+
"safrapay": {
|
|
56
|
+
"command": "node",
|
|
57
|
+
"args": ["/caminho/para/banco-safra-mcp/dist/index.js"],
|
|
58
|
+
"env": {
|
|
59
|
+
"SAFRA_ENV": "HML",
|
|
60
|
+
"SAFRA_CLIENT_SECRET": "seu-merchant-token"
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## 🛠️ Ferramentas Disponíveis
|
|
68
|
+
|
|
69
|
+
O servidor expõe **12 ferramentas agrupadas** que cobrem toda a API SafraPay:
|
|
70
|
+
|
|
71
|
+
### 1. `safrapay_authentication`
|
|
72
|
+
Gestão de usuários SafraPay
|
|
73
|
+
- CRUD de usuários
|
|
74
|
+
- Listar merchants do usuário
|
|
75
|
+
|
|
76
|
+
**IMPORTANTE**: A autenticação de token é **AUTOMÁTICA**. Não é necessário chamar endpoints de autenticação manualmente.
|
|
77
|
+
|
|
78
|
+
### 2. `safrapay_payments`
|
|
79
|
+
Processamento de pagamentos completo
|
|
80
|
+
- Clientes (customers)
|
|
81
|
+
- Cartão de crédito/débito
|
|
82
|
+
- 3D Secure (3DS)
|
|
83
|
+
- PIX
|
|
84
|
+
- Boleto
|
|
85
|
+
- Consulta de BIN
|
|
86
|
+
- Produtos
|
|
87
|
+
- Planos de taxas
|
|
88
|
+
|
|
89
|
+
### 3. `safrapay_charges`
|
|
90
|
+
Gestão de cobranças
|
|
91
|
+
- Buscar cobrança
|
|
92
|
+
- Capturar pré-autorização
|
|
93
|
+
- Cancelar/estornar
|
|
94
|
+
|
|
95
|
+
### 4. `safrapay_vault`
|
|
96
|
+
Tokenização de cartões (Cartão Protegido)
|
|
97
|
+
- Salvar cartão
|
|
98
|
+
- Atualizar cartão
|
|
99
|
+
- Buscar cartões
|
|
100
|
+
- Cartão temporário
|
|
101
|
+
- Validação zero dollar
|
|
102
|
+
|
|
103
|
+
### 5. `safrapay_recurrence`
|
|
104
|
+
Planos e assinaturas recorrentes
|
|
105
|
+
- CRUD de planos
|
|
106
|
+
- CRUD de assinaturas
|
|
107
|
+
- Assinaturas em lote
|
|
108
|
+
- Relatórios
|
|
109
|
+
|
|
110
|
+
### 6. `safrapay_payment_link`
|
|
111
|
+
Links de pagamento (SmartCheckout)
|
|
112
|
+
- Criar link
|
|
113
|
+
- Listar links
|
|
114
|
+
- Detalhes e exclusão
|
|
115
|
+
|
|
116
|
+
### 7. `safrapay_checkout`
|
|
117
|
+
Sessões de checkout
|
|
118
|
+
- Checkout Redirect
|
|
119
|
+
- Checkout Lightbox
|
|
120
|
+
- Checkout Transparente
|
|
121
|
+
|
|
122
|
+
### 8. `safrapay_split`
|
|
123
|
+
Split de pagamentos
|
|
124
|
+
- Gestão de recebedores
|
|
125
|
+
- Configuração de split
|
|
126
|
+
- Extrato digital
|
|
127
|
+
- Saldo disponível
|
|
128
|
+
|
|
129
|
+
### 9. `safrapay_accreditation`
|
|
130
|
+
Credenciamento
|
|
131
|
+
- Gestão de merchants
|
|
132
|
+
- Sub-merchants
|
|
133
|
+
- Taxas e produtos
|
|
134
|
+
- Upload de documentos
|
|
135
|
+
- Reconciliação
|
|
136
|
+
- Adquirentes virtuais
|
|
137
|
+
|
|
138
|
+
### 10. `safrapay_webhook`
|
|
139
|
+
Webhooks para eventos
|
|
140
|
+
- Criar webhooks
|
|
141
|
+
- Listar webhooks
|
|
142
|
+
- Cancelar webhook
|
|
143
|
+
|
|
144
|
+
### 11. `safrapay_chargeback`
|
|
145
|
+
Gestão de disputas
|
|
146
|
+
- Resumo de disputas
|
|
147
|
+
- Detalhes de disputa
|
|
148
|
+
- Aceitar débito
|
|
149
|
+
- Representação secundária
|
|
150
|
+
|
|
151
|
+
### 12. `safrapay_tef`
|
|
152
|
+
Integração com PinPads
|
|
153
|
+
- Fluxo transacional completo
|
|
154
|
+
- Funções auxiliares
|
|
155
|
+
|
|
156
|
+
## 💡 Exemplos de Uso
|
|
157
|
+
|
|
158
|
+
### Exemplo 1: Criar uma transação de crédito
|
|
159
|
+
|
|
160
|
+
```
|
|
161
|
+
Usuário: "Crie uma transação de crédito de R$ 100,00"
|
|
162
|
+
|
|
163
|
+
Agente IA usa: safrapay_payments
|
|
164
|
+
{
|
|
165
|
+
"api": "GATEWAY",
|
|
166
|
+
"method": "POST",
|
|
167
|
+
"path": "/v2/charge/authorization",
|
|
168
|
+
"body": {
|
|
169
|
+
"charge": {
|
|
170
|
+
"merchantChargeId": "ORDER-123",
|
|
171
|
+
"transactions": [{
|
|
172
|
+
"card": {
|
|
173
|
+
"cardholderName": "JOAO SILVA",
|
|
174
|
+
"cardNumber": "4111111111111111",
|
|
175
|
+
"expirationMonth": 12,
|
|
176
|
+
"expirationYear": 2025,
|
|
177
|
+
"securityCode": "123"
|
|
178
|
+
},
|
|
179
|
+
"paymentType": 2,
|
|
180
|
+
"amount": 10000,
|
|
181
|
+
"installmentNumber": 1,
|
|
182
|
+
"installmentType": 0,
|
|
183
|
+
"autoCapture": true
|
|
184
|
+
}],
|
|
185
|
+
"source": 1
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Exemplo 2: Criar cobrança PIX
|
|
192
|
+
|
|
193
|
+
```
|
|
194
|
+
Usuário: "Crie uma cobrança PIX de R$ 50,00"
|
|
195
|
+
|
|
196
|
+
Agente IA usa: safrapay_payments
|
|
197
|
+
{
|
|
198
|
+
"api": "GATEWAY",
|
|
199
|
+
"method": "POST",
|
|
200
|
+
"path": "/v2/charge/pix",
|
|
201
|
+
"body": {
|
|
202
|
+
"charge": {
|
|
203
|
+
"merchantChargeId": "PIX-456",
|
|
204
|
+
"transactions": [{
|
|
205
|
+
"amount": 5000,
|
|
206
|
+
"paymentType": "Pix"
|
|
207
|
+
}],
|
|
208
|
+
"source": 1
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### Exemplo 3: Criar assinatura recorrente
|
|
215
|
+
|
|
216
|
+
```
|
|
217
|
+
Usuário: "Crie uma assinatura mensal de R$ 99,90"
|
|
218
|
+
|
|
219
|
+
Passo 1 - Criar plano (safrapay_recurrence):
|
|
220
|
+
{
|
|
221
|
+
"api": "PORTAL",
|
|
222
|
+
"method": "POST",
|
|
223
|
+
"path": "/plan",
|
|
224
|
+
"body": {
|
|
225
|
+
"name": "Plano Premium",
|
|
226
|
+
"amount": 9990,
|
|
227
|
+
"interval": 3,
|
|
228
|
+
"intervalCount": 1
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
Passo 2 - Criar assinatura (safrapay_recurrence):
|
|
233
|
+
{
|
|
234
|
+
"api": "GATEWAY",
|
|
235
|
+
"method": "POST",
|
|
236
|
+
"path": "/subscription",
|
|
237
|
+
"body": {
|
|
238
|
+
"planId": "plan-123",
|
|
239
|
+
"customerId": "customer-456",
|
|
240
|
+
"cardToken": "token-abc"
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## 📚 Documentação Completa
|
|
246
|
+
|
|
247
|
+
Consulte os arquivos na raiz do projeto:
|
|
248
|
+
|
|
249
|
+
- **`SAFRAPAY_API_MAPPING.md`**: Mapeamento completo de todas as rotas organizadas por grupo
|
|
250
|
+
- **`API_DOCUMENTATION.md`**: Documentação técnica detalhada com exemplos de request/response
|
|
251
|
+
|
|
252
|
+
## 🔑 Enumeradores Importantes
|
|
253
|
+
|
|
254
|
+
### Status de Transação
|
|
255
|
+
- `1` - Pendente
|
|
256
|
+
- `2` - Autorizada
|
|
257
|
+
- `3` - Capturada
|
|
258
|
+
- `4` - Cancelada
|
|
259
|
+
- `5` - Negada
|
|
260
|
+
- `6` - Estornada
|
|
261
|
+
|
|
262
|
+
### Tipos de Pagamento
|
|
263
|
+
- `2` - Crédito
|
|
264
|
+
- `3` - Débito
|
|
265
|
+
- `4` - Boleto
|
|
266
|
+
- `5` - PIX
|
|
267
|
+
- `"Pix"` - PIX (string)
|
|
268
|
+
- `"Boleto"` - Boleto (string)
|
|
269
|
+
|
|
270
|
+
### Tipos de Parcelamento
|
|
271
|
+
- `0` - À vista
|
|
272
|
+
- `2` - Emissor (com juros)
|
|
273
|
+
- `3` - Lojista (sem juros)
|
|
274
|
+
|
|
275
|
+
### Intervalos de Recorrência
|
|
276
|
+
- `1` - Diário
|
|
277
|
+
- `2` - Semanal
|
|
278
|
+
- `3` - Mensal
|
|
279
|
+
- `4` - Anual
|
|
280
|
+
|
|
281
|
+
### Source (Origem)
|
|
282
|
+
- `1` - E-commerce/API
|
|
283
|
+
- `2` - Mobile
|
|
284
|
+
- `3` - Recorrência
|
|
285
|
+
- `4` - Telefone
|
|
286
|
+
|
|
287
|
+
## 🌐 Ambientes
|
|
288
|
+
|
|
289
|
+
### Homologação (HML)
|
|
290
|
+
- Portal API: `https://portal-api-hml.safrapay.com.br`
|
|
291
|
+
- Gateway API: `https://payment-hml.safrapay.com.br`
|
|
292
|
+
- Reconciliation API: `https://reconciliation-api-hml.safrapay.com.br`
|
|
293
|
+
|
|
294
|
+
### Produção (PROD)
|
|
295
|
+
- Portal API: `https://portal-api.safrapay.com.br`
|
|
296
|
+
- Gateway API: `https://payment.safrapay.com.br`
|
|
297
|
+
- Reconciliation API: `https://reconciliation-api.safrapay.com.br`
|
|
298
|
+
|
|
299
|
+
## ⚡ Desenvolvimento
|
|
300
|
+
|
|
301
|
+
```bash
|
|
302
|
+
# Compilar
|
|
303
|
+
npm run build
|
|
304
|
+
|
|
305
|
+
# Modo watch (desenvolvimento)
|
|
306
|
+
npm run dev
|
|
307
|
+
|
|
308
|
+
# Executar
|
|
309
|
+
npm start
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
## 🔒 Segurança
|
|
313
|
+
|
|
314
|
+
- NUNCA armazene dados de cartão completos
|
|
315
|
+
- Use tokenização sempre que possível
|
|
316
|
+
- Implemente validação zero dollar antes de cobranças recorrentes
|
|
317
|
+
- Utilize HTTPS em todos os endpoints
|
|
318
|
+
- Monitore transações suspeitas
|
|
319
|
+
|
|
320
|
+
## 🤝 Contribuindo
|
|
321
|
+
|
|
322
|
+
Este é um projeto em desenvolvimento ativo. Sugestões e melhorias são bem-vindas!
|
|
323
|
+
|
|
324
|
+
## 📄 Licença
|
|
325
|
+
|
|
326
|
+
ISC
|
|
327
|
+
|
|
328
|
+
## 👤 Autor
|
|
329
|
+
|
|
330
|
+
Marcelo Correa
|
|
331
|
+
|
|
332
|
+
---
|
|
333
|
+
|
|
334
|
+
**Versão**: 0.2.0
|
|
335
|
+
**Última atualização**: Janeiro 2026
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,564 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
|
|
8
|
+
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
9
|
+
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
|
|
10
|
+
const axios_1 = __importDefault(require("axios"));
|
|
11
|
+
const zod_to_json_schema_1 = require("zod-to-json-schema");
|
|
12
|
+
const dotenv_1 = __importDefault(require("dotenv"));
|
|
13
|
+
const zod_1 = require("zod");
|
|
14
|
+
dotenv_1.default.config();
|
|
15
|
+
// --- Configuração de Constantes e Tipos ---
|
|
16
|
+
const API_ENVS = {
|
|
17
|
+
HML: {
|
|
18
|
+
PORTAL: "https://portal-api-hml.safrapay.com.br",
|
|
19
|
+
GATEWAY: "https://payment-hml.safrapay.com.br",
|
|
20
|
+
RECONCILIATION: "https://reconciliation-api-hml.safrapay.com.br"
|
|
21
|
+
},
|
|
22
|
+
PROD: {
|
|
23
|
+
PORTAL: "https://portal-api.safrapay.com.br",
|
|
24
|
+
GATEWAY: "https://payment.safrapay.com.br",
|
|
25
|
+
RECONCILIATION: "https://reconciliation-api.safrapay.com.br"
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
class SafraPayServer {
|
|
29
|
+
server;
|
|
30
|
+
env;
|
|
31
|
+
axiosInstances;
|
|
32
|
+
token = null;
|
|
33
|
+
merchantToken;
|
|
34
|
+
isAuthenticating = false;
|
|
35
|
+
constructor() {
|
|
36
|
+
this.server = new index_js_1.Server({
|
|
37
|
+
name: "@marcelocorrea/mcp-safrapay",
|
|
38
|
+
version: "0.2.0",
|
|
39
|
+
}, {
|
|
40
|
+
capabilities: {
|
|
41
|
+
tools: {},
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
// Determina ambiente (Default: HML para segurança)
|
|
45
|
+
this.env = (process.env.SAFRA_ENV === "PROD") ? "PROD" : "HML";
|
|
46
|
+
this.token = process.env.SAFRA_ACCESS_TOKEN || null;
|
|
47
|
+
// Valida se o MerchantToken está configurado
|
|
48
|
+
const merchantToken = process.env.SAFRA_CLIENT_SECRET;
|
|
49
|
+
if (!merchantToken) {
|
|
50
|
+
throw new Error("SAFRA_CLIENT_SECRET (MerchantToken) não configurado. " +
|
|
51
|
+
"Por favor, configure a variável de ambiente antes de iniciar o servidor.");
|
|
52
|
+
}
|
|
53
|
+
this.merchantToken = merchantToken;
|
|
54
|
+
console.error(`[SafraPay MCP] Ambiente: ${this.env}`);
|
|
55
|
+
console.error(`[SafraPay MCP] Token configurado: ${this.token ? "Sim" : "Não (será gerado automaticamente)"}`);
|
|
56
|
+
console.error(`[SafraPay MCP] MerchantToken presente: Sim`);
|
|
57
|
+
// Inicializa instâncias Axios para cada serviço base
|
|
58
|
+
this.axiosInstances = {
|
|
59
|
+
PORTAL: this.createAxiosInstance(API_ENVS[this.env].PORTAL),
|
|
60
|
+
GATEWAY: this.createAxiosInstance(API_ENVS[this.env].GATEWAY),
|
|
61
|
+
RECONCILIATION: this.createAxiosInstance(API_ENVS[this.env].RECONCILIATION),
|
|
62
|
+
};
|
|
63
|
+
this.setupToolHandlers();
|
|
64
|
+
// Error handling
|
|
65
|
+
this.server.onerror = (error) => console.error("[MCP Error]", error);
|
|
66
|
+
process.on("SIGINT", async () => {
|
|
67
|
+
await this.server.close();
|
|
68
|
+
process.exit(0);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
createAxiosInstance(baseURL) {
|
|
72
|
+
const instance = axios_1.default.create({
|
|
73
|
+
baseURL,
|
|
74
|
+
headers: {
|
|
75
|
+
"Content-Type": "application/json",
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
// Interceptor de requisição: adiciona token
|
|
79
|
+
instance.interceptors.request.use((config) => {
|
|
80
|
+
if (this.token) {
|
|
81
|
+
config.headers.Authorization = `Bearer ${this.token}`;
|
|
82
|
+
}
|
|
83
|
+
return config;
|
|
84
|
+
});
|
|
85
|
+
// Interceptor de resposta: reautentica automaticamente em caso de 401
|
|
86
|
+
instance.interceptors.response.use((response) => response, async (error) => {
|
|
87
|
+
const originalRequest = error.config;
|
|
88
|
+
// Se recebeu 401 e ainda não tentou reautenticar
|
|
89
|
+
if (error.response?.status === 401 && !originalRequest._retry) {
|
|
90
|
+
originalRequest._retry = true;
|
|
91
|
+
try {
|
|
92
|
+
// Reautentica automaticamente
|
|
93
|
+
await this.autoAuthenticate();
|
|
94
|
+
// Atualiza o header com o novo token
|
|
95
|
+
originalRequest.headers.Authorization = `Bearer ${this.token}`;
|
|
96
|
+
// Retenta a requisição original
|
|
97
|
+
return instance(originalRequest);
|
|
98
|
+
}
|
|
99
|
+
catch (authError) {
|
|
100
|
+
console.error("[SafraPay MCP] Falha na reautenticação automática:", authError);
|
|
101
|
+
return Promise.reject(error);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return Promise.reject(error);
|
|
105
|
+
});
|
|
106
|
+
return instance;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Autentica automaticamente usando as credenciais configuradas
|
|
110
|
+
*/
|
|
111
|
+
async autoAuthenticate() {
|
|
112
|
+
// Evita múltiplas chamadas simultâneas de autenticação
|
|
113
|
+
if (this.isAuthenticating) {
|
|
114
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
this.isAuthenticating = true;
|
|
118
|
+
try {
|
|
119
|
+
console.error("[SafraPay MCP] Gerando novo token automaticamente...");
|
|
120
|
+
const response = await axios_1.default.post(`${API_ENVS[this.env].PORTAL}/v1/Login/GenerateToken`, {}, {
|
|
121
|
+
headers: {
|
|
122
|
+
"MerchantToken": this.merchantToken,
|
|
123
|
+
"Content-Type": "application/json"
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
if (response.data && response.data.generatedToken) {
|
|
127
|
+
this.token = response.data.generatedToken;
|
|
128
|
+
console.error("[SafraPay MCP] Token gerado com sucesso!");
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
throw new Error("Token não retornado pela API");
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
finally {
|
|
135
|
+
this.isAuthenticating = false;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
setupToolHandlers() {
|
|
139
|
+
this.server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
|
|
140
|
+
tools: [
|
|
141
|
+
{
|
|
142
|
+
name: "safrapay_authentication",
|
|
143
|
+
description: `Gestão de usuários SafraPay.
|
|
144
|
+
|
|
145
|
+
NOTA: A autenticação de token é AUTOMÁTICA. O servidor reautentica automaticamente quando necessário usando as credenciais configuradas via variáveis de ambiente. Você NÃO precisa chamar os endpoints de autenticação manualmente.
|
|
146
|
+
|
|
147
|
+
GESTÃO DE USUÁRIOS:
|
|
148
|
+
- POST /v1/User - Criar: { name, email, password, phone?, role? }
|
|
149
|
+
- GET /v1/User - Buscar: query { userId? }
|
|
150
|
+
- PUT /v1/User - Atualizar: { userId, name?, email?, phone? }
|
|
151
|
+
- GET /v1/User/Merchants - Listar merchants: query { currentPage?, pageSize?, sortDirection? }
|
|
152
|
+
- DELETE /v1/User/{userId} - Deletar
|
|
153
|
+
|
|
154
|
+
Use 'api' para especificar PORTAL ou GATEWAY, 'method' para o verbo HTTP, 'path' para o endpoint e 'body' para dados.`,
|
|
155
|
+
inputSchema: (0, zod_to_json_schema_1.zodToJsonSchema)(zod_1.z.object({
|
|
156
|
+
api: zod_1.z.enum(["PORTAL", "GATEWAY"]).describe("API base (PORTAL ou GATEWAY)"),
|
|
157
|
+
method: zod_1.z.enum(["GET", "POST", "PUT", "DELETE"]).describe("Método HTTP"),
|
|
158
|
+
path: zod_1.z.string().describe("Caminho do endpoint"),
|
|
159
|
+
body: zod_1.z.record(zod_1.z.any()).optional().describe("Corpo da requisição JSON"),
|
|
160
|
+
params: zod_1.z.record(zod_1.z.any()).optional().describe("Query parameters"),
|
|
161
|
+
})),
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
name: "safrapay_payments",
|
|
165
|
+
description: `Processamento de pagamentos: cartão, PIX, boleto, produtos e taxas.
|
|
166
|
+
|
|
167
|
+
CLIENTES (Customers):
|
|
168
|
+
- POST /customer - Criar: { merchantCustomerId, name, email?, birthDate?, phone?, document?, address? }
|
|
169
|
+
- PUT /customer - Atualizar: mesma estrutura
|
|
170
|
+
- GET /customer - Buscar: query { customerId?, merchantCustomerId? }
|
|
171
|
+
|
|
172
|
+
CARTÃO DE CRÉDITO:
|
|
173
|
+
- POST /v2/charge/authorization - Transação: { charge: { merchantChargeId, customer?, transactions: [{ card: { cardholderName, cardNumber, expirationMonth, expirationYear, securityCode }, paymentType: 2, amount, installmentNumber, installmentType, autoCapture?, softDescriptor? }], source: 1 } }
|
|
174
|
+
- POST /v2/charge/preauthorization - Pré-autorização
|
|
175
|
+
- POST /v2/charge/preauthorization/incremental - Incremental: { chargeId, transactionId, incrementalAmount }
|
|
176
|
+
- POST /v2/charge/capture - Captura: { chargeId, transactionId?, amount? }
|
|
177
|
+
|
|
178
|
+
3DS (3D Secure):
|
|
179
|
+
- POST /v2/charge/ecommerce/3ds/setup - Setup
|
|
180
|
+
- PUT /v2/charge/ecommerce/3ds/enrollment - Enrollment
|
|
181
|
+
- PUT /v2/charge/ecommerce - Transação 3DS
|
|
182
|
+
|
|
183
|
+
PIX:
|
|
184
|
+
- POST /v2/charge/pix - Criar: { charge: { merchantChargeId, transactions: [{ amount, paymentType: "Pix", expirationDate? }], source: 1 } }
|
|
185
|
+
Response: { chargeId, transactions: [{ qrCode, qrCodeText }] }
|
|
186
|
+
|
|
187
|
+
BOLETO:
|
|
188
|
+
- POST /v2/charge/boleto - Criar: { charge: { merchantChargeId, customer, transactions: [{ amount, paymentType: "Boleto", dueDate, instructions?, fine?, interest?, discount? }] } }
|
|
189
|
+
- GET /v2/charge/{chargeId}/boleto/{transactionId} - Consultar
|
|
190
|
+
|
|
191
|
+
BIN:
|
|
192
|
+
- GET /Card/Bin/Brand/{bin} - Consultar bandeira
|
|
193
|
+
|
|
194
|
+
PRODUTOS:
|
|
195
|
+
- POST /v1/product - Criar: { name, description?, price, sku?, active? }
|
|
196
|
+
- GET /v1/product - Listar: query { currentPage?, pageSize?, active? }
|
|
197
|
+
- PUT /v1/product/{productId} - Atualizar
|
|
198
|
+
- GET /v1/product/{productId} - Buscar
|
|
199
|
+
|
|
200
|
+
TAXAS:
|
|
201
|
+
- POST /tax - Criar: { name, description?, fees: [{ paymentType, installmentNumber, fee, fixedFee? }] }
|
|
202
|
+
- GET /tax - Listar
|
|
203
|
+
- PUT /tax - Atualizar
|
|
204
|
+
- DELETE /tax/{taxPlanId} - Deletar
|
|
205
|
+
- PUT /tax/Activate/{taxPlanId} - Ativar
|
|
206
|
+
|
|
207
|
+
VALORES: em centavos (1000 = R$ 10,00)
|
|
208
|
+
paymentType: 2=Crédito, 3=Débito
|
|
209
|
+
installmentType: 0=À vista, 2=Com juros, 3=Sem juros`,
|
|
210
|
+
inputSchema: (0, zod_to_json_schema_1.zodToJsonSchema)(zod_1.z.object({
|
|
211
|
+
api: zod_1.z.enum(["PORTAL", "GATEWAY"]).describe("API base"),
|
|
212
|
+
method: zod_1.z.enum(["GET", "POST", "PUT", "DELETE"]).describe("Método HTTP"),
|
|
213
|
+
path: zod_1.z.string().describe("Caminho do endpoint"),
|
|
214
|
+
body: zod_1.z.record(zod_1.z.any()).optional().describe("Corpo JSON"),
|
|
215
|
+
params: zod_1.z.record(zod_1.z.any()).optional().describe("Query parameters"),
|
|
216
|
+
})),
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
name: "safrapay_charges",
|
|
220
|
+
description: `Gestão de cobranças: buscar, capturar e cancelar.
|
|
221
|
+
|
|
222
|
+
ENDPOINTS:
|
|
223
|
+
- GET /v2/charge/{chargeId} - Buscar cobrança
|
|
224
|
+
Response: { chargeId, merchantChargeId, status, amount, transactions: [...] }
|
|
225
|
+
|
|
226
|
+
- POST /v2/charge/capture - Capturar cobrança pré-autorizada
|
|
227
|
+
Body: { chargeId, transactionId?, amount? }
|
|
228
|
+
|
|
229
|
+
- POST /v2/charge/cancelation - Cancelar/Estornar cobrança
|
|
230
|
+
Body: { chargeId, transactionId?, amount? }
|
|
231
|
+
|
|
232
|
+
STATUS: 1=Pendente, 2=Autorizada, 3=Capturada, 4=Cancelada, 5=Negada, 6=Estornada`,
|
|
233
|
+
inputSchema: (0, zod_to_json_schema_1.zodToJsonSchema)(zod_1.z.object({
|
|
234
|
+
method: zod_1.z.enum(["GET", "POST"]).describe("Método HTTP"),
|
|
235
|
+
path: zod_1.z.string().describe("Caminho do endpoint (ex: /v2/charge/{chargeId})"),
|
|
236
|
+
body: zod_1.z.record(zod_1.z.any()).optional().describe("Corpo JSON"),
|
|
237
|
+
})),
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
name: "safrapay_vault",
|
|
241
|
+
description: `Tokenização e armazenamento seguro de cartões (Cartão Protegido).
|
|
242
|
+
|
|
243
|
+
CARTÃO:
|
|
244
|
+
- POST /card - Salvar: { customerId, card: { cardholderName, cardNumber, expirationMonth, expirationYear, securityCode }, alias? }
|
|
245
|
+
Response: { cardToken, maskedCardNumber, cardBrand }
|
|
246
|
+
|
|
247
|
+
- PUT /card - Atualizar: { cardToken, expirationMonth?, expirationYear?, alias? }
|
|
248
|
+
|
|
249
|
+
- GET /card - Buscar: query { cardToken }
|
|
250
|
+
|
|
251
|
+
- GET /card/byCustomer - Por cliente: query { customerId }
|
|
252
|
+
|
|
253
|
+
- DELETE /card/{cardId} - Deletar
|
|
254
|
+
|
|
255
|
+
CARTÃO TEMPORÁRIO:
|
|
256
|
+
- POST /temporary/card - Criar: { card: {...} }
|
|
257
|
+
Response: { temporaryToken, expiresIn }
|
|
258
|
+
|
|
259
|
+
VALIDAÇÃO ZERO DOLLAR:
|
|
260
|
+
- POST /card/validation/zerodollar - Validar: { customerId, card: {...} }
|
|
261
|
+
Response: { cardToken, validationResult, transactionId }
|
|
262
|
+
|
|
263
|
+
Use cardToken nas transações ao invés dos dados completos do cartão.`,
|
|
264
|
+
inputSchema: (0, zod_to_json_schema_1.zodToJsonSchema)(zod_1.z.object({
|
|
265
|
+
method: zod_1.z.enum(["GET", "POST", "PUT", "DELETE"]).describe("Método HTTP"),
|
|
266
|
+
path: zod_1.z.string().describe("Caminho do endpoint"),
|
|
267
|
+
body: zod_1.z.record(zod_1.z.any()).optional().describe("Corpo JSON"),
|
|
268
|
+
params: zod_1.z.record(zod_1.z.any()).optional().describe("Query parameters"),
|
|
269
|
+
})),
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
name: "safrapay_recurrence",
|
|
273
|
+
description: `Gestão de planos e assinaturas recorrentes.
|
|
274
|
+
|
|
275
|
+
PLANOS:
|
|
276
|
+
- POST /plan - Criar: { name, description?, amount, interval: 1-4 (1=Diário, 2=Semanal, 3=Mensal, 4=Anual), intervalCount, trialDays?, cycles?, active? }
|
|
277
|
+
- PUT /plan - Atualizar: { planId, ... }
|
|
278
|
+
- GET /plan/all - Listar: query { currentPage?, pageSize?, active? }
|
|
279
|
+
- DELETE /plan - Deletar: query { planId }
|
|
280
|
+
|
|
281
|
+
ASSINATURAS:
|
|
282
|
+
- POST /subscription - Criar: { planId, customerId, cardToken?, startDate?, description?, metadata? }
|
|
283
|
+
- POST /subscription/bulk - Em lote: { subscriptions: [{...}] }
|
|
284
|
+
- PUT /subscription/cancelation/{subscriptionId} - Cancelar: { cancelReason? }
|
|
285
|
+
- GET /subscription/{subscriptionId} - Buscar
|
|
286
|
+
- GET /subscription - Listar: query { currentPage?, pageSize?, status?, customerId? }
|
|
287
|
+
- GET /subscription/report - Relatório: query { startDate, endDate, format? }
|
|
288
|
+
- PATCH /subscription/{subscriptionId} - Atualizar: { cardToken?, metadata? }
|
|
289
|
+
|
|
290
|
+
VALORES: amount em centavos
|
|
291
|
+
cycles: null = infinito`,
|
|
292
|
+
inputSchema: (0, zod_to_json_schema_1.zodToJsonSchema)(zod_1.z.object({
|
|
293
|
+
api: zod_1.z.enum(["PORTAL", "GATEWAY"]).describe("API base"),
|
|
294
|
+
method: zod_1.z.enum(["GET", "POST", "PUT", "DELETE", "PATCH"]).describe("Método HTTP"),
|
|
295
|
+
path: zod_1.z.string().describe("Caminho do endpoint"),
|
|
296
|
+
body: zod_1.z.record(zod_1.z.any()).optional().describe("Corpo JSON"),
|
|
297
|
+
params: zod_1.z.record(zod_1.z.any()).optional().describe("Query parameters"),
|
|
298
|
+
})),
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
name: "safrapay_payment_link",
|
|
302
|
+
description: `Links de pagamento (SmartCheckout).
|
|
303
|
+
|
|
304
|
+
ENDPOINTS:
|
|
305
|
+
- POST /paymentlink - Criar: { name, description?, amount, maxInstallments?, expirationDate?, paymentTypes?, metadata? }
|
|
306
|
+
Response: { smartcheckoutId, url }
|
|
307
|
+
|
|
308
|
+
- GET /smartcheckout/{smartcheckoutId}/detail - Detalhes
|
|
309
|
+
|
|
310
|
+
- DELETE /smartcheckout/{smartcheckoutId} - Deletar
|
|
311
|
+
|
|
312
|
+
- GET /smartcheckout - Listar: query { currentPage?, pageSize?, status? }
|
|
313
|
+
|
|
314
|
+
paymentTypes: 2=Crédito, 3=Débito, 4=Boleto, 5=Pix`,
|
|
315
|
+
inputSchema: (0, zod_to_json_schema_1.zodToJsonSchema)(zod_1.z.object({
|
|
316
|
+
method: zod_1.z.enum(["GET", "POST", "DELETE"]).describe("Método HTTP"),
|
|
317
|
+
path: zod_1.z.string().describe("Caminho do endpoint"),
|
|
318
|
+
body: zod_1.z.record(zod_1.z.any()).optional().describe("Corpo JSON"),
|
|
319
|
+
params: zod_1.z.record(zod_1.z.any()).optional().describe("Query parameters"),
|
|
320
|
+
})),
|
|
321
|
+
},
|
|
322
|
+
{
|
|
323
|
+
name: "safrapay_checkout",
|
|
324
|
+
description: `Criação de sessões de checkout com SDK.
|
|
325
|
+
|
|
326
|
+
ENDPOINTS:
|
|
327
|
+
- POST /smartcheckout - Criar: { charge: { merchantChargeId, amount, customer?, source: 1 }, settings: { type: 1-3 (1=Redirect, 2=Lightbox, 3=Transparente), paymentTypes?, maxInstallments?, returnUrl?, callbackUrl? } }
|
|
328
|
+
Response: { smartcheckoutId, url?, token? }
|
|
329
|
+
|
|
330
|
+
- GET /smartcheckout/{smartcheckoutId}/detail - Detalhes
|
|
331
|
+
|
|
332
|
+
SDKs disponíveis para integração frontend.`,
|
|
333
|
+
inputSchema: (0, zod_to_json_schema_1.zodToJsonSchema)(zod_1.z.object({
|
|
334
|
+
method: zod_1.z.enum(["GET", "POST"]).describe("Método HTTP"),
|
|
335
|
+
path: zod_1.z.string().describe("Caminho do endpoint"),
|
|
336
|
+
body: zod_1.z.record(zod_1.z.any()).optional().describe("Corpo JSON"),
|
|
337
|
+
})),
|
|
338
|
+
},
|
|
339
|
+
{
|
|
340
|
+
name: "safrapay_split",
|
|
341
|
+
description: `Split de pagamentos entre múltiplos recebedores.
|
|
342
|
+
|
|
343
|
+
RECEBEDORES:
|
|
344
|
+
- POST /receiver - Criar: { name, document: { type: 1-2 (1=CPF, 2=CNPJ), number }, bankAccount: { bank, agency, agencyDigit?, account, accountDigit, accountType: 1-2 (1=Corrente, 2=Poupança) }, email?, phone? }
|
|
345
|
+
Response: { receiverId }
|
|
346
|
+
- PUT /receiver - Atualizar: { receiverId, ... }
|
|
347
|
+
- GET /receiver/{receiverId} - Buscar
|
|
348
|
+
|
|
349
|
+
SPLIT:
|
|
350
|
+
- PUT /charge/split/ - Configurar: { chargeId, splits: [{ receiverId, type: 1-2 (1=Percentual, 2=Fixo), value, feeResponsible }] }
|
|
351
|
+
|
|
352
|
+
EXTRATO (Reconciliation API):
|
|
353
|
+
- GET /Account/Movement/Extract - query { startDate, endDate, receiverId?, currentPage?, pageSize? }
|
|
354
|
+
- GET /Future/Movement/Resume - query { receiverId? }
|
|
355
|
+
- GET /Account/Movement/Amount/Available - query { receiverId? }`,
|
|
356
|
+
inputSchema: (0, zod_to_json_schema_1.zodToJsonSchema)(zod_1.z.object({
|
|
357
|
+
api: zod_1.z.enum(["PORTAL", "GATEWAY", "RECONCILIATION"]).describe("API base"),
|
|
358
|
+
method: zod_1.z.enum(["GET", "POST", "PUT"]).describe("Método HTTP"),
|
|
359
|
+
path: zod_1.z.string().describe("Caminho do endpoint"),
|
|
360
|
+
body: zod_1.z.record(zod_1.z.any()).optional().describe("Corpo JSON"),
|
|
361
|
+
params: zod_1.z.record(zod_1.z.any()).optional().describe("Query parameters"),
|
|
362
|
+
})),
|
|
363
|
+
},
|
|
364
|
+
{
|
|
365
|
+
name: "safrapay_accreditation",
|
|
366
|
+
description: `Credenciamento: gestão de estabelecimentos (merchants) e adquirentes virtuais.
|
|
367
|
+
|
|
368
|
+
ESTABELECIMENTO:
|
|
369
|
+
- POST /v1/Merchant - Criar: { name, tradeName, document: { type, number }, email, phone, address, businessCategory, mcc, parentMerchantId? }
|
|
370
|
+
- PUT /v1/Merchant - Atualizar: { merchantId, ... }
|
|
371
|
+
- DELETE /v1/Merchant - Deletar: query { merchantId }
|
|
372
|
+
- GET /v1/Merchant - Listar: query { currentPage?, pageSize? }
|
|
373
|
+
- GET /v1/Merchant/{merchantId} - Buscar
|
|
374
|
+
- GET /v1/Merchant/GetChildMerchantsByParentId - Sub-merchants: query { parentMerchantId }
|
|
375
|
+
- GET /v1/Merchant/GetByUserId - Por usuário: query { userId }
|
|
376
|
+
- GET /v1/Merchant/{merchantId}/Taxes - Taxas
|
|
377
|
+
- GET /v1/Merchant/Mcc - Listar MCCs
|
|
378
|
+
- GET /v1/Merchant/Terminal - Terminais: query { merchantId? }
|
|
379
|
+
- GET /v1/Merchant/{merchantId}/BankSlipTaxesPlan - Taxas boleto
|
|
380
|
+
- GET /v1/Merchant/Taxes/Products - Produtos de taxas
|
|
381
|
+
- PUT /v1/Merchant/{merchantId}/Taxes/Products - Atualizar produtos: { products: [{ productId, active }] }
|
|
382
|
+
- PUT /v1/Merchant/UploadDocuments - Upload docs (multipart/form-data)
|
|
383
|
+
- POST /v1/Merchant/{merchantId}/Reconciliation - Criar reconciliação: { acquirerId, clientId, clientSecret }
|
|
384
|
+
- DELETE /v1/Merchant/{merchantId}/Reconciliation/{acquirerId}/{clientId} - Deletar
|
|
385
|
+
- PATCH /v1/Merchant/{merchantId}/Reconciliation/{acquirerId}/{clientId} - Atualizar: { clientSecret?, active? }
|
|
386
|
+
|
|
387
|
+
ADQUIRENTE VIRTUAL:
|
|
388
|
+
- POST /VirtualAcquirer - Criar: { name, cnpj, active? }
|
|
389
|
+
- GET /VirtualAcquirer - Listar
|
|
390
|
+
- PUT /VirtualAcquirer/{virtualAcquirerId} - Atualizar
|
|
391
|
+
- DELETE /VirtualAcquirer/{virtualAcquirerId} - Deletar`,
|
|
392
|
+
inputSchema: (0, zod_to_json_schema_1.zodToJsonSchema)(zod_1.z.object({
|
|
393
|
+
method: zod_1.z.enum(["GET", "POST", "PUT", "DELETE", "PATCH"]).describe("Método HTTP"),
|
|
394
|
+
path: zod_1.z.string().describe("Caminho do endpoint"),
|
|
395
|
+
body: zod_1.z.record(zod_1.z.any()).optional().describe("Corpo JSON"),
|
|
396
|
+
params: zod_1.z.record(zod_1.z.any()).optional().describe("Query parameters"),
|
|
397
|
+
isMultipart: zod_1.z.boolean().optional().describe("true para upload de arquivos"),
|
|
398
|
+
})),
|
|
399
|
+
},
|
|
400
|
+
{
|
|
401
|
+
name: "safrapay_webhook",
|
|
402
|
+
description: `Configuração de webhooks para notificações de eventos.
|
|
403
|
+
|
|
404
|
+
ENDPOINTS:
|
|
405
|
+
- POST /webhook/bulk - Criar: { url, events: ["CHARGE_PAID", "CHARGE_REFUNDED", "CHARGE_CANCELED", "CHARGE_CHARGEBACK", "SUBSCRIPTION_CREATED", "SUBSCRIPTION_CANCELED", "SUBSCRIPTION_PAYMENT_SUCCESS", "SUBSCRIPTION_PAYMENT_FAILED"], active?, headers? }
|
|
406
|
+
|
|
407
|
+
- GET /webhook - Listar: query { currentPage?, pageSize? }
|
|
408
|
+
|
|
409
|
+
- PUT /Webhook/Cancel/{webhookId} - Cancelar
|
|
410
|
+
|
|
411
|
+
EVENTOS:
|
|
412
|
+
- CHARGE_PAID: Cobrança paga
|
|
413
|
+
- CHARGE_REFUNDED: Estornada
|
|
414
|
+
- CHARGE_CANCELED: Cancelada
|
|
415
|
+
- CHARGE_CHARGEBACK: Chargeback
|
|
416
|
+
- SUBSCRIPTION_*: Eventos de assinatura`,
|
|
417
|
+
inputSchema: (0, zod_to_json_schema_1.zodToJsonSchema)(zod_1.z.object({
|
|
418
|
+
method: zod_1.z.enum(["GET", "POST", "PUT"]).describe("Método HTTP"),
|
|
419
|
+
path: zod_1.z.string().describe("Caminho do endpoint"),
|
|
420
|
+
body: zod_1.z.record(zod_1.z.any()).optional().describe("Corpo JSON"),
|
|
421
|
+
params: zod_1.z.record(zod_1.z.any()).optional().describe("Query parameters"),
|
|
422
|
+
})),
|
|
423
|
+
},
|
|
424
|
+
{
|
|
425
|
+
name: "safrapay_chargeback",
|
|
426
|
+
description: `Gestão de disputas e chargebacks.
|
|
427
|
+
|
|
428
|
+
ENDPOINTS:
|
|
429
|
+
- GET /v1/disputes/summary - Resumo: query { startDate?, endDate? }
|
|
430
|
+
|
|
431
|
+
- GET /v1/disputes/total - Total: query { status? }
|
|
432
|
+
|
|
433
|
+
- GET /v1/disputes/{disputeId} - Detalhes
|
|
434
|
+
|
|
435
|
+
- POST /v1/disputes/{disputeId}/debts/accept - Aceitar débito: { acceptReason? }
|
|
436
|
+
|
|
437
|
+
- POST /v1/disputes/second-presentment - Representação (multipart): { disputeId, documents: File[], description }`,
|
|
438
|
+
inputSchema: (0, zod_to_json_schema_1.zodToJsonSchema)(zod_1.z.object({
|
|
439
|
+
method: zod_1.z.enum(["GET", "POST"]).describe("Método HTTP"),
|
|
440
|
+
path: zod_1.z.string().describe("Caminho do endpoint"),
|
|
441
|
+
body: zod_1.z.record(zod_1.z.any()).optional().describe("Corpo JSON"),
|
|
442
|
+
params: zod_1.z.record(zod_1.z.any()).optional().describe("Query parameters"),
|
|
443
|
+
isMultipart: zod_1.z.boolean().optional().describe("true para upload de documentos"),
|
|
444
|
+
})),
|
|
445
|
+
},
|
|
446
|
+
{
|
|
447
|
+
name: "safrapay_tef",
|
|
448
|
+
description: `Integração com PinPads via protocolo TEF.
|
|
449
|
+
|
|
450
|
+
FLUXO TRANSACIONAL:
|
|
451
|
+
- POST /Init - Inicializar: { terminalId, softwareVersion }
|
|
452
|
+
- POST /Payment - Pagamento: { amount, installments, transactionType }
|
|
453
|
+
- GET /Abort - Abortar
|
|
454
|
+
- GET /Cancelation - Cancelar: query { transactionId, amount? }
|
|
455
|
+
- GET /Reversal - Estornar: query { transactionId }
|
|
456
|
+
- GET /GetPending - Buscar pendências
|
|
457
|
+
- GET /Confirm - Confirmar: query { transactionId }
|
|
458
|
+
|
|
459
|
+
FUNÇÕES AUXILIARES:
|
|
460
|
+
- GET /Display - Display
|
|
461
|
+
- POST /DataPicker - Seletor: { options: string[], message }
|
|
462
|
+
- GET /WaitEvent - Aguardar evento
|
|
463
|
+
- GET /Status - Status
|
|
464
|
+
- GET /RemoveCard - Remover cartão`,
|
|
465
|
+
inputSchema: (0, zod_to_json_schema_1.zodToJsonSchema)(zod_1.z.object({
|
|
466
|
+
method: zod_1.z.enum(["GET", "POST"]).describe("Método HTTP"),
|
|
467
|
+
path: zod_1.z.string().describe("Caminho do endpoint"),
|
|
468
|
+
body: zod_1.z.record(zod_1.z.any()).optional().describe("Corpo JSON"),
|
|
469
|
+
params: zod_1.z.record(zod_1.z.any()).optional().describe("Query parameters"),
|
|
470
|
+
})),
|
|
471
|
+
},
|
|
472
|
+
],
|
|
473
|
+
}));
|
|
474
|
+
this.server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
475
|
+
try {
|
|
476
|
+
const toolName = request.params.name;
|
|
477
|
+
const args = request.params.arguments;
|
|
478
|
+
// Todas as ferramentas agrupadas usam o mesmo handler genérico
|
|
479
|
+
if (toolName.startsWith("safrapay_")) {
|
|
480
|
+
return await this.handleGroupedTool(toolName, args);
|
|
481
|
+
}
|
|
482
|
+
throw new types_js_1.McpError(types_js_1.ErrorCode.MethodNotFound, `Unknown tool: ${request.params.name}`);
|
|
483
|
+
}
|
|
484
|
+
catch (error) {
|
|
485
|
+
const errorMessage = error.response?.data
|
|
486
|
+
? JSON.stringify(error.response.data)
|
|
487
|
+
: error.message;
|
|
488
|
+
return {
|
|
489
|
+
content: [
|
|
490
|
+
{
|
|
491
|
+
type: "text",
|
|
492
|
+
text: `Erro na execução: ${errorMessage}`,
|
|
493
|
+
},
|
|
494
|
+
],
|
|
495
|
+
isError: true,
|
|
496
|
+
};
|
|
497
|
+
}
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
async handleGroupedTool(toolName, args) {
|
|
501
|
+
const { api, method, path, body, params, headers, isMultipart } = args;
|
|
502
|
+
// Determina qual API usar baseado no contexto
|
|
503
|
+
let apiType;
|
|
504
|
+
if (toolName === "safrapay_authentication") {
|
|
505
|
+
apiType = api || "PORTAL";
|
|
506
|
+
}
|
|
507
|
+
else if (toolName === "safrapay_payments") {
|
|
508
|
+
apiType = api || "GATEWAY";
|
|
509
|
+
}
|
|
510
|
+
else if (toolName === "safrapay_charges" || toolName === "safrapay_vault" || toolName === "safrapay_checkout" || toolName === "safrapay_tef") {
|
|
511
|
+
apiType = "GATEWAY";
|
|
512
|
+
}
|
|
513
|
+
else if (toolName === "safrapay_recurrence") {
|
|
514
|
+
apiType = api || (path.includes("/plan") ? "PORTAL" : "GATEWAY");
|
|
515
|
+
}
|
|
516
|
+
else if (toolName === "safrapay_payment_link") {
|
|
517
|
+
apiType = "PORTAL";
|
|
518
|
+
}
|
|
519
|
+
else if (toolName === "safrapay_split") {
|
|
520
|
+
apiType = api || (path.includes("/Account") || path.includes("/Future") ? "RECONCILIATION" : "PORTAL");
|
|
521
|
+
}
|
|
522
|
+
else if (toolName === "safrapay_accreditation" || toolName === "safrapay_webhook" || toolName === "safrapay_chargeback") {
|
|
523
|
+
apiType = "PORTAL";
|
|
524
|
+
}
|
|
525
|
+
else {
|
|
526
|
+
apiType = api || "GATEWAY";
|
|
527
|
+
}
|
|
528
|
+
const instance = this.axiosInstances[apiType];
|
|
529
|
+
const config = {
|
|
530
|
+
method,
|
|
531
|
+
url: path,
|
|
532
|
+
data: body,
|
|
533
|
+
params,
|
|
534
|
+
headers: headers || {},
|
|
535
|
+
};
|
|
536
|
+
if (isMultipart) {
|
|
537
|
+
config.headers = {
|
|
538
|
+
...config.headers,
|
|
539
|
+
"Content-Type": "multipart/form-data",
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
// Se não há token, autentica antes da primeira requisição
|
|
543
|
+
if (!this.token) {
|
|
544
|
+
await this.autoAuthenticate();
|
|
545
|
+
}
|
|
546
|
+
// Executa a requisição (o interceptor cuida da reautenticação automática se necessário)
|
|
547
|
+
const response = await instance.request(config);
|
|
548
|
+
return {
|
|
549
|
+
content: [
|
|
550
|
+
{
|
|
551
|
+
type: "text",
|
|
552
|
+
text: JSON.stringify(response.data, null, 2),
|
|
553
|
+
},
|
|
554
|
+
],
|
|
555
|
+
};
|
|
556
|
+
}
|
|
557
|
+
async run() {
|
|
558
|
+
const transport = new stdio_js_1.StdioServerTransport();
|
|
559
|
+
await this.server.connect(transport);
|
|
560
|
+
console.error(`SafraPay MCP Server v0.2.0 running on stdio [Env: ${this.env}]`);
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
const server = new SafraPayServer();
|
|
564
|
+
server.run().catch(console.error);
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@marcelocorrea/mcp-safrapay",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "MCP Server for SafraPay Integration",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"bin": {
|
|
8
|
+
"mcp-safrapay": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist"
|
|
12
|
+
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsc",
|
|
15
|
+
"start": "node dist/index.js",
|
|
16
|
+
"dev": "tsc --watch",
|
|
17
|
+
"prepublishOnly": "npm run build"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"mcp",
|
|
21
|
+
"mcp-server",
|
|
22
|
+
"safrapay",
|
|
23
|
+
"safra",
|
|
24
|
+
"model-context-protocol",
|
|
25
|
+
"payment",
|
|
26
|
+
"payment-gateway",
|
|
27
|
+
"pix",
|
|
28
|
+
"boleto",
|
|
29
|
+
"credit-card",
|
|
30
|
+
"brasil",
|
|
31
|
+
"brazil"
|
|
32
|
+
],
|
|
33
|
+
"author": "Marcelo Correa",
|
|
34
|
+
"license": "ISC",
|
|
35
|
+
"repository": {
|
|
36
|
+
"type": "git",
|
|
37
|
+
"url": "git+https://github.com/marcelocorrea/mcp-safrapay.git"
|
|
38
|
+
},
|
|
39
|
+
"homepage": "https://github.com/marcelocorrea/mcp-safrapay#readme",
|
|
40
|
+
"bugs": {
|
|
41
|
+
"url": "https://github.com/marcelocorrea/mcp-safrapay/issues"
|
|
42
|
+
},
|
|
43
|
+
"engines": {
|
|
44
|
+
"node": ">=18.0.0"
|
|
45
|
+
},
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"@modelcontextprotocol/sdk": "^1.0.1",
|
|
48
|
+
"axios": "^1.6.0",
|
|
49
|
+
"dotenv": "^16.0.0",
|
|
50
|
+
"zod": "^3.22.0",
|
|
51
|
+
"zod-to-json-schema": "^3.25.1"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@types/node": "^20.0.0",
|
|
55
|
+
"typescript": "^5.0.0"
|
|
56
|
+
}
|
|
57
|
+
}
|