@aiconnect/agentjobs-mcp 1.0.8 → 1.1.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.
@@ -0,0 +1,387 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { formatJobDetails, formatJobStats, formatJobTypeDetails, formatJobTypeSummary } from './formatters.js';
3
+ describe('formatJobDetails', () => {
4
+ const fullJob = {
5
+ job_id: 'job_123',
6
+ job_type_id: 'type_abc',
7
+ org_id: 'org_xyz',
8
+ channel_code: 'ch_def',
9
+ chat_id: 'chat_456',
10
+ job_status: 'completed',
11
+ result: 'Success',
12
+ created_at: '2023-01-01T10:00:00.000Z',
13
+ updated_at: '2023-01-01T10:15:00.000Z',
14
+ scheduled_at: '2023-01-01T09:55:00.000Z',
15
+ last_task_created_at: '2023-01-01T10:10:00.000Z',
16
+ tags: 'tag1, tag2',
17
+ execution_log: ['Log entry 1', 'Log entry 2'],
18
+ tasks: [{ task_id: 'task_789', created_at: '2023-01-01T10:05:00.000Z' }],
19
+ flags: {
20
+ is_new_channel: true,
21
+ has_human_reply: false,
22
+ first_reply_at: '2023-01-01T10:02:00.000Z',
23
+ ignore_cooldown: true,
24
+ },
25
+ channel_data: {
26
+ platform: 'test_platform',
27
+ name: 'Test Channel',
28
+ },
29
+ job_config: {
30
+ max_task_retries: 3,
31
+ start_prompt: 'Initial prompt',
32
+ },
33
+ params: { key: 'value' },
34
+ };
35
+ it('should format a full job object correctly', () => {
36
+ const result = formatJobDetails(fullJob);
37
+ expect(result).toContain('Job ID: job_123');
38
+ expect(result).toContain('Status: completed');
39
+ expect(result).toContain('Result: Success');
40
+ expect(result).toContain('Tags: tag1, tag2');
41
+ expect(result).toContain('Total Tasks: 1');
42
+ expect(result).toContain('Retries Used: 0 / 3 (remaining: 3)');
43
+ expect(result).toContain('Duration: 20m 0s');
44
+ });
45
+ it('should handle minimal job object', () => {
46
+ const minimalJob = {
47
+ job_id: 'job_min',
48
+ job_type_id: 'type_min',
49
+ org_id: 'org_min',
50
+ channel_code: 'ch_min',
51
+ job_status: 'running',
52
+ created_at: new Date().toISOString(),
53
+ updated_at: new Date().toISOString(),
54
+ };
55
+ const result = formatJobDetails(minimalJob);
56
+ expect(result).toContain('Job ID: job_min');
57
+ expect(result).toContain('Status: running');
58
+ expect(result).toContain('Result: n/a');
59
+ expect(result).toContain('Total Tasks: 0');
60
+ });
61
+ it('should handle dates as numbers (timestamps)', () => {
62
+ const jobWithTimestamps = {
63
+ ...fullJob,
64
+ created_at: new Date(fullJob.created_at).getTime(),
65
+ updated_at: new Date(fullJob.updated_at).getTime(),
66
+ };
67
+ const result = formatJobDetails(jobWithTimestamps);
68
+ expect(result).toContain(`Created At: ${new Date(jobWithTimestamps.created_at).toISOString()}`);
69
+ expect(result).toContain(`Updated At: ${new Date(jobWithTimestamps.updated_at).toISOString()}`);
70
+ });
71
+ it('should fall back to JSON.stringify for invalid job object', () => {
72
+ const invalidJob = { job_id: '123' }; // Missing required fields
73
+ const result = formatJobDetails(invalidJob);
74
+ expect(result).toContain('"job_id": "123"');
75
+ expect(result).toContain('Job Details (raw):');
76
+ });
77
+ });
78
+ describe('formatJobStats', () => {
79
+ it('should return correct percentages when total is greater than 0', () => {
80
+ const stats = {
81
+ status: {
82
+ completed: 10,
83
+ running: 5,
84
+ failed: 2,
85
+ canceled: 1,
86
+ waiting: 1,
87
+ scheduled: 1,
88
+ },
89
+ };
90
+ const filters = {};
91
+ const result = formatJobStats(stats, filters);
92
+ expect(result).toContain('Completed: 10 jobs (50.0%)');
93
+ expect(result).toContain('Running: 5 jobs (25.0%)');
94
+ expect(result).toContain('Failed: 2 jobs (10.0%)');
95
+ expect(result).toContain('Canceled: 1 jobs (5.0%)');
96
+ expect(result).toContain('Waiting: 1 jobs (5.0%)');
97
+ expect(result).toContain('Scheduled: 1 jobs (5.0%)');
98
+ expect(result).toContain('Total Jobs: 20');
99
+ });
100
+ it('should return 0.0% for all statuses when there are no jobs', () => {
101
+ const stats = {
102
+ status: {
103
+ completed: 0,
104
+ running: 0,
105
+ failed: 0,
106
+ canceled: 0,
107
+ waiting: 0,
108
+ scheduled: 0,
109
+ },
110
+ };
111
+ const filters = {};
112
+ const result = formatJobStats(stats, filters);
113
+ expect(result).toContain('Completed: 0 jobs (0.0%)');
114
+ expect(result).toContain('Running: 0 jobs (0.0%)');
115
+ expect(result).toContain('Failed: 0 jobs (0.0%)');
116
+ expect(result).toContain('Canceled: 0 jobs (0.0%)');
117
+ expect(result).toContain('Waiting: 0 jobs (0.0%)');
118
+ expect(result).toContain('Scheduled: 0 jobs (0.0%)');
119
+ expect(result).toContain('Total Jobs: 0');
120
+ });
121
+ it('should handle null filters gracefully', () => {
122
+ const stats = {
123
+ status: {
124
+ completed: 10,
125
+ running: 5,
126
+ failed: 2,
127
+ canceled: 1,
128
+ waiting: 1,
129
+ scheduled: 1,
130
+ },
131
+ };
132
+ const filters = null;
133
+ const result = formatJobStats(stats, filters);
134
+ expect(result).toContain('Period: All time');
135
+ });
136
+ });
137
+ describe('formatJobTypeDetails', () => {
138
+ const fullJobType = {
139
+ id: 'follow-up-v2',
140
+ name: 'Follow Up by DM',
141
+ org_id: 'acme-co',
142
+ version: 2,
143
+ visibility: 'private',
144
+ active: true,
145
+ description: 'Automated follow-up to contacts who haven\'t replied within 24h. Supports templated prompts and throttling.',
146
+ default_config: {
147
+ profile_id: 'default-bot',
148
+ max_follow_ups: 3,
149
+ max_task_retries: 2,
150
+ task_retry_interval: 30,
151
+ max_time_to_complete: 180,
152
+ failure_cooldown_minutes: 120,
153
+ start_prompt: 'Hello! Just circling back on our last conversation...'
154
+ },
155
+ params_schema: {
156
+ type: 'object',
157
+ required: ['recipient_id', 'initial_message'],
158
+ properties: {
159
+ recipient_id: { type: 'string', description: 'User ID of the recipient' },
160
+ initial_message: { type: 'string', description: 'Initial text to send to the recipient' },
161
+ locale: { type: 'string', default: 'en-US', description: 'Locale for message formatting' },
162
+ throttle_minutes: { type: 'number', description: 'Min minutes between attempts' },
163
+ metadata: { type: 'object', description: 'Free-form context data' }
164
+ }
165
+ },
166
+ tags: 'outreach, dm, v2',
167
+ created_at: '2025-08-02T14:03:28.120Z',
168
+ updated_at: '2025-08-12T09:22:01.553Z'
169
+ };
170
+ it('should format a full job type object correctly', () => {
171
+ const result = formatJobTypeDetails(fullJobType);
172
+ expect(result).toContain('ID: follow-up-v2');
173
+ expect(result).toContain('Name: Follow Up by DM');
174
+ expect(result).toContain('Version: 2');
175
+ expect(result).toContain('Visibility: private');
176
+ expect(result).toContain('Active: yes');
177
+ expect(result).toContain('Profile ID: default-bot');
178
+ expect(result).toContain('Max Follow-ups: 3');
179
+ expect(result).toContain('Max Task Retries: 2');
180
+ expect(result).toContain('Task Retry Interval: 30 min');
181
+ expect(result).toContain('retries up to 2 every 30 min');
182
+ expect(result).toContain('window 180 min');
183
+ expect(result).toContain('cooldown 120 min');
184
+ expect(result).toContain('Type: object | Required: 2 | Properties: 5');
185
+ expect(result).toContain('recipient_id: string (required)');
186
+ expect(result).toContain('locale: string — Locale for message formatting — Defaults to "en-US"');
187
+ expect(result).toContain('Tags: outreach, dm, v2');
188
+ });
189
+ it('should handle minimal job type object', () => {
190
+ const minimalJobType = {
191
+ id: 'minimal',
192
+ name: 'Minimal Type',
193
+ org_id: 'org-min',
194
+ created_at: new Date().toISOString(),
195
+ updated_at: new Date().toISOString()
196
+ };
197
+ const result = formatJobTypeDetails(minimalJobType);
198
+ expect(result).toContain('ID: minimal');
199
+ expect(result).toContain('Name: Minimal Type');
200
+ expect(result).toContain('Org ID: org-min');
201
+ expect(result).not.toContain('Version:');
202
+ expect(result).not.toContain('Description:');
203
+ });
204
+ it('should handle missing optional fields gracefully', () => {
205
+ const jobTypeNoConfig = {
206
+ id: 'no-config',
207
+ name: 'No Config Type',
208
+ org_id: 'org-test',
209
+ created_at: '2025-01-01T00:00:00Z',
210
+ updated_at: '2025-01-01T00:00:00Z'
211
+ };
212
+ const result = formatJobTypeDetails(jobTypeNoConfig, { showEmptySections: true });
213
+ expect(result).toContain('Default Config:');
214
+ expect(result).toContain('n/a');
215
+ expect(result).toContain('Params Schema:');
216
+ });
217
+ it('should truncate long strings with ellipsis', () => {
218
+ const longDescription = 'A'.repeat(500);
219
+ const longPrompt = 'B'.repeat(600);
220
+ const jobTypeWithLongText = {
221
+ id: 'long-text',
222
+ name: 'Long Text Type',
223
+ org_id: 'org-test',
224
+ description: longDescription,
225
+ default_config: {
226
+ start_prompt: longPrompt
227
+ },
228
+ created_at: '2025-01-01T00:00:00Z',
229
+ updated_at: '2025-01-01T00:00:00Z'
230
+ };
231
+ const result = formatJobTypeDetails(jobTypeWithLongText);
232
+ expect(result).toContain('A'.repeat(400) + '…');
233
+ expect(result).toContain('B'.repeat(500) + '…');
234
+ });
235
+ it('should normalize date fields (ms to ISO)', () => {
236
+ const jobTypeWithTimestamps = {
237
+ id: 'timestamps',
238
+ name: 'Timestamp Type',
239
+ org_id: 'org-test',
240
+ created_at: 1704067200000, // 2024-01-01T00:00:00.000Z
241
+ updated_at: 1704153600000 // 2024-01-02T00:00:00.000Z
242
+ };
243
+ const result = formatJobTypeDetails(jobTypeWithTimestamps);
244
+ expect(result).toContain('Created At: 2024-01-01T00:00:00.000Z');
245
+ expect(result).toContain('Updated At: 2024-01-02T00:00:00.000Z');
246
+ });
247
+ it('should handle tags as CSV string', () => {
248
+ const jobTypeWithCSVTags = {
249
+ id: 'csv-tags',
250
+ name: 'CSV Tags Type',
251
+ org_id: 'org-test',
252
+ tags: 'tag1, tag2 , tag3',
253
+ created_at: '2025-01-01T00:00:00Z',
254
+ updated_at: '2025-01-01T00:00:00Z'
255
+ };
256
+ const result = formatJobTypeDetails(jobTypeWithCSVTags);
257
+ expect(result).toContain('Tags: tag1, tag2, tag3');
258
+ });
259
+ it('should handle tags as array', () => {
260
+ const jobTypeWithArrayTags = {
261
+ id: 'array-tags',
262
+ name: 'Array Tags Type',
263
+ org_id: 'org-test',
264
+ tags: ['tag1', 'tag2', 'tag3'],
265
+ created_at: '2025-01-01T00:00:00Z',
266
+ updated_at: '2025-01-01T00:00:00Z'
267
+ };
268
+ const result = formatJobTypeDetails(jobTypeWithArrayTags);
269
+ expect(result).toContain('Tags: tag1, tag2, tag3');
270
+ });
271
+ it('should summarize large schemas with "+N more" indication', () => {
272
+ const properties = {};
273
+ for (let i = 1; i <= 30; i++) {
274
+ properties[`prop${i}`] = { type: 'string', description: `Property ${i}` };
275
+ }
276
+ const jobTypeWithLargeSchema = {
277
+ id: 'large-schema',
278
+ name: 'Large Schema Type',
279
+ org_id: 'org-test',
280
+ params_schema: {
281
+ type: 'object',
282
+ required: ['prop1', 'prop2'],
283
+ properties
284
+ },
285
+ created_at: '2025-01-01T00:00:00Z',
286
+ updated_at: '2025-01-01T00:00:00Z'
287
+ };
288
+ const result = formatJobTypeDetails(jobTypeWithLargeSchema);
289
+ expect(result).toContain('Properties: 30');
290
+ expect(result).toContain('+18 more…');
291
+ expect(result).toContain('prop1: string (required)');
292
+ expect(result).toContain('prop12: string');
293
+ });
294
+ it('should return raw JSON on parse failure', () => {
295
+ const invalidJobType = { notAValidField: 123 };
296
+ const result = formatJobTypeDetails(invalidJobType);
297
+ expect(result).toContain('Job Type Details (raw):');
298
+ expect(result).toContain('"notAValidField": 123');
299
+ });
300
+ it('should respect formatter options', () => {
301
+ const result = formatJobTypeDetails(fullJobType, {
302
+ includeSchema: false,
303
+ renderAsMarkdown: false
304
+ });
305
+ expect(result).not.toContain('## Job Type Details');
306
+ expect(result).toContain('Job Type Details\n===========');
307
+ expect(result).not.toContain('Params Schema:');
308
+ });
309
+ it('should handle custom truncation limits', () => {
310
+ const longJobType = {
311
+ id: 'custom-truncate',
312
+ name: 'Custom Truncate',
313
+ org_id: 'org-test',
314
+ description: 'X'.repeat(100),
315
+ default_config: {
316
+ start_prompt: 'Y'.repeat(100)
317
+ },
318
+ created_at: '2025-01-01T00:00:00Z',
319
+ updated_at: '2025-01-01T00:00:00Z'
320
+ };
321
+ const result = formatJobTypeDetails(longJobType, {
322
+ truncate: {
323
+ description: 50,
324
+ startPrompt: 30
325
+ }
326
+ });
327
+ expect(result).toContain('X'.repeat(50) + '…');
328
+ expect(result).toContain('Y'.repeat(30) + '…');
329
+ });
330
+ });
331
+ describe('formatJobTypeSummary', () => {
332
+ it('should format a complete job type summary', () => {
333
+ const jobType = {
334
+ id: 'summary-test',
335
+ name: 'Summary Test Type',
336
+ org_id: 'org-test',
337
+ active: true,
338
+ default_config: {
339
+ max_task_retries: 3,
340
+ task_retry_interval: 15,
341
+ max_time_to_complete: 60,
342
+ failure_cooldown_minutes: 30
343
+ },
344
+ params_schema: {
345
+ type: 'object',
346
+ required: ['field1', 'field2'],
347
+ properties: {
348
+ field1: { type: 'string' },
349
+ field2: { type: 'number' },
350
+ field3: { type: 'boolean' }
351
+ }
352
+ },
353
+ created_at: '2025-01-01T00:00:00Z',
354
+ updated_at: '2025-01-01T00:00:00Z'
355
+ };
356
+ const result = formatJobTypeSummary(jobType);
357
+ expect(result).toContain('ID: summary-test');
358
+ expect(result).toContain('Name: Summary Test Type');
359
+ expect(result).toContain('Active: yes');
360
+ expect(result).toContain('Retries: 3 every 15 min');
361
+ expect(result).toContain('Max Time: 60 min');
362
+ expect(result).toContain('Cooldown: 30 min');
363
+ expect(result).toContain('Params: required=2, props=3');
364
+ });
365
+ it('should handle minimal job type summary', () => {
366
+ const minimalJobType = {
367
+ id: 'minimal',
368
+ name: 'Minimal',
369
+ org_id: 'org-test',
370
+ created_at: '2025-01-01T00:00:00Z',
371
+ updated_at: '2025-01-01T00:00:00Z'
372
+ };
373
+ const result = formatJobTypeSummary(minimalJobType);
374
+ expect(result).toContain('ID: minimal');
375
+ expect(result).toContain('Name: Minimal');
376
+ expect(result).toContain('Active: n/a');
377
+ expect(result).toContain('Retries: n/a');
378
+ expect(result).toContain('Max Time: n/a');
379
+ expect(result).toContain('Cooldown: n/a');
380
+ expect(result).toContain('Params: n/a');
381
+ });
382
+ it('should return raw JSON for invalid job type', () => {
383
+ const invalidJobType = { invalid: true };
384
+ const result = formatJobTypeSummary(invalidJobType);
385
+ expect(result).toContain('"invalid": true');
386
+ });
387
+ });
@@ -0,0 +1,20 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * A flexible Zod schema for validating ISO 8601 date-time strings.
4
+ *
5
+ * This schema accepts any string that can be successfully parsed by the `Date` constructor,
6
+ * which includes formats with 'Z' (UTC) and timezone offsets (e.g., '+01:00').
7
+ * It refines a base string schema, providing a more specific error message if the
8
+ * date-time string is invalid.
9
+ */
10
+ export const flexibleDateTimeSchema = z.string().refine((value) => {
11
+ // Try to parse the date string.
12
+ // The Date constructor is quite flexible with ISO 8601 formats.
13
+ const date = new Date(value);
14
+ // Check if the parsed date is valid.
15
+ // `isNaN(date.getTime())` is a reliable way to check for invalid dates.
16
+ return !isNaN(date.getTime());
17
+ }, {
18
+ // Custom error message for invalid date-time strings.
19
+ message: "Invalid date-time string. Please use a valid ISO 8601 format.",
20
+ });
@@ -0,0 +1,40 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { flexibleDateTimeSchema } from './schemas.js';
3
+ describe('flexibleDateTimeSchema', () => {
4
+ // Test case 1: Valid ISO 8601 with UTC 'Z'
5
+ it('should validate a correct ISO 8601 string with Zulu time', () => {
6
+ const validDate = '2025-07-23T21:00:00Z';
7
+ const result = flexibleDateTimeSchema.safeParse(validDate);
8
+ expect(result.success).toBe(true);
9
+ });
10
+ // Test case 2: Valid ISO 8601 with a positive timezone offset
11
+ it('should validate a correct ISO 8601 string with a positive offset', () => {
12
+ const validDate = '2025-07-23T22:00:00+01:00';
13
+ const result = flexibleDateTimeSchema.safeParse(validDate);
14
+ expect(result.success).toBe(true);
15
+ });
16
+ // Test case 3: Valid ISO 8601 with a negative timezone offset
17
+ it('should validate a correct ISO 8601 string with a negative offset', () => {
18
+ const validDate = '2025-07-23T16:00:00-05:00';
19
+ const result = flexibleDateTimeSchema.safeParse(validDate);
20
+ expect(result.success).toBe(true);
21
+ });
22
+ // Test case 4: Invalid date format (not ISO 8601)
23
+ it('should not validate an incorrect date format', () => {
24
+ const invalidDate = '23/07/2025 21:00:00';
25
+ const result = flexibleDateTimeSchema.safeParse(invalidDate);
26
+ expect(result.success).toBe(false);
27
+ });
28
+ // Test case 5: Invalid date string (gibberish)
29
+ it('should not validate a gibberish string', () => {
30
+ const gibberish = 'not-a-date';
31
+ const result = flexibleDateTimeSchema.safeParse(gibberish);
32
+ expect(result.success).toBe(false);
33
+ });
34
+ // Test case 6: Empty string
35
+ it('should not validate an empty string', () => {
36
+ const emptyString = '';
37
+ const result = flexibleDateTimeSchema.safeParse(emptyString);
38
+ expect(result.success).toBe(false);
39
+ });
40
+ });
@@ -0,0 +1,203 @@
1
+ # 🔍 Guia de Debug do MCP Server
2
+
3
+ Este guia fornece várias maneiras de depurar e diagnosticar problemas no seu MCP Server.
4
+
5
+ ## 🚀 Comandos de Debug Disponíveis
6
+
7
+ ### 1. Debug Básico
8
+ ```bash
9
+ # Compilar e rodar em modo debug
10
+ npm run debug
11
+
12
+ # Debug com variáveis de ambiente específicas
13
+ MCP_DEBUG=true npm run debug
14
+ ```
15
+
16
+ ### 2. Testar Tools
17
+ ```bash
18
+ # Verificar se todas as tools estão carregando
19
+ npm run test:tools
20
+
21
+ # Verificar configuração atual
22
+ npm run cli:config
23
+ ```
24
+
25
+ ### 3. Debug com Logs Detalhados
26
+ ```bash
27
+ # Usar arquivo de ambiente de debug
28
+ cp .env.debug .env
29
+ # Editar .env com suas credenciais
30
+ npm run debug
31
+ ```
32
+
33
+ ## 🛠️ Tipos de Debug
34
+
35
+ ### 1. **Debug de Configuração**
36
+ ```bash
37
+ npm run cli:config
38
+ ```
39
+ Este comando mostra:
40
+ - URL da API
41
+ - Status da chave de API
42
+ - Versão do Node.js
43
+ - Versão do MCP Server
44
+
45
+ ### 2. **Debug de Carregamento de Tools**
46
+ ```bash
47
+ npm run test:tools
48
+ ```
49
+ Este comando:
50
+ - Lista todas as tools encontradas
51
+ - Testa o carregamento de cada tool
52
+ - Mostra erros de carregamento se houver
53
+
54
+ ### 3. **Debug Completo em Runtime**
55
+ ```bash
56
+ MCP_DEBUG=true npm run debug
57
+ ```
58
+ Com `MCP_DEBUG=true`, você verá:
59
+ - Logs de inicialização detalhados
60
+ - Configuração carregada
61
+ - Chamadas de tools em tempo real
62
+ - Respostas das APIs
63
+ - Erros detalhados
64
+
65
+ ## 📊 Interpretando os Logs
66
+
67
+ ### Logs de Tool
68
+ ```
69
+ [MCP-DEBUG 2025-08-13T...] [INFO] Tool called: get_jobs_stats
70
+ [MCP-DEBUG 2025-08-13T...] [DEBUG] Data: {"org_id":"aiconnect"}
71
+ ```
72
+
73
+ ### Logs de API
74
+ ```
75
+ [MCP-DEBUG 2025-08-13T...] [DEBUG] HTTP GET https://api.aiconnect.cloud/api/v0/jobs/stats
76
+ [MCP-DEBUG 2025-08-13T...] [DEBUG] HTTP Response GET [200]
77
+ ```
78
+
79
+ ### Logs de Erro
80
+ ```
81
+ [MCP-DEBUG 2025-08-13T...] [ERROR] Tool error: get_jobs_stats
82
+ [MCP-DEBUG 2025-08-13T...] [ERROR] Data: {"error": "API key not provided"}
83
+ ```
84
+
85
+ ## 🔧 Problemas Comuns e Soluções
86
+
87
+ ### 1. **API Key não configurada**
88
+ **Erro:** `API key not provided`
89
+ **Solução:**
90
+ ```bash
91
+ # Definir a chave de API
92
+ export AICONNECT_API_KEY="sua-chave-aqui"
93
+ npm run debug
94
+ ```
95
+
96
+ ### 2. **URL da API incorreta**
97
+ **Erro:** `Request failed with status 404`
98
+ **Solução:**
99
+ ```bash
100
+ # Verificar/definir URL da API
101
+ export AICONNECT_API_URL="https://api.aiconnect.cloud/api/v0"
102
+ npm run debug
103
+ ```
104
+
105
+ ### 3. **Tools não carregando**
106
+ **Erro:** `Error loading tools`
107
+ **Solução:**
108
+ ```bash
109
+ # Verificar se o build está atualizado
110
+ npm run build
111
+ npm run test:tools
112
+ ```
113
+
114
+ ### 4. **Problemas de Conexão MCP**
115
+ **Erro:** `Transport connection closed`
116
+ **Solução:**
117
+ - Verificar se o cliente MCP está conectado corretamente
118
+ - Usar logs de debug para ver detalhes da conexão
119
+
120
+ ## 📝 Configuração para Claude Desktop
121
+
122
+ Para debug no Claude Desktop, use esta configuração no `claude_desktop_config.json`:
123
+
124
+ ```json
125
+ {
126
+ "mcpServers": {
127
+ "agentjobs-debug": {
128
+ "command": "node",
129
+ "args": ["/caminho/para/agentjobs-mcp/build/debug.js"],
130
+ "env": {
131
+ "MCP_DEBUG": "true",
132
+ "AICONNECT_API_KEY": "sua-chave-aqui",
133
+ "AICONNECT_API_URL": "https://api.aiconnect.cloud/api/v0",
134
+ "DEFAULT_ORG_ID": "aiconnect"
135
+ }
136
+ }
137
+ }
138
+ }
139
+ ```
140
+
141
+ ## 🧪 Testes de Funcionalidade
142
+
143
+ ### Teste Manual das Tools
144
+
145
+ 1. **Listar Jobs:**
146
+ - Comando: "List all jobs"
147
+ - Debug: Verificar se a API é chamada e se os dados são formatados
148
+
149
+ 2. **Buscar Job Específico:**
150
+ - Comando: "Get job details for job-123"
151
+ - Debug: Verificar parâmetros enviados e resposta recebida
152
+
153
+ 3. **Criar Job:**
154
+ - Comando: "Create a new job"
155
+ - Debug: Verificar payload da criação e resposta
156
+
157
+ ### Teste de Configuração
158
+
159
+ ```bash
160
+ # Verificar todas as configurações
161
+ npm run cli:config
162
+
163
+ # Verificar carregamento das tools
164
+ npm run test:tools
165
+
166
+ # Verificar versão
167
+ npm run cli:version
168
+ ```
169
+
170
+ ## 🎯 Dicas de Debug
171
+
172
+ 1. **Use logs incrementais:** Comece com debug básico e aumente verbosidade conforme necessário
173
+
174
+ 2. **Teste isoladamente:** Use `npm run test:tools` para verificar carregamento antes de testar funcionalidade
175
+
176
+ 3. **Monitore a API:** Se possível, monitore logs da API AI Connect em paralelo
177
+
178
+ 4. **Verifique configuração:** Sempre rode `npm run cli:config` primeiro
179
+
180
+ 5. **Use ambiente controlado:** Use `.env.debug` para configuração consistente
181
+
182
+ ## 📋 Checklist de Debug
183
+
184
+ - [ ] Configuração carregada corretamente (`npm run cli:config`)
185
+ - [ ] Tools carregando sem erro (`npm run test:tools`)
186
+ - [ ] API key configurada
187
+ - [ ] URL da API acessível
188
+ - [ ] Logs de debug habilitados (`MCP_DEBUG=true`)
189
+ - [ ] Conexão MCP funcionando
190
+ - [ ] Tools respondendo conforme esperado
191
+
192
+ ## 🆘 Debugging Avançado
193
+
194
+ Para problemas complexos, você pode:
195
+
196
+ 1. **Adicionar mais logs** nas tools específicas
197
+ 2. **Usar Node.js debugger** com `--inspect`
198
+ 3. **Monitorar requisições HTTP** com `DEBUG=axios`
199
+ 4. **Verificar memória e performance** com `node --trace-warnings`
200
+
201
+ ---
202
+
203
+ 💡 **Lembre-se:** O debug é mais eficiente quando feito de forma incremental, testando cada componente isoladamente antes de testar o sistema completo.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiconnect/agentjobs-mcp",
3
- "version": "1.0.8",
3
+ "version": "1.1.0",
4
4
  "description": "MCP (Model Context Protocol) server for managing Agent Jobs in the AI Connect platform. Developed by AI Connect - Advanced AI automation and integration solutions.",
5
5
  "type": "module",
6
6
  "main": "build/index.js",
@@ -28,10 +28,14 @@
28
28
  "build": "tsc && chmod +x build/index.js",
29
29
  "start": "node build/index.js",
30
30
  "dev": "tsc && node build/index.js",
31
+ "debug": "tsc && node build/debug.js",
32
+ "debug:watch": "tsc --watch & sleep 2 && node build/debug.js",
31
33
  "clean": "rm -rf build",
32
34
  "typecheck": "tsc --noEmit",
33
- "lint": "echo 'Linting not configured yet'",
34
- "test": "echo 'Tests not configured yet'",
35
+ "lint": "eslint . --ext .ts,.js",
36
+ "lint:fix": "eslint . --ext .ts,.js --fix",
37
+ "test": "vitest",
38
+ "test:tools": "npm run build && node build/test-tools.js",
35
39
  "prepare": "npm run build",
36
40
  "version:patch": "npm version patch",
37
41
  "version:minor": "npm version minor",
@@ -53,7 +57,11 @@
53
57
  },
54
58
  "devDependencies": {
55
59
  "@types/node": "^22.10.5",
56
- "typescript": "^5.7.2"
60
+ "@eslint/js": "^9.14.0",
61
+ "eslint": "^9.14.0",
62
+ "typescript-eslint": "^8.12.2",
63
+ "typescript": "^5.7.2",
64
+ "vitest": "^3.2.4"
57
65
  },
58
66
  "engines": {
59
67
  "node": ">=18.0.0"