agent-master-devsecops 3.9.0 → 5.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.
- package/README.md +205 -371
- package/agents/AGENT_DEVSECOPS.md +32 -417
- package/agents/AGENT_INFRA.md +31 -0
- package/agents/AGENT_ORCHESTRATOR.md +39 -264
- package/agents/AGENT_QA.md +58 -186
- package/agents/AGENT_SCRUM.md +23 -190
- package/agents/AGENT_SRE.md +22 -173
- package/agents/AGENT_UIUX.md +26 -162
- package/docs/ARCHITECTURE.md +152 -148
- package/docs/CALCULATIONS.md +17 -17
- package/docs/CHANGELOG.md +112 -49
- package/docs/ENGINEERING_RULES.md +56 -252
- package/docs/IDEAS.md +17 -17
- package/docs/LOCAL_BACKLOG.md +20 -0
- package/docs/STATE.md +111 -43
- package/docs/playbooks/PLAYBOOK_CIRCUIT_BREAKER_LLM.md +58 -58
- package/docs/playbooks/PLAYBOOK_OPENTELEMETRY_TRACING.md +58 -58
- package/package.json +59 -47
- package/scripts/auditors/a11y_auditor.js +462 -0
- package/scripts/auditors/code_quality_auditor.js +444 -0
- package/scripts/auditors/contract_test_validator.js +396 -0
- package/scripts/auditors/eval_harness.js +213 -0
- package/scripts/auditors/git_hygiene_linter.js +391 -0
- package/scripts/auditors/pr_reviewer.js +627 -0
- package/scripts/auditors/sast_scanner.js +442 -0
- package/scripts/auditors/sca_dependency_auditor.js +673 -0
- package/scripts/{bootstrap_cli.js → bin/bootstrap_cli.js} +597 -468
- package/scripts/bin/domain_idea_miner.js +658 -0
- package/scripts/bin/smart_onboarding.js +905 -0
- package/scripts/{web_inspector.js → bin/web_inspector.js} +578 -355
- package/scripts/core/architecture_advisor.js +378 -0
- package/scripts/core/ast_skeletonizer.js +413 -0
- package/scripts/core/autonomous_remediation_engine.js +305 -0
- package/scripts/{circuit_breaker.js → core/circuit_breaker.js} +546 -330
- package/scripts/core/context_compressor.js +237 -0
- package/scripts/core/fast_feature_scaffold.js +840 -0
- package/scripts/core/hot_state_cache.js +238 -0
- package/scripts/core/knowledge_gateway.js +888 -0
- package/scripts/{magic_prompt_generator.js → core/magic_prompt_generator.js} +250 -205
- package/scripts/{multi_agent_orchestrator.js → core/multi_agent_orchestrator.js} +421 -258
- package/scripts/{otel_tracer.js → core/otel_tracer.js} +335 -228
- package/scripts/{perf_benchmark.js → core/perf_benchmark.js} +212 -153
- package/scripts/core/sarif_engine.js +299 -0
- package/scripts/{sre_remediation_engine.js → core/sre_remediation_engine.js} +236 -174
- package/scripts/{universal_packager.js → core/universal_packager.js} +357 -313
- package/scripts/integrations/atlassian_client.js +600 -0
- package/scripts/integrations/atlassian_sync_action.js +576 -0
- package/scripts/integrations/confluence_sync.js +684 -0
- package/scripts/integrations/credentials_guard.js +500 -0
- package/scripts/integrations/jira_manager.js +722 -0
- package/scripts/mcp/handlers/atlassian_handlers.js +300 -0
- package/scripts/mcp/handlers/core_handlers.js +419 -0
- package/scripts/mcp/handlers/qa_handlers.js +502 -0
- package/scripts/mcp/handlers/rules_handlers.js +379 -0
- package/scripts/mcp/handlers/scaffold_handlers.js +334 -0
- package/scripts/mcp/handlers/sre_handlers.js +443 -0
- package/scripts/mcp/resources_registry.js +453 -0
- package/scripts/mcp/server.js +408 -0
- package/scripts/mcp/tool_handlers.js +444 -0
- package/scripts/mcp/tools_registry.js +1123 -0
- package/scripts/mcp_server.js +236 -1884
- package/.cursorignore +0 -23
- package/agents/compact/AGENT_ORCHESTRATOR_COMPACTO.md +0 -53
- package/scripts/a11y_auditor.js +0 -187
- package/scripts/ast_skeletonizer.js +0 -220
- package/scripts/atlassian_client.js +0 -238
- package/scripts/atlassian_sync_action.js +0 -269
- package/scripts/code_quality_auditor.js +0 -142
- package/scripts/confluence_sync.js +0 -337
- package/scripts/context_compressor.js +0 -139
- package/scripts/contract_test_validator.js +0 -166
- package/scripts/credentials_guard.js +0 -216
- package/scripts/domain_idea_miner.js +0 -364
- package/scripts/eval_harness.js +0 -100
- package/scripts/fast_feature_scaffold.js +0 -338
- package/scripts/git_hygiene_linter.js +0 -186
- package/scripts/hot_state_cache.js +0 -95
- package/scripts/jira_manager.js +0 -408
- package/scripts/pr_reviewer.js +0 -373
- package/scripts/sast_scanner.js +0 -180
- package/scripts/sca_dependency_auditor.js +0 -167
- package/scripts/smart_onboarding.js +0 -610
package/scripts/mcp_server.js
CHANGED
|
@@ -1,1884 +1,236 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
{
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
},
|
|
240
|
-
{
|
|
241
|
-
name: 'agent_sre_remediate',
|
|
242
|
-
description: 'Executa playbook de auto-remediação operacional SRE (purge_buffers, trigger_gc, reset_circuits, prune_cache) para mitigar saturação.',
|
|
243
|
-
inputSchema: {
|
|
244
|
-
type: 'object',
|
|
245
|
-
properties: {
|
|
246
|
-
action: {
|
|
247
|
-
type: 'string',
|
|
248
|
-
enum: ['purge_buffers', 'trigger_gc', 'reset_circuits', 'prune_cache'],
|
|
249
|
-
description: 'Ação de auto-cura a ser executada'
|
|
250
|
-
},
|
|
251
|
-
context: { type: 'object', description: 'Metadados contextuais do incidente' }
|
|
252
|
-
},
|
|
253
|
-
required: ['action']
|
|
254
|
-
}
|
|
255
|
-
},
|
|
256
|
-
{
|
|
257
|
-
name: 'agent_export_universal_bundle',
|
|
258
|
-
description: 'Exporta perfis, regras e configurações pré-moldadas do Agent Master para Cursor (.cursorrules), Windsurf (.windsurfrules), Claude Desktop, ChatGPT Custom GPTs ou Ollama local.',
|
|
259
|
-
inputSchema: {
|
|
260
|
-
type: 'object',
|
|
261
|
-
properties: {
|
|
262
|
-
platform: {
|
|
263
|
-
type: 'string',
|
|
264
|
-
enum: ['cursor', 'windsurf', 'claude_desktop', 'chatgpt', 'ollama', 'all'],
|
|
265
|
-
description: 'Plataforma alvo para exportação (ou "all" para todas)'
|
|
266
|
-
},
|
|
267
|
-
targetDir: { type: 'string', description: 'Diretório de destino para exportação' },
|
|
268
|
-
dryRun: { type: 'boolean', description: 'Simula a geração sem gravar arquivos físicos no disco' }
|
|
269
|
-
},
|
|
270
|
-
required: ['platform']
|
|
271
|
-
}
|
|
272
|
-
},
|
|
273
|
-
{
|
|
274
|
-
name: 'agent_bootstrap_environment',
|
|
275
|
-
description: 'Executa o auto-bootstrap do Agent Master DevSecOps: detecta IDEs e ferramentas instaladas (Cursor, Windsurf, VS Code, Claude Desktop, Ollama) e injeta regras e manifestos MCP com zero configuração em < 2 segundos.',
|
|
276
|
-
inputSchema: {
|
|
277
|
-
type: 'object',
|
|
278
|
-
properties: {
|
|
279
|
-
targetDir: { type: 'string', description: 'Diretório alvo do projeto (padrão: raiz do projeto)' },
|
|
280
|
-
dryRun: { type: 'boolean', description: 'Simula a detecção e geração sem escrever em disco' },
|
|
281
|
-
platforms: {
|
|
282
|
-
type: 'array',
|
|
283
|
-
items: { type: 'string' },
|
|
284
|
-
description: 'Lista explícita opcional de plataformas a configurar (caso queira forçar em vez de auto-detectar)'
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
},
|
|
289
|
-
{
|
|
290
|
-
name: 'agent_generate_magic_prompt',
|
|
291
|
-
description: 'Gera o Magic Prompt autocontido (< 900 tokens) e o Web Bookmarklet para ativação instantânea em 1 clique em interfaces web de LLMs (ChatGPT, Claude.ai, Gemini, DeepSeek).',
|
|
292
|
-
inputSchema: {
|
|
293
|
-
type: 'object',
|
|
294
|
-
properties: {
|
|
295
|
-
targetDir: { type: 'string', description: 'Diretório de exportação dos arquivos HTML e Markdown' },
|
|
296
|
-
dryRun: { type: 'boolean', description: 'Simula a geração sem gravar arquivos físicos no disco' }
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
},
|
|
300
|
-
{
|
|
301
|
-
name: 'agent_inspector_info',
|
|
302
|
-
description: 'Consulta informações, rotas de API e telemetria do Web Dashboard & Playground do Agent Master (servido via scripts/web_inspector.js na porta 4040).',
|
|
303
|
-
inputSchema: {
|
|
304
|
-
type: 'object',
|
|
305
|
-
properties: {
|
|
306
|
-
port: { type: 'number', description: 'Porta HTTP configurada (padrão: 4040)' }
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
},
|
|
310
|
-
{
|
|
311
|
-
name: 'agent_check_credentials',
|
|
312
|
-
description: 'Audita e executa healthcheck de autenticação no GitHub CLI e Atlassian (Jira e Confluence), orientando o setup de credenciais para garantir o Tríplice Registro contínuo.',
|
|
313
|
-
inputSchema: {
|
|
314
|
-
type: 'object',
|
|
315
|
-
properties: {
|
|
316
|
-
targetDir: { type: 'string', description: 'Diretório raiz do projeto (opcional)' }
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
},
|
|
320
|
-
{
|
|
321
|
-
name: 'agent_configure_credentials',
|
|
322
|
-
description: 'Configura credenciais de autenticação da Atlassian no arquivo .env local com garantia de proteção estrita no .gitignore.',
|
|
323
|
-
inputSchema: {
|
|
324
|
-
type: 'object',
|
|
325
|
-
properties: {
|
|
326
|
-
domain: { type: 'string', description: 'Domínio Atlassian (ex: sua-empresa.atlassian.net)' },
|
|
327
|
-
email: { type: 'string', description: 'Email da conta Atlassian' },
|
|
328
|
-
token: { type: 'string', description: 'API Token da Atlassian' },
|
|
329
|
-
jiraKey: { type: 'string', description: 'Chave do projeto Jira (ex: PROJ)' },
|
|
330
|
-
confluenceSpace: { type: 'string', description: 'Espaço do Confluence (ex: DOC)' },
|
|
331
|
-
targetDir: { type: 'string', description: 'Diretório raiz do projeto (opcional)' }
|
|
332
|
-
},
|
|
333
|
-
required: ['domain', 'email', 'token']
|
|
334
|
-
}
|
|
335
|
-
},
|
|
336
|
-
{
|
|
337
|
-
name: 'agent_standardize_kanban',
|
|
338
|
-
description: 'Padroniza qualquer quadro Jira para as 3 colunas canônicas ("A fazer", "Em andamento", "Concluído") e gera as consultas JQL e mapeamento unificado.',
|
|
339
|
-
inputSchema: {
|
|
340
|
-
type: 'object',
|
|
341
|
-
properties: {
|
|
342
|
-
projectKey: { type: 'string', description: 'Chave do projeto Jira (ex: AGDEV)' },
|
|
343
|
-
boardConfig: { type: 'object', description: 'Configuração opcional do quadro retornada pela API do Jira' }
|
|
344
|
-
},
|
|
345
|
-
required: ['projectKey']
|
|
346
|
-
}
|
|
347
|
-
},
|
|
348
|
-
{
|
|
349
|
-
name: 'agent_full_dev_pipeline',
|
|
350
|
-
description: 'Orquestra o ciclo do Modo Full Developer: lê "A fazer", aplica filtro de sanidade (Regra 14), planeja transição para "Em andamento", homologa e move para "Concluído" em loop recursivo.',
|
|
351
|
-
inputSchema: {
|
|
352
|
-
type: 'object',
|
|
353
|
-
properties: {
|
|
354
|
-
tasks: {
|
|
355
|
-
type: 'array',
|
|
356
|
-
items: { type: 'object' },
|
|
357
|
-
description: 'Lista de tarefas obtidas do Jira'
|
|
358
|
-
},
|
|
359
|
-
projectContext: {
|
|
360
|
-
type: 'object',
|
|
361
|
-
description: 'Contexto real do projeto (stack, domain, architecture)'
|
|
362
|
-
}
|
|
363
|
-
},
|
|
364
|
-
required: ['tasks']
|
|
365
|
-
}
|
|
366
|
-
},
|
|
367
|
-
{
|
|
368
|
-
name: 'agent_validate_rule15',
|
|
369
|
-
description: 'Valida compulsória e ativamente o cumprimento da Regra 15 (Imutabilidade de Requisitos e Pré-Validação de Segredos Atlassian e GitHub). Bloqueia falhas silenciosas.',
|
|
370
|
-
inputSchema: {
|
|
371
|
-
type: 'object',
|
|
372
|
-
properties: {
|
|
373
|
-
failFast: { type: 'boolean', description: 'Se true, levanta erro impeditivo caso faltem requisitos. Padrão: false' },
|
|
374
|
-
requireGitHub: { type: 'boolean', description: 'Exige autenticação válida do GitHub CLI. Padrão: true' },
|
|
375
|
-
requireAtlassian: { type: 'boolean', description: 'Exige credenciais válidas do ecossistema Atlassian. Padrão: true' }
|
|
376
|
-
}
|
|
377
|
-
} },
|
|
378
|
-
{
|
|
379
|
-
name: 'agent_audit_a11y',
|
|
380
|
-
description: 'Audita código HTML, JSX e TSX contra diretrizes de acessibilidade WCAG 2.1 AA (AGENT_UIUX & AGENT_QA), verificando contraste, semântica ARIA, imagens sem alt e foco visível.',
|
|
381
|
-
inputSchema: {
|
|
382
|
-
type: 'object',
|
|
383
|
-
properties: {
|
|
384
|
-
code: { type: 'string', description: 'Código-fonte HTML, JSX ou TSX a ser auditado.' },
|
|
385
|
-
filename: { type: 'string', description: 'Nome do arquivo de origem (ex: Header.tsx).' }
|
|
386
|
-
},
|
|
387
|
-
required: ['code']
|
|
388
|
-
}
|
|
389
|
-
},
|
|
390
|
-
{
|
|
391
|
-
name: 'agent_lint_git_hygiene',
|
|
392
|
-
description: 'Audita mensagens de commit e nomes de branch contra a Regra 11 de Engenharia ([<TICKET>] - <Ação em português> e veto a Conventional Commits e prefixos legados).',
|
|
393
|
-
inputSchema: {
|
|
394
|
-
type: 'object',
|
|
395
|
-
properties: {
|
|
396
|
-
commitMessage: { type: 'string', description: 'Mensagem do commit a ser auditada' },
|
|
397
|
-
branchName: { type: 'string', description: 'Nome da branch a ser auditada' },
|
|
398
|
-
auditState: { type: 'boolean', description: 'Se true, audita o repositório Git local ativo' }
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
},
|
|
402
|
-
{
|
|
403
|
-
name: 'agent_audit_dependencies_sca',
|
|
404
|
-
description: 'Executa Software Composition Analysis (SCA) offline no manifesto package.json, detectando CVEs conhecidas e licenças restritivas (GPL/AGPL).',
|
|
405
|
-
inputSchema: {
|
|
406
|
-
type: 'object',
|
|
407
|
-
properties: {
|
|
408
|
-
packageJson: { type: 'string', description: 'Conteúdo JSON ou caminho do package.json a auditar' }
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
},
|
|
412
|
-
{
|
|
413
|
-
name: 'agent_validate_api_contract',
|
|
414
|
-
description: 'Valida contratos OpenAPI 3.x / Swagger 2.0 (Loop 2) e detecta Drifts arquiteturais entre contrato e rotas implementadas no código (Shadow APIs e rotas ausentes).',
|
|
415
|
-
inputSchema: {
|
|
416
|
-
type: 'object',
|
|
417
|
-
properties: {
|
|
418
|
-
spec: { type: 'string', description: 'Conteúdo JSON ou caminho do arquivo OpenAPI/Swagger' },
|
|
419
|
-
implementedRoutes: {
|
|
420
|
-
type: 'array',
|
|
421
|
-
items: {
|
|
422
|
-
type: 'object',
|
|
423
|
-
properties: {
|
|
424
|
-
method: { type: 'string' },
|
|
425
|
-
path: { type: 'string' }
|
|
426
|
-
},
|
|
427
|
-
required: ['method', 'path']
|
|
428
|
-
},
|
|
429
|
-
description: 'Lista de rotas implementadas no código para detecção de Drift'
|
|
430
|
-
}
|
|
431
|
-
},
|
|
432
|
-
required: ['spec']
|
|
433
|
-
}
|
|
434
|
-
},
|
|
435
|
-
{
|
|
436
|
-
name: 'agent_smart_onboarding',
|
|
437
|
-
description: 'Executa a Regra 16: detecta modo Greenfield vs Brownfield, mapeia a stack via engenharia reversa e orquestra o auto-provisionamento de Jira e Confluence sem páginas vazias.',
|
|
438
|
-
inputSchema: {
|
|
439
|
-
type: 'object',
|
|
440
|
-
properties: {
|
|
441
|
-
targetDir: {
|
|
442
|
-
type: 'string',
|
|
443
|
-
description: 'Caminho do projeto para auditoria/onboarding'
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
},
|
|
448
|
-
{
|
|
449
|
-
name: 'agent_verify_triad_gate',
|
|
450
|
-
description: 'Valida o Gate de Governança da Regra 16: bloqueia prompts de desenvolvimento de software caso a Tríade (Git + Jira + Confluence) não esteja 100% configurada, verificada e operacional.',
|
|
451
|
-
inputSchema: {
|
|
452
|
-
type: 'object',
|
|
453
|
-
properties: {
|
|
454
|
-
targetDir: {
|
|
455
|
-
type: 'string',
|
|
456
|
-
description: 'Caminho raiz do projeto a ser validado pelo Gate'
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
},
|
|
461
|
-
{
|
|
462
|
-
name: 'agent_extract_code_skeleton',
|
|
463
|
-
description: 'Extrai o esqueleto semântico de código (Rule 9), eliminando corpos de métodos para reduzir em até 90% o consumo de tokens de contexto entre módulos.',
|
|
464
|
-
inputSchema: {
|
|
465
|
-
type: 'object',
|
|
466
|
-
properties: {
|
|
467
|
-
code: { type: 'string', description: 'Código fonte a ser esqueletizado' },
|
|
468
|
-
language: { type: 'string', description: 'Linguagem do código (javascript, typescript, java, python)' }
|
|
469
|
-
},
|
|
470
|
-
required: ['code']
|
|
471
|
-
}
|
|
472
|
-
},
|
|
473
|
-
{
|
|
474
|
-
name: 'agent_scaffold_feature',
|
|
475
|
-
description: 'Gera atomicamente em 1 único turno (< 25ms) todos os arquivos de uma funcionalidade completa (Model, Repository, Service, Controller REST e Teste TDD), eliminando múltiplos roundtrips.',
|
|
476
|
-
inputSchema: {
|
|
477
|
-
type: 'object',
|
|
478
|
-
properties: {
|
|
479
|
-
name: { type: 'string', description: 'Nome da entidade/funcionalidade (ex: Filme)' },
|
|
480
|
-
domain: { type: 'string', description: 'Domínio funcional (ex: filmes)' },
|
|
481
|
-
package: { type: 'string', description: 'Pacote base (ex: br.com.empresa.filmes)' },
|
|
482
|
-
stack: { type: 'string', enum: ['spring-boot', 'nodejs', 'typescript'], description: 'Stack tecnológica' },
|
|
483
|
-
fields: {
|
|
484
|
-
type: 'array',
|
|
485
|
-
items: {
|
|
486
|
-
type: 'object',
|
|
487
|
-
properties: {
|
|
488
|
-
name: { type: 'string' },
|
|
489
|
-
type: { type: 'string' },
|
|
490
|
-
required: { type: 'boolean' },
|
|
491
|
-
isId: { type: 'boolean' }
|
|
492
|
-
},
|
|
493
|
-
required: ['name', 'type']
|
|
494
|
-
},
|
|
495
|
-
description: 'Lista de atributos da entidade'
|
|
496
|
-
},
|
|
497
|
-
writeToDisk: { type: 'boolean', description: 'Se true, grava os arquivos diretamente nas pastas' }
|
|
498
|
-
},
|
|
499
|
-
required: ['name']
|
|
500
|
-
}
|
|
501
|
-
},
|
|
502
|
-
{
|
|
503
|
-
name: 'agent_set_mcp_profile',
|
|
504
|
-
description: 'Altera o perfil de ferramentas ativas do MCP (Late-Binding de Ferramentas) para economizar tokens de contexto: "all", "core", "qa_devsecops", "atlassian", "sre".',
|
|
505
|
-
inputSchema: {
|
|
506
|
-
type: 'object',
|
|
507
|
-
properties: {
|
|
508
|
-
profile: {
|
|
509
|
-
type: 'string',
|
|
510
|
-
enum: ['all', 'core', 'qa_devsecops', 'atlassian', 'sre'],
|
|
511
|
-
description: 'Perfil de ferramentas desejado'
|
|
512
|
-
}
|
|
513
|
-
},
|
|
514
|
-
required: ['profile']
|
|
515
|
-
}
|
|
516
|
-
},
|
|
517
|
-
{
|
|
518
|
-
name: 'agent_mine_domain_ideas',
|
|
519
|
-
description: 'Varredura inteligente de código-fonte de aplicação para identificar oportunidades reais de performance, resiliência, arquitetura e contratos, adicionando ao IDEAS.md.',
|
|
520
|
-
inputSchema: {
|
|
521
|
-
type: 'object',
|
|
522
|
-
properties: {
|
|
523
|
-
targetDir: {
|
|
524
|
-
type: 'string',
|
|
525
|
-
description: 'Diretório raiz do projeto para varredura (opcional, padrão: diretório atual).'
|
|
526
|
-
},
|
|
527
|
-
autoApply: {
|
|
528
|
-
type: 'boolean',
|
|
529
|
-
description: 'Se true, sincroniza as oportunidades descobertas diretamente em docs/IDEAS.md.'
|
|
530
|
-
},
|
|
531
|
-
dryRun: {
|
|
532
|
-
type: 'boolean',
|
|
533
|
-
description: 'Se true, apenas simula a sincronização sem alterar arquivos em disco.'
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
}
|
|
538
|
-
];
|
|
539
|
-
|
|
540
|
-
const RESOURCES = [
|
|
541
|
-
{
|
|
542
|
-
uri: 'agent://rules',
|
|
543
|
-
name: 'As 15 Regras de Ouro de Engenharia (ENGINEERING_RULES.md)',
|
|
544
|
-
mimeType: 'text/markdown'
|
|
545
|
-
},
|
|
546
|
-
{
|
|
547
|
-
uri: 'agent://architecture',
|
|
548
|
-
name: 'Arquitetura Multi-Agente & Handovers (ARCHITECTURE.md)',
|
|
549
|
-
mimeType: 'text/markdown'
|
|
550
|
-
},
|
|
551
|
-
{
|
|
552
|
-
uri: 'agent://ideas',
|
|
553
|
-
name: 'Backlog Vivo de Ideias & Auto-Evolução (IDEAS.md)',
|
|
554
|
-
mimeType: 'text/markdown'
|
|
555
|
-
},
|
|
556
|
-
{
|
|
557
|
-
uri: 'agent://events',
|
|
558
|
-
name: 'Histórico e Barramento de Eventos Multi-Agente',
|
|
559
|
-
mimeType: 'application/json'
|
|
560
|
-
}
|
|
561
|
-
];
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
const TOOL_PROFILES = Object.freeze({
|
|
565
|
-
all: null,
|
|
566
|
-
fast_dev: [
|
|
567
|
-
'agent_scaffold_feature',
|
|
568
|
-
'agent_audit_code',
|
|
569
|
-
'agent_verify_triad_gate',
|
|
570
|
-
'agent_set_mcp_profile'
|
|
571
|
-
],
|
|
572
|
-
core: [
|
|
573
|
-
'agent_get_rule',
|
|
574
|
-
'agent_validate_idea',
|
|
575
|
-
'agent_orchestrate_event',
|
|
576
|
-
'agent_check_credentials',
|
|
577
|
-
'agent_bootstrap_environment',
|
|
578
|
-
'agent_compress_context',
|
|
579
|
-
'agent_full_dev_status',
|
|
580
|
-
'agent_set_mcp_profile',
|
|
581
|
-
'agent_smart_onboarding',
|
|
582
|
-
'agent_verify_triad_gate',
|
|
583
|
-
'agent_extract_code_skeleton',
|
|
584
|
-
'agent_scaffold_feature'
|
|
585
|
-
],
|
|
586
|
-
qa_devsecops: [
|
|
587
|
-
'agent_audit_code',
|
|
588
|
-
'agent_review_pr',
|
|
589
|
-
'agent_sast_scan',
|
|
590
|
-
'agent_audit_quality',
|
|
591
|
-
'agent_audit_dependencies_sca',
|
|
592
|
-
'agent_validate_api_contract',
|
|
593
|
-
'agent_lint_git_hygiene',
|
|
594
|
-
'agent_audit_a11y',
|
|
595
|
-
'agent_set_mcp_profile'
|
|
596
|
-
],
|
|
597
|
-
atlassian: [
|
|
598
|
-
'agent_sync_atlassian',
|
|
599
|
-
'agent_standardize_kanban',
|
|
600
|
-
'agent_full_dev_pipeline',
|
|
601
|
-
'agent_validate_rule15',
|
|
602
|
-
'agent_configure_credentials',
|
|
603
|
-
'agent_check_credentials',
|
|
604
|
-
'agent_set_mcp_profile'
|
|
605
|
-
],
|
|
606
|
-
sre: [
|
|
607
|
-
'agent_sre_telemetry',
|
|
608
|
-
'agent_sre_remediate',
|
|
609
|
-
'agent_otel_trace',
|
|
610
|
-
'agent_perf_benchmark',
|
|
611
|
-
'agent_circuit_breaker',
|
|
612
|
-
'agent_set_mcp_profile'
|
|
613
|
-
]
|
|
614
|
-
});
|
|
615
|
-
|
|
616
|
-
let activeProfile = process.env.MCP_PROFILE || 'all';
|
|
617
|
-
|
|
618
|
-
function getActiveTools() {
|
|
619
|
-
const profileName = String(activeProfile).toLowerCase();
|
|
620
|
-
const allowed = TOOL_PROFILES[profileName];
|
|
621
|
-
if (!allowed) return TOOLS;
|
|
622
|
-
return TOOLS.filter(t => allowed.includes(t.name));
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
function setMcpProfile(profile) {
|
|
626
|
-
const target = String(profile).toLowerCase();
|
|
627
|
-
if (TOOL_PROFILES[target] !== undefined) {
|
|
628
|
-
activeProfile = target;
|
|
629
|
-
return { success: true, profile: target, activeToolsCount: getActiveTools().length };
|
|
630
|
-
}
|
|
631
|
-
return { success: false, error: `Perfil inválido: ${profile}. Opções válidas: all, core, qa_devsecops, atlassian, sre` };
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
function handleInitialize(id) {
|
|
635
|
-
return {
|
|
636
|
-
jsonrpc: '2.0',
|
|
637
|
-
id,
|
|
638
|
-
result: {
|
|
639
|
-
protocolVersion: '2024-11-05',
|
|
640
|
-
capabilities: {
|
|
641
|
-
tools: {},
|
|
642
|
-
resources: {}
|
|
643
|
-
},
|
|
644
|
-
serverInfo: {
|
|
645
|
-
name: 'agent-master-devsecops-mcp',
|
|
646
|
-
version: '3.2.0'
|
|
647
|
-
}
|
|
648
|
-
}
|
|
649
|
-
};
|
|
650
|
-
}
|
|
651
|
-
|
|
652
|
-
function handleToolsList(id) {
|
|
653
|
-
return {
|
|
654
|
-
jsonrpc: '2.0',
|
|
655
|
-
id,
|
|
656
|
-
result: {
|
|
657
|
-
tools: getActiveTools()
|
|
658
|
-
}
|
|
659
|
-
};
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
function handleResourcesList(id) {
|
|
663
|
-
return {
|
|
664
|
-
jsonrpc: '2.0',
|
|
665
|
-
id,
|
|
666
|
-
result: {
|
|
667
|
-
resources: RESOURCES
|
|
668
|
-
}
|
|
669
|
-
};
|
|
670
|
-
}
|
|
671
|
-
|
|
672
|
-
function handleResourceRead(id, params) {
|
|
673
|
-
const uri = params && params.uri;
|
|
674
|
-
let filePath = null;
|
|
675
|
-
|
|
676
|
-
if (uri === 'agent://rules') {
|
|
677
|
-
filePath = resolveDocFile(ROOT_DIR, 'docs/ENGINEERING_RULES.md');
|
|
678
|
-
} else if (uri === 'agent://architecture') {
|
|
679
|
-
filePath = resolveDocFile(ROOT_DIR, 'docs/ARCHITECTURE.md');
|
|
680
|
-
} else if (uri === 'agent://ideas') {
|
|
681
|
-
filePath = resolveDocFile(ROOT_DIR, 'docs/IDEAS.md');
|
|
682
|
-
} else if (uri === 'agent://events') {
|
|
683
|
-
const { EVENT_TYPES } = require('./multi_agent_orchestrator.js');
|
|
684
|
-
return {
|
|
685
|
-
jsonrpc: '2.0',
|
|
686
|
-
id,
|
|
687
|
-
result: {
|
|
688
|
-
contents: [
|
|
689
|
-
{
|
|
690
|
-
uri,
|
|
691
|
-
mimeType: 'application/json',
|
|
692
|
-
text: JSON.stringify({
|
|
693
|
-
status: 'ACTIVE',
|
|
694
|
-
busType: 'Mesh-Hierarchical Event Bus',
|
|
695
|
-
supportedEvents: Object.keys(EVENT_TYPES)
|
|
696
|
-
}, null, 2)
|
|
697
|
-
}
|
|
698
|
-
]
|
|
699
|
-
}
|
|
700
|
-
};
|
|
701
|
-
}
|
|
702
|
-
|
|
703
|
-
if (filePath && fs.existsSync(filePath)) {
|
|
704
|
-
const text = fs.readFileSync(filePath, 'utf8');
|
|
705
|
-
return {
|
|
706
|
-
jsonrpc: '2.0',
|
|
707
|
-
id,
|
|
708
|
-
result: {
|
|
709
|
-
contents: [
|
|
710
|
-
{
|
|
711
|
-
uri,
|
|
712
|
-
mimeType: 'text/markdown',
|
|
713
|
-
text
|
|
714
|
-
}
|
|
715
|
-
]
|
|
716
|
-
}
|
|
717
|
-
};
|
|
718
|
-
}
|
|
719
|
-
|
|
720
|
-
return {
|
|
721
|
-
jsonrpc: '2.0',
|
|
722
|
-
id,
|
|
723
|
-
error: {
|
|
724
|
-
code: -32602,
|
|
725
|
-
message: `Recurso não encontrado: ${uri}`
|
|
726
|
-
}
|
|
727
|
-
};
|
|
728
|
-
}
|
|
729
|
-
|
|
730
|
-
function handleToolCall(id, params) {
|
|
731
|
-
const { name, arguments: args } = params;
|
|
732
|
-
|
|
733
|
-
if (name === 'agent_get_rule') {
|
|
734
|
-
const num = args.ruleNumber;
|
|
735
|
-
const rulesPath = resolveDocFile(ROOT_DIR, 'docs/ENGINEERING_RULES.md');
|
|
736
|
-
if (!fs.existsSync(rulesPath)) {
|
|
737
|
-
return { jsonrpc: '2.0', id, error: { code: -32603, message: 'ENGINEERING_RULES.md não encontrado.' } };
|
|
738
|
-
}
|
|
739
|
-
const content = fs.readFileSync(rulesPath, 'utf8');
|
|
740
|
-
const regex = new RegExp(`(^|\\n)\\s*${num}\\.\\s*([\\s\\S]*?)(?=\\n\\s*\\d+\\.|$)`, 'm');
|
|
741
|
-
const match = content.match(regex);
|
|
742
|
-
const ruleText = match ? match[0].trim() : `Regra ${num} não encontrada em ENGINEERING_RULES.md.`;
|
|
743
|
-
|
|
744
|
-
return {
|
|
745
|
-
jsonrpc: '2.0',
|
|
746
|
-
id,
|
|
747
|
-
result: {
|
|
748
|
-
content: [
|
|
749
|
-
{
|
|
750
|
-
type: 'text',
|
|
751
|
-
text: ruleText
|
|
752
|
-
}
|
|
753
|
-
]
|
|
754
|
-
}
|
|
755
|
-
};
|
|
756
|
-
}
|
|
757
|
-
|
|
758
|
-
if (name === 'agent_validate_idea') {
|
|
759
|
-
const { ideaTitle, ideaDescription, projectStack, projectDomain } = args;
|
|
760
|
-
|
|
761
|
-
// Análise contextual empírica
|
|
762
|
-
const isOffDomain = /blockchain|crypto|metaverse|web3/i.test(ideaTitle + ideaDescription) && !/crypto|blockchain/i.test(projectDomain);
|
|
763
|
-
const isOverengineering = /kubernetes|kafka|microservices|distributed/i.test(ideaTitle + ideaDescription) && /bot|cli|pequeno|monolito|sqlite/i.test(projectStack + projectDomain);
|
|
764
|
-
|
|
765
|
-
let approved = true;
|
|
766
|
-
let verdict = 'APROVADA';
|
|
767
|
-
let rationale = 'A ideia apresenta coerência arquitetural com a stack e o domínio fornecidos.';
|
|
768
|
-
|
|
769
|
-
if (isOffDomain) {
|
|
770
|
-
approved = false;
|
|
771
|
-
verdict = 'REJEITADA (Critério 1: Desconexão de Domínio)';
|
|
772
|
-
rationale = 'A proposta introduz componentes fora do propósito e regras de negócio da aplicação.';
|
|
773
|
-
} else if (isOverengineering) {
|
|
774
|
-
approved = false;
|
|
775
|
-
verdict = 'REJEITADA (Critério 2: Overengineering / Complexidade Artificial)';
|
|
776
|
-
rationale = 'A solução proposta introduz complexidade operacional desproporcional à escala do projeto.';
|
|
777
|
-
}
|
|
778
|
-
|
|
779
|
-
return {
|
|
780
|
-
jsonrpc: '2.0',
|
|
781
|
-
id,
|
|
782
|
-
result: {
|
|
783
|
-
content: [
|
|
784
|
-
{
|
|
785
|
-
type: 'text',
|
|
786
|
-
text: JSON.stringify({
|
|
787
|
-
idea: ideaTitle,
|
|
788
|
-
veredito: verdict,
|
|
789
|
-
aprovado: approved,
|
|
790
|
-
justificativa: rationale,
|
|
791
|
-
regra: 'Regra 14 - Ideation Sanity Filter'
|
|
792
|
-
}, null, 2)
|
|
793
|
-
}
|
|
794
|
-
]
|
|
795
|
-
}
|
|
796
|
-
};
|
|
797
|
-
}
|
|
798
|
-
|
|
799
|
-
if (name === 'agent_audit_code') {
|
|
800
|
-
const { codeDiff } = args;
|
|
801
|
-
const issues = [];
|
|
802
|
-
|
|
803
|
-
// Inspeção fria por vulnerabilidades comuns
|
|
804
|
-
if (/eval\(|new Function\(|child_process\.exec\(/i.test(codeDiff)) {
|
|
805
|
-
issues.push({
|
|
806
|
-
tipo: 'Command / Code Injection',
|
|
807
|
-
gravidade: 'CRÍTICA',
|
|
808
|
-
cwe: 'CWE-94 / CWE-78',
|
|
809
|
-
detalhe: 'Uso de funções perigosas de execução dinâmica de strings.'
|
|
810
|
-
});
|
|
811
|
-
}
|
|
812
|
-
|
|
813
|
-
if (/(["'][a-zA-Z0-9_\-]{20,}["'])/.test(codeDiff) && /token|secret|password|key/i.test(codeDiff)) {
|
|
814
|
-
issues.push({
|
|
815
|
-
tipo: 'Hardcoded Secret Exposure',
|
|
816
|
-
gravidade: 'CRÍTICA',
|
|
817
|
-
cwe: 'CWE-798',
|
|
818
|
-
detalhe: 'Possível segredo ou credencial embutida em texto plano no diff.'
|
|
819
|
-
});
|
|
820
|
-
}
|
|
821
|
-
|
|
822
|
-
if (/<[^>]+>.*<[^>]+>/i.test(codeDiff) && !/stripHtml|sanitize|recursiv/i.test(codeDiff)) {
|
|
823
|
-
issues.push({
|
|
824
|
-
tipo: 'HTML Sanitization Bypass',
|
|
825
|
-
gravidade: 'ALTA',
|
|
826
|
-
cwe: 'CWE-116 / CWE-79',
|
|
827
|
-
detalhe: 'Manipulação de strings HTML sem sanitização recursiva comprovada.'
|
|
828
|
-
});
|
|
829
|
-
}
|
|
830
|
-
|
|
831
|
-
const verdict = issues.length === 0 ? 'APROVADO' : (issues.some(i => i.gravidade === 'CRÍTICA') ? 'REPROVADO' : 'APROVADO COM RESSALVAS');
|
|
832
|
-
|
|
833
|
-
return {
|
|
834
|
-
jsonrpc: '2.0',
|
|
835
|
-
id,
|
|
836
|
-
result: {
|
|
837
|
-
content: [
|
|
838
|
-
{
|
|
839
|
-
type: 'text',
|
|
840
|
-
text: JSON.stringify({
|
|
841
|
-
veredito: verdict,
|
|
842
|
-
defeitosEncontrados: issues,
|
|
843
|
-
auditor: 'Revisor Crítico Adversário (AGENT_QA.md)',
|
|
844
|
-
totalIssues: issues.length
|
|
845
|
-
}, null, 2)
|
|
846
|
-
}
|
|
847
|
-
]
|
|
848
|
-
}
|
|
849
|
-
};
|
|
850
|
-
}
|
|
851
|
-
|
|
852
|
-
if (name === 'agent_full_dev_status') {
|
|
853
|
-
const ideasPath = path.join(ROOT_DIR, 'docs', 'IDEAS.md');
|
|
854
|
-
let nextIdea = 'Nenhuma ideia pendente no backlog aberto.';
|
|
855
|
-
if (fs.existsSync(ideasPath)) {
|
|
856
|
-
const ideasContent = fs.readFileSync(ideasPath, 'utf8');
|
|
857
|
-
const lines = ideasContent.split(/\r?\n/);
|
|
858
|
-
for (const line of lines) {
|
|
859
|
-
const trimmed = line.trim();
|
|
860
|
-
if (/^- I-\d+/.test(trimmed)) {
|
|
861
|
-
if (!/\[(CONCLUÍDO|EM PRODUÇÃO|DONE|DROP|REJEITAD[OA]|ARCHIVED)\]/i.test(trimmed)) {
|
|
862
|
-
nextIdea = trimmed.replace(/^- /, '');
|
|
863
|
-
break;
|
|
864
|
-
}
|
|
865
|
-
}
|
|
866
|
-
}
|
|
867
|
-
}
|
|
868
|
-
|
|
869
|
-
return {
|
|
870
|
-
jsonrpc: '2.0',
|
|
871
|
-
id,
|
|
872
|
-
result: {
|
|
873
|
-
content: [
|
|
874
|
-
{
|
|
875
|
-
type: 'text',
|
|
876
|
-
text: JSON.stringify({
|
|
877
|
-
modo: 'full-dev',
|
|
878
|
-
status: 'ATIVO',
|
|
879
|
-
proximaIdeia: nextIdea,
|
|
880
|
-
regrasAtivas: 14,
|
|
881
|
-
governance: 'Tríplice Registro Obrigatório (Git, Jira, Confluence)'
|
|
882
|
-
}, null, 2)
|
|
883
|
-
}
|
|
884
|
-
]
|
|
885
|
-
}
|
|
886
|
-
};
|
|
887
|
-
}
|
|
888
|
-
|
|
889
|
-
if (name === 'agent_eval_harness') {
|
|
890
|
-
const { evaluateResponse } = require('./eval_harness.js');
|
|
891
|
-
const { modelName, promptSent, responseReceived } = args;
|
|
892
|
-
const report = evaluateResponse(modelName, promptSent, responseReceived);
|
|
893
|
-
|
|
894
|
-
return {
|
|
895
|
-
jsonrpc: '2.0',
|
|
896
|
-
id,
|
|
897
|
-
result: {
|
|
898
|
-
content: [
|
|
899
|
-
{
|
|
900
|
-
type: 'text',
|
|
901
|
-
text: JSON.stringify(report, null, 2)
|
|
902
|
-
}
|
|
903
|
-
]
|
|
904
|
-
}
|
|
905
|
-
};
|
|
906
|
-
}
|
|
907
|
-
|
|
908
|
-
if (name === 'agent_generate_ide_plugins') {
|
|
909
|
-
const { generateIdeConfigs } = safeRequire('./universal_packager.js');
|
|
910
|
-
const target = (args && args.target) || 'all';
|
|
911
|
-
const targetDir = (args && args.targetDir) || ROOT_DIR;
|
|
912
|
-
const generated = generateIdeConfigs(targetDir, target);
|
|
913
|
-
|
|
914
|
-
return {
|
|
915
|
-
jsonrpc: '2.0',
|
|
916
|
-
id,
|
|
917
|
-
result: {
|
|
918
|
-
content: [
|
|
919
|
-
{
|
|
920
|
-
type: 'text',
|
|
921
|
-
text: JSON.stringify({
|
|
922
|
-
status: 'SUCCESS',
|
|
923
|
-
generatedFiles: generated,
|
|
924
|
-
target,
|
|
925
|
-
targetDir
|
|
926
|
-
}, null, 2)
|
|
927
|
-
}
|
|
928
|
-
]
|
|
929
|
-
}
|
|
930
|
-
};
|
|
931
|
-
}
|
|
932
|
-
|
|
933
|
-
if (name === 'agent_review_pr') {
|
|
934
|
-
const { analyzeDiff, formatReport } = require('./pr_reviewer.js');
|
|
935
|
-
const diff = (args && args.diff) || '';
|
|
936
|
-
const files = (args && args.files) || [];
|
|
937
|
-
const analysis = analyzeDiff(diff, files);
|
|
938
|
-
const report = formatReport(analysis);
|
|
939
|
-
|
|
940
|
-
return {
|
|
941
|
-
jsonrpc: '2.0',
|
|
942
|
-
id,
|
|
943
|
-
result: {
|
|
944
|
-
content: [
|
|
945
|
-
{
|
|
946
|
-
type: 'text',
|
|
947
|
-
text: JSON.stringify({
|
|
948
|
-
veredito: analysis.verdict,
|
|
949
|
-
analise: analysis,
|
|
950
|
-
relatorioCanonico: report
|
|
951
|
-
}, null, 2)
|
|
952
|
-
}
|
|
953
|
-
]
|
|
954
|
-
}
|
|
955
|
-
};
|
|
956
|
-
}
|
|
957
|
-
|
|
958
|
-
if (name === 'agent_compress_context') {
|
|
959
|
-
const { generateCompactPrompt, compressCustomText, estimateTokens } = require('./context_compressor.js');
|
|
960
|
-
const customText = args && args.text;
|
|
961
|
-
const maxTokens = (args && args.maxTokens) || 1500;
|
|
962
|
-
|
|
963
|
-
let compressedText = '';
|
|
964
|
-
if (customText) {
|
|
965
|
-
compressedText = compressCustomText(customText, maxTokens);
|
|
966
|
-
} else {
|
|
967
|
-
compressedText = generateCompactPrompt();
|
|
968
|
-
}
|
|
969
|
-
|
|
970
|
-
const tokenCount = estimateTokens(compressedText);
|
|
971
|
-
return {
|
|
972
|
-
jsonrpc: '2.0',
|
|
973
|
-
id,
|
|
974
|
-
result: {
|
|
975
|
-
content: [
|
|
976
|
-
{
|
|
977
|
-
type: 'text',
|
|
978
|
-
text: JSON.stringify({
|
|
979
|
-
status: 'SUCCESS',
|
|
980
|
-
tokensEstimados: tokenCount,
|
|
981
|
-
limiteTokens: maxTokens,
|
|
982
|
-
dentroDoOrcamento: tokenCount <= maxTokens,
|
|
983
|
-
tamanhoCaracteres: compressedText.length,
|
|
984
|
-
textoCompactado: compressedText
|
|
985
|
-
}, null, 2)
|
|
986
|
-
}
|
|
987
|
-
]
|
|
988
|
-
}
|
|
989
|
-
};
|
|
990
|
-
}
|
|
991
|
-
|
|
992
|
-
if (name === 'agent_sync_atlassian') {
|
|
993
|
-
const { extractIssueKeys, formatRemoteLinkPayload, getAuth } = require('./atlassian_sync_action.js');
|
|
994
|
-
const { issueKey, url, title, type } = args;
|
|
995
|
-
const authConfigured = Boolean(getAuth());
|
|
996
|
-
const payload = formatRemoteLinkPayload(url, title, type || 'commit');
|
|
997
|
-
|
|
998
|
-
return {
|
|
999
|
-
jsonrpc: '2.0',
|
|
1000
|
-
id,
|
|
1001
|
-
result: {
|
|
1002
|
-
content: [
|
|
1003
|
-
{
|
|
1004
|
-
type: 'text',
|
|
1005
|
-
text: JSON.stringify({
|
|
1006
|
-
status: authConfigured ? 'READY_TO_SYNC' : 'SKIPPED_NO_AUTH',
|
|
1007
|
-
issueKey,
|
|
1008
|
-
authConfigured,
|
|
1009
|
-
remoteLinkPayload: payload
|
|
1010
|
-
}, null, 2)
|
|
1011
|
-
}
|
|
1012
|
-
]
|
|
1013
|
-
}
|
|
1014
|
-
};
|
|
1015
|
-
}
|
|
1016
|
-
|
|
1017
|
-
if (name === 'agent_otel_trace') {
|
|
1018
|
-
const { Tracer } = require('./otel_tracer.js');
|
|
1019
|
-
const serviceName = (args && args.serviceName) || 'agent-service';
|
|
1020
|
-
const thresholdMs = (args && args.thresholdMs) || 50;
|
|
1021
|
-
const tracer = new Tracer(serviceName);
|
|
1022
|
-
|
|
1023
|
-
const inputSpans = (args && args.spans) || [
|
|
1024
|
-
{ name: 'op_request', durationMs: 15 },
|
|
1025
|
-
{ name: 'llm_inference', durationMs: 70 },
|
|
1026
|
-
{ name: 'response_formatting', durationMs: 10 }
|
|
1027
|
-
];
|
|
1028
|
-
|
|
1029
|
-
let runningOffset = Date.now();
|
|
1030
|
-
let rootSpan = null;
|
|
1031
|
-
|
|
1032
|
-
inputSpans.forEach((s, idx) => {
|
|
1033
|
-
const span = tracer.startSpan(s.name, {
|
|
1034
|
-
startTime: runningOffset,
|
|
1035
|
-
parentSpanId: idx > 0 && rootSpan ? rootSpan.spanId : null,
|
|
1036
|
-
attributes: s.attributes || {}
|
|
1037
|
-
});
|
|
1038
|
-
span.end(runningOffset + s.durationMs);
|
|
1039
|
-
if (idx === 0) rootSpan = span;
|
|
1040
|
-
runningOffset += s.durationMs;
|
|
1041
|
-
});
|
|
1042
|
-
|
|
1043
|
-
const bottlenecks = tracer.analyzeBottlenecks(thresholdMs);
|
|
1044
|
-
const flamegraph = tracer.renderFlamegraphAscii();
|
|
1045
|
-
const traceContext = tracer.getTraceContext(rootSpan);
|
|
1046
|
-
|
|
1047
|
-
return {
|
|
1048
|
-
jsonrpc: '2.0',
|
|
1049
|
-
id,
|
|
1050
|
-
result: {
|
|
1051
|
-
content: [
|
|
1052
|
-
{
|
|
1053
|
-
type: 'text',
|
|
1054
|
-
text: JSON.stringify({
|
|
1055
|
-
traceId: traceContext.traceId,
|
|
1056
|
-
traceparent: traceContext.traceparent,
|
|
1057
|
-
serviceName,
|
|
1058
|
-
totalSpans: tracer.spans.length,
|
|
1059
|
-
gargalosDetectados: bottlenecks,
|
|
1060
|
-
flamegraph
|
|
1061
|
-
}, null, 2)
|
|
1062
|
-
}
|
|
1063
|
-
]
|
|
1064
|
-
}
|
|
1065
|
-
};
|
|
1066
|
-
}
|
|
1067
|
-
|
|
1068
|
-
if (name === 'agent_perf_benchmark') {
|
|
1069
|
-
const { runBenchmark, comparePerformance, formatPerfReport, getOrInitBaseline } = require('./perf_benchmark.js');
|
|
1070
|
-
const iterations = (args && args.iterations) || 50;
|
|
1071
|
-
const maxDegradationPct = (args && args.maxDegradationPct) || 15;
|
|
1072
|
-
|
|
1073
|
-
const baseline = getOrInitBaseline();
|
|
1074
|
-
const current = runBenchmark(iterations);
|
|
1075
|
-
const comparison = comparePerformance(current, baseline, maxDegradationPct);
|
|
1076
|
-
const report = formatPerfReport(comparison);
|
|
1077
|
-
|
|
1078
|
-
return {
|
|
1079
|
-
jsonrpc: '2.0',
|
|
1080
|
-
id,
|
|
1081
|
-
result: {
|
|
1082
|
-
content: [
|
|
1083
|
-
{
|
|
1084
|
-
type: 'text',
|
|
1085
|
-
text: JSON.stringify({
|
|
1086
|
-
veredito: comparison.verdict,
|
|
1087
|
-
passou: comparison.passed,
|
|
1088
|
-
metricas: current,
|
|
1089
|
-
deltas: comparison.deltas,
|
|
1090
|
-
relatorio: report
|
|
1091
|
-
}, null, 2)
|
|
1092
|
-
}
|
|
1093
|
-
]
|
|
1094
|
-
}
|
|
1095
|
-
};
|
|
1096
|
-
}
|
|
1097
|
-
|
|
1098
|
-
if (name === 'agent_circuit_breaker') {
|
|
1099
|
-
const { MultiProviderRouter } = require('./circuit_breaker.js');
|
|
1100
|
-
const action = (args && args.action) || 'status';
|
|
1101
|
-
const failureThreshold = (args && args.failureThreshold) || 3;
|
|
1102
|
-
const router = new MultiProviderRouter(['anthropic', 'openai', 'groq', 'ollama'], { failureThreshold });
|
|
1103
|
-
|
|
1104
|
-
if (action === 'reset') {
|
|
1105
|
-
router.resetAll();
|
|
1106
|
-
return {
|
|
1107
|
-
jsonrpc: '2.0',
|
|
1108
|
-
id,
|
|
1109
|
-
result: {
|
|
1110
|
-
content: [
|
|
1111
|
-
{
|
|
1112
|
-
type: 'text',
|
|
1113
|
-
text: JSON.stringify({
|
|
1114
|
-
status: 'SUCCESS',
|
|
1115
|
-
action: 'reset',
|
|
1116
|
-
circuitStates: router.getAllStatuses()
|
|
1117
|
-
}, null, 2)
|
|
1118
|
-
}
|
|
1119
|
-
]
|
|
1120
|
-
}
|
|
1121
|
-
};
|
|
1122
|
-
}
|
|
1123
|
-
|
|
1124
|
-
if (action === 'simulate_failover') {
|
|
1125
|
-
const taskMap = {
|
|
1126
|
-
anthropic: () => { throw new Error('HTTP 429: Too Many Requests (Rate limit)'); },
|
|
1127
|
-
openai: () => { throw new Error('HTTP 503: Service Unavailable'); },
|
|
1128
|
-
groq: () => 'Resposta gerada com sucesso via Groq (Llama 3.3 70B)',
|
|
1129
|
-
ollama: () => 'Resposta via Ollama local'
|
|
1130
|
-
};
|
|
1131
|
-
|
|
1132
|
-
const dispatchRes = router.dispatchSync(taskMap);
|
|
1133
|
-
return {
|
|
1134
|
-
jsonrpc: '2.0',
|
|
1135
|
-
id,
|
|
1136
|
-
result: {
|
|
1137
|
-
content: [
|
|
1138
|
-
{
|
|
1139
|
-
type: 'text',
|
|
1140
|
-
text: JSON.stringify({
|
|
1141
|
-
status: 'SUCCESS',
|
|
1142
|
-
action: 'simulate_failover',
|
|
1143
|
-
dispatchResult: dispatchRes
|
|
1144
|
-
}, null, 2)
|
|
1145
|
-
}
|
|
1146
|
-
]
|
|
1147
|
-
}
|
|
1148
|
-
};
|
|
1149
|
-
}
|
|
1150
|
-
|
|
1151
|
-
// Default: 'status'
|
|
1152
|
-
return {
|
|
1153
|
-
jsonrpc: '2.0',
|
|
1154
|
-
id,
|
|
1155
|
-
result: {
|
|
1156
|
-
content: [
|
|
1157
|
-
{
|
|
1158
|
-
type: 'text',
|
|
1159
|
-
text: JSON.stringify({
|
|
1160
|
-
status: 'SUCCESS',
|
|
1161
|
-
action: 'status',
|
|
1162
|
-
circuitStates: router.getAllStatuses()
|
|
1163
|
-
}, null, 2)
|
|
1164
|
-
}
|
|
1165
|
-
]
|
|
1166
|
-
}
|
|
1167
|
-
};
|
|
1168
|
-
}
|
|
1169
|
-
|
|
1170
|
-
if (name === 'agent_orchestrate_event') {
|
|
1171
|
-
const { MultiAgentOrchestrator } = require('./multi_agent_orchestrator.js');
|
|
1172
|
-
const orchestrator = new MultiAgentOrchestrator();
|
|
1173
|
-
const eventType = args && args.eventType;
|
|
1174
|
-
const payload = (args && args.payload) || {};
|
|
1175
|
-
|
|
1176
|
-
const eventRecord = orchestrator.dispatch(eventType, payload);
|
|
1177
|
-
return {
|
|
1178
|
-
jsonrpc: '2.0',
|
|
1179
|
-
id,
|
|
1180
|
-
result: {
|
|
1181
|
-
content: [
|
|
1182
|
-
{
|
|
1183
|
-
type: 'text',
|
|
1184
|
-
text: JSON.stringify({
|
|
1185
|
-
status: 'SUCCESS',
|
|
1186
|
-
eventRecord
|
|
1187
|
-
}, null, 2)
|
|
1188
|
-
}
|
|
1189
|
-
]
|
|
1190
|
-
}
|
|
1191
|
-
};
|
|
1192
|
-
}
|
|
1193
|
-
|
|
1194
|
-
if (name === 'agent_sast_scan') {
|
|
1195
|
-
const { SastScanner } = require('./sast_scanner.js');
|
|
1196
|
-
const scanner = new SastScanner();
|
|
1197
|
-
const code = (args && args.code) || '';
|
|
1198
|
-
const filename = (args && args.filename) || 'snippet.js';
|
|
1199
|
-
const scanResult = scanner.scanCode(code, filename);
|
|
1200
|
-
|
|
1201
|
-
return {
|
|
1202
|
-
jsonrpc: '2.0',
|
|
1203
|
-
id,
|
|
1204
|
-
result: {
|
|
1205
|
-
content: [
|
|
1206
|
-
{
|
|
1207
|
-
type: 'text',
|
|
1208
|
-
text: JSON.stringify(scanResult, null, 2)
|
|
1209
|
-
}
|
|
1210
|
-
]
|
|
1211
|
-
}
|
|
1212
|
-
};
|
|
1213
|
-
}
|
|
1214
|
-
|
|
1215
|
-
if (name === 'agent_audit_quality') {
|
|
1216
|
-
const { CodeQualityAuditor } = require('./code_quality_auditor.js');
|
|
1217
|
-
const maxComplexity = (args && args.maxComplexity) || 15;
|
|
1218
|
-
const auditor = new CodeQualityAuditor({ maxComplexity });
|
|
1219
|
-
const code = (args && args.code) || '';
|
|
1220
|
-
const filename = (args && args.filename) || 'snippet.js';
|
|
1221
|
-
const auditResult = auditor.auditCode(code, filename);
|
|
1222
|
-
|
|
1223
|
-
return {
|
|
1224
|
-
jsonrpc: '2.0',
|
|
1225
|
-
id,
|
|
1226
|
-
result: {
|
|
1227
|
-
content: [
|
|
1228
|
-
{
|
|
1229
|
-
type: 'text',
|
|
1230
|
-
text: JSON.stringify(auditResult, null, 2)
|
|
1231
|
-
}
|
|
1232
|
-
]
|
|
1233
|
-
}
|
|
1234
|
-
};
|
|
1235
|
-
}
|
|
1236
|
-
|
|
1237
|
-
if (name === 'agent_sre_telemetry') {
|
|
1238
|
-
const { SreRemediationEngine } = require('./sre_remediation_engine.js');
|
|
1239
|
-
const engine = new SreRemediationEngine();
|
|
1240
|
-
const format = (args && args.format) || 'json';
|
|
1241
|
-
const evaluateAlerts = args && args.evaluateAlerts;
|
|
1242
|
-
|
|
1243
|
-
let responseData;
|
|
1244
|
-
if (format === 'prometheus') {
|
|
1245
|
-
responseData = engine.getPrometheusFormat();
|
|
1246
|
-
} else {
|
|
1247
|
-
responseData = {
|
|
1248
|
-
summary: engine.getMetricsSummary(),
|
|
1249
|
-
...(evaluateAlerts ? { alertsEvaluation: engine.evaluateAlerts() } : {})
|
|
1250
|
-
};
|
|
1251
|
-
}
|
|
1252
|
-
|
|
1253
|
-
return {
|
|
1254
|
-
jsonrpc: '2.0',
|
|
1255
|
-
id,
|
|
1256
|
-
result: {
|
|
1257
|
-
content: [
|
|
1258
|
-
{
|
|
1259
|
-
type: 'text',
|
|
1260
|
-
text: typeof responseData === 'string' ? responseData : JSON.stringify(responseData, null, 2)
|
|
1261
|
-
}
|
|
1262
|
-
]
|
|
1263
|
-
}
|
|
1264
|
-
};
|
|
1265
|
-
}
|
|
1266
|
-
|
|
1267
|
-
if (name === 'agent_sre_remediate') {
|
|
1268
|
-
const { SreRemediationEngine } = require('./sre_remediation_engine.js');
|
|
1269
|
-
const engine = new SreRemediationEngine();
|
|
1270
|
-
const action = args && args.action;
|
|
1271
|
-
const context = (args && args.context) || {};
|
|
1272
|
-
|
|
1273
|
-
const remediationRecord = engine.executeRemediation(action, context);
|
|
1274
|
-
|
|
1275
|
-
return {
|
|
1276
|
-
jsonrpc: '2.0',
|
|
1277
|
-
id,
|
|
1278
|
-
result: {
|
|
1279
|
-
content: [
|
|
1280
|
-
{
|
|
1281
|
-
type: 'text',
|
|
1282
|
-
text: JSON.stringify({
|
|
1283
|
-
status: 'SUCCESS',
|
|
1284
|
-
remediationRecord
|
|
1285
|
-
}, null, 2)
|
|
1286
|
-
}
|
|
1287
|
-
]
|
|
1288
|
-
}
|
|
1289
|
-
};
|
|
1290
|
-
}
|
|
1291
|
-
|
|
1292
|
-
if (name === 'agent_export_universal_bundle') {
|
|
1293
|
-
const { UniversalPackager } = require('./universal_packager.js');
|
|
1294
|
-
const packager = new UniversalPackager();
|
|
1295
|
-
const platform = (args && args.platform) || 'all';
|
|
1296
|
-
const targetDir = (args && args.targetDir) || path.join(ROOT_DIR, 'dist', 'bundles', platform);
|
|
1297
|
-
const dryRun = args && args.dryRun;
|
|
1298
|
-
|
|
1299
|
-
const result = packager.exportProfile(platform, targetDir, { dryRun });
|
|
1300
|
-
|
|
1301
|
-
return {
|
|
1302
|
-
jsonrpc: '2.0',
|
|
1303
|
-
id,
|
|
1304
|
-
result: {
|
|
1305
|
-
content: [
|
|
1306
|
-
{
|
|
1307
|
-
type: 'text',
|
|
1308
|
-
text: JSON.stringify({
|
|
1309
|
-
status: 'SUCCESS',
|
|
1310
|
-
exportResult: result
|
|
1311
|
-
}, null, 2)
|
|
1312
|
-
}
|
|
1313
|
-
]
|
|
1314
|
-
}
|
|
1315
|
-
};
|
|
1316
|
-
}
|
|
1317
|
-
|
|
1318
|
-
if (name === 'agent_bootstrap_environment') {
|
|
1319
|
-
const { bootstrapEnvironment } = require('./bootstrap_cli.js');
|
|
1320
|
-
const targetDir = (args && args.targetDir) || ROOT_DIR;
|
|
1321
|
-
const dryRun = args && args.dryRun;
|
|
1322
|
-
const platforms = args && args.platforms;
|
|
1323
|
-
|
|
1324
|
-
const result = bootstrapEnvironment(targetDir, { dryRun, platforms });
|
|
1325
|
-
|
|
1326
|
-
return {
|
|
1327
|
-
jsonrpc: '2.0',
|
|
1328
|
-
id,
|
|
1329
|
-
result: {
|
|
1330
|
-
content: [
|
|
1331
|
-
{
|
|
1332
|
-
type: 'text',
|
|
1333
|
-
text: JSON.stringify(result, null, 2)
|
|
1334
|
-
}
|
|
1335
|
-
]
|
|
1336
|
-
}
|
|
1337
|
-
};
|
|
1338
|
-
}
|
|
1339
|
-
|
|
1340
|
-
if (name === 'agent_generate_magic_prompt') {
|
|
1341
|
-
const { MagicPromptGenerator } = require('./magic_prompt_generator.js');
|
|
1342
|
-
const generator = new MagicPromptGenerator(ROOT_DIR);
|
|
1343
|
-
const targetDir = (args && args.targetDir) || path.join(ROOT_DIR, 'dist', 'magic_prompt');
|
|
1344
|
-
const dryRun = args && args.dryRun;
|
|
1345
|
-
|
|
1346
|
-
const result = generator.exportArtifacts(targetDir, { dryRun });
|
|
1347
|
-
|
|
1348
|
-
return {
|
|
1349
|
-
jsonrpc: '2.0',
|
|
1350
|
-
id,
|
|
1351
|
-
result: {
|
|
1352
|
-
content: [
|
|
1353
|
-
{
|
|
1354
|
-
type: 'text',
|
|
1355
|
-
text: JSON.stringify(result, null, 2)
|
|
1356
|
-
}
|
|
1357
|
-
]
|
|
1358
|
-
}
|
|
1359
|
-
};
|
|
1360
|
-
}
|
|
1361
|
-
|
|
1362
|
-
if (name === 'agent_inspector_info') {
|
|
1363
|
-
const { getTelemetry } = require('./web_inspector.js');
|
|
1364
|
-
const port = (args && args.port) || 4040;
|
|
1365
|
-
|
|
1366
|
-
return {
|
|
1367
|
-
jsonrpc: '2.0',
|
|
1368
|
-
id,
|
|
1369
|
-
result: {
|
|
1370
|
-
content: [
|
|
1371
|
-
{
|
|
1372
|
-
type: 'text',
|
|
1373
|
-
text: JSON.stringify({
|
|
1374
|
-
status: 'READY',
|
|
1375
|
-
dashboardUrl: `http://localhost:${port}`,
|
|
1376
|
-
endpoints: {
|
|
1377
|
-
dashboard: '/',
|
|
1378
|
-
status: '/api/status',
|
|
1379
|
-
mcpProxy: '/api/mcp',
|
|
1380
|
-
evalHarness: '/api/eval',
|
|
1381
|
-
magicPrompt: '/api/magic-prompt'
|
|
1382
|
-
},
|
|
1383
|
-
telemetry: getTelemetry()
|
|
1384
|
-
}, null, 2)
|
|
1385
|
-
}
|
|
1386
|
-
]
|
|
1387
|
-
}
|
|
1388
|
-
};
|
|
1389
|
-
}
|
|
1390
|
-
|
|
1391
|
-
if (name === 'agent_check_credentials') {
|
|
1392
|
-
const { runCredentialHealthcheck } = require('./credentials_guard.js');
|
|
1393
|
-
const targetDir = (args && args.targetDir) || ROOT_DIR;
|
|
1394
|
-
const check = runCredentialHealthcheck(targetDir);
|
|
1395
|
-
|
|
1396
|
-
return {
|
|
1397
|
-
jsonrpc: '2.0',
|
|
1398
|
-
id,
|
|
1399
|
-
result: {
|
|
1400
|
-
content: [
|
|
1401
|
-
{
|
|
1402
|
-
type: 'text',
|
|
1403
|
-
text: JSON.stringify(check, null, 2)
|
|
1404
|
-
}
|
|
1405
|
-
]
|
|
1406
|
-
}
|
|
1407
|
-
};
|
|
1408
|
-
}
|
|
1409
|
-
|
|
1410
|
-
if (name === 'agent_configure_credentials') {
|
|
1411
|
-
const { configureCredentials } = require('./credentials_guard.js');
|
|
1412
|
-
const targetDir = (args && args.targetDir) || ROOT_DIR;
|
|
1413
|
-
const { domain, email, token, jiraKey, confluenceSpace } = args || {};
|
|
1414
|
-
|
|
1415
|
-
if (!domain || !email || !token) {
|
|
1416
|
-
return {
|
|
1417
|
-
jsonrpc: '2.0',
|
|
1418
|
-
id,
|
|
1419
|
-
error: {
|
|
1420
|
-
code: -32602,
|
|
1421
|
-
message: 'Parâmetros obrigatórios ausentes: domain, email e token são requeridos.'
|
|
1422
|
-
}
|
|
1423
|
-
};
|
|
1424
|
-
}
|
|
1425
|
-
|
|
1426
|
-
const result = configureCredentials(targetDir, { domain, email, token, jiraKey, confluenceSpace });
|
|
1427
|
-
|
|
1428
|
-
return {
|
|
1429
|
-
jsonrpc: '2.0',
|
|
1430
|
-
id,
|
|
1431
|
-
result: {
|
|
1432
|
-
content: [
|
|
1433
|
-
{
|
|
1434
|
-
type: 'text',
|
|
1435
|
-
text: JSON.stringify(result, null, 2)
|
|
1436
|
-
}
|
|
1437
|
-
]
|
|
1438
|
-
}
|
|
1439
|
-
};
|
|
1440
|
-
}
|
|
1441
|
-
|
|
1442
|
-
if (name === 'agent_standardize_kanban') {
|
|
1443
|
-
const {
|
|
1444
|
-
CANONICAL_COLUMNS_LIST,
|
|
1445
|
-
standardizeBoardColumns,
|
|
1446
|
-
buildCanonicalJql
|
|
1447
|
-
} = require('./jira_manager.js');
|
|
1448
|
-
|
|
1449
|
-
const projectKey = (args && args.projectKey) || 'AGDEV';
|
|
1450
|
-
const boardConfig = args && args.boardConfig;
|
|
1451
|
-
|
|
1452
|
-
const jqls = {
|
|
1453
|
-
todo: buildCanonicalJql(projectKey, 'A fazer'),
|
|
1454
|
-
inProgress: buildCanonicalJql(projectKey, 'Em andamento'),
|
|
1455
|
-
done: buildCanonicalJql(projectKey, 'Concluído')
|
|
1456
|
-
};
|
|
1457
|
-
|
|
1458
|
-
const boardStandardization = boardConfig ? standardizeBoardColumns(boardConfig) : null;
|
|
1459
|
-
|
|
1460
|
-
return {
|
|
1461
|
-
jsonrpc: '2.0',
|
|
1462
|
-
id,
|
|
1463
|
-
result: {
|
|
1464
|
-
content: [
|
|
1465
|
-
{
|
|
1466
|
-
type: 'text',
|
|
1467
|
-
text: JSON.stringify({
|
|
1468
|
-
status: 'SUCCESS',
|
|
1469
|
-
projectKey,
|
|
1470
|
-
canonicalColumns: CANONICAL_COLUMNS_LIST,
|
|
1471
|
-
standardQueries: jqls,
|
|
1472
|
-
boardStandardization
|
|
1473
|
-
}, null, 2)
|
|
1474
|
-
}
|
|
1475
|
-
]
|
|
1476
|
-
}
|
|
1477
|
-
};
|
|
1478
|
-
}
|
|
1479
|
-
|
|
1480
|
-
if (name === 'agent_validate_rule15') {
|
|
1481
|
-
const { validateRule15 } = require('./credentials_guard.js');
|
|
1482
|
-
try {
|
|
1483
|
-
const res = validateRule15({
|
|
1484
|
-
failFast: Boolean(args && args.failFast),
|
|
1485
|
-
requireGitHub: args ? args.requireGitHub !== false : true,
|
|
1486
|
-
requireAtlassian: args ? args.requireAtlassian !== false : true
|
|
1487
|
-
});
|
|
1488
|
-
return {
|
|
1489
|
-
jsonrpc: '2.0',
|
|
1490
|
-
id,
|
|
1491
|
-
result: {
|
|
1492
|
-
content: [
|
|
1493
|
-
{
|
|
1494
|
-
type: 'text',
|
|
1495
|
-
text: JSON.stringify({
|
|
1496
|
-
status: res.valid ? 'SUCCESS' : 'BLOCKED',
|
|
1497
|
-
rule: 'Regra 15 - Imutabilidade de Requisitos & Validação Compulsória de Segredos',
|
|
1498
|
-
valid: res.valid,
|
|
1499
|
-
missing: res.missing,
|
|
1500
|
-
remediation: res.remediation,
|
|
1501
|
-
atlassianConfigured: res.atlassian.isConfigured,
|
|
1502
|
-
githubAuthenticated: res.github.isAuthenticated
|
|
1503
|
-
}, null, 2)
|
|
1504
|
-
}
|
|
1505
|
-
]
|
|
1506
|
-
}
|
|
1507
|
-
};
|
|
1508
|
-
} catch (err) {
|
|
1509
|
-
return {
|
|
1510
|
-
jsonrpc: '2.0',
|
|
1511
|
-
id,
|
|
1512
|
-
error: {
|
|
1513
|
-
code: -32015,
|
|
1514
|
-
message: err.message,
|
|
1515
|
-
data: {
|
|
1516
|
-
missing: err.missingRequirements || [],
|
|
1517
|
-
remediation: err.remediationSteps || []
|
|
1518
|
-
}
|
|
1519
|
-
}
|
|
1520
|
-
};
|
|
1521
|
-
}
|
|
1522
|
-
}
|
|
1523
|
-
|
|
1524
|
-
if (name === 'agent_full_dev_pipeline') {
|
|
1525
|
-
const { processFullDevPipeline } = require('./jira_manager.js');
|
|
1526
|
-
const tasks = (args && args.tasks) || [];
|
|
1527
|
-
const projectContext = (args && args.projectContext) || {};
|
|
1528
|
-
|
|
1529
|
-
const pipelineResult = processFullDevPipeline(tasks, projectContext);
|
|
1530
|
-
|
|
1531
|
-
return {
|
|
1532
|
-
jsonrpc: '2.0',
|
|
1533
|
-
id,
|
|
1534
|
-
result: {
|
|
1535
|
-
content: [
|
|
1536
|
-
{
|
|
1537
|
-
type: 'text',
|
|
1538
|
-
text: JSON.stringify(pipelineResult, null, 2)
|
|
1539
|
-
}
|
|
1540
|
-
]
|
|
1541
|
-
}
|
|
1542
|
-
};
|
|
1543
|
-
}
|
|
1544
|
-
if (name === 'agent_audit_a11y') {
|
|
1545
|
-
const { A11yAuditor } = safeRequire('./a11y_auditor.js');
|
|
1546
|
-
const auditor = new A11yAuditor();
|
|
1547
|
-
const code = (args && args.code) || '';
|
|
1548
|
-
const filename = (args && args.filename) || 'component.tsx';
|
|
1549
|
-
const auditResult = auditor.auditCode(code, filename);
|
|
1550
|
-
const report = auditor.formatReport(auditResult);
|
|
1551
|
-
|
|
1552
|
-
return {
|
|
1553
|
-
jsonrpc: '2.0',
|
|
1554
|
-
id,
|
|
1555
|
-
result: {
|
|
1556
|
-
content: [
|
|
1557
|
-
{
|
|
1558
|
-
type: 'text',
|
|
1559
|
-
text: JSON.stringify({ ...auditResult, formattedReport: report }, null, 2)
|
|
1560
|
-
}
|
|
1561
|
-
]
|
|
1562
|
-
}
|
|
1563
|
-
};
|
|
1564
|
-
}
|
|
1565
|
-
|
|
1566
|
-
if (name === 'agent_audit_token_finops') {
|
|
1567
|
-
const { TokenFinopsGuard } = safeRequire('./token_finops_guard.js');
|
|
1568
|
-
const guard = new TokenFinopsGuard();
|
|
1569
|
-
const promptText = (args && args.promptText) || '';
|
|
1570
|
-
const model = (args && args.model) || 'claude-3-5-sonnet';
|
|
1571
|
-
const auditResult = guard.auditPrompt(promptText, { model });
|
|
1572
|
-
|
|
1573
|
-
if (args && args.taskDescription) {
|
|
1574
|
-
auditResult.tierRecommendation = guard.classifyTaskAndRecommendTier(args.taskDescription, promptText);
|
|
1575
|
-
}
|
|
1576
|
-
if (args && args.diffText) {
|
|
1577
|
-
auditResult.diffPruning = guard.pruneDiff(args.diffText);
|
|
1578
|
-
}
|
|
1579
|
-
|
|
1580
|
-
const report = guard.formatFinopsReport(auditResult);
|
|
1581
|
-
|
|
1582
|
-
return {
|
|
1583
|
-
jsonrpc: '2.0',
|
|
1584
|
-
id,
|
|
1585
|
-
result: {
|
|
1586
|
-
content: [
|
|
1587
|
-
{
|
|
1588
|
-
type: 'text',
|
|
1589
|
-
text: JSON.stringify({ ...auditResult, formattedReport: report }, null, 2)
|
|
1590
|
-
}
|
|
1591
|
-
]
|
|
1592
|
-
}
|
|
1593
|
-
};
|
|
1594
|
-
}
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
if (name === 'agent_lint_git_hygiene') {
|
|
1598
|
-
const { lintCommitMessage, lintBranchName, auditGitState } = safeRequire('./git_hygiene_linter.js');
|
|
1599
|
-
let res = {};
|
|
1600
|
-
if (args && args.commitMessage) {
|
|
1601
|
-
res.commitAudit = lintCommitMessage(args.commitMessage);
|
|
1602
|
-
}
|
|
1603
|
-
if (args && args.branchName) {
|
|
1604
|
-
res.branchAudit = lintBranchName(args.branchName);
|
|
1605
|
-
}
|
|
1606
|
-
if (args && args.auditState) {
|
|
1607
|
-
res.gitState = auditGitState();
|
|
1608
|
-
}
|
|
1609
|
-
if (!args || (!args.commitMessage && !args.branchName && !args.auditState)) {
|
|
1610
|
-
res.gitState = auditGitState();
|
|
1611
|
-
}
|
|
1612
|
-
return {
|
|
1613
|
-
jsonrpc: '2.0',
|
|
1614
|
-
id,
|
|
1615
|
-
result: {
|
|
1616
|
-
content: [{ type: 'text', text: JSON.stringify(res, null, 2) }]
|
|
1617
|
-
}
|
|
1618
|
-
};
|
|
1619
|
-
}
|
|
1620
|
-
|
|
1621
|
-
if (name === 'agent_audit_dependencies_sca') {
|
|
1622
|
-
const { auditDependenciesSCA } = safeRequire('./sca_dependency_auditor.js');
|
|
1623
|
-
const input = (args && args.packageJson) || path.join(process.cwd(), 'package.json');
|
|
1624
|
-
const res = auditDependenciesSCA(input);
|
|
1625
|
-
return {
|
|
1626
|
-
jsonrpc: '2.0',
|
|
1627
|
-
id,
|
|
1628
|
-
result: {
|
|
1629
|
-
content: [{ type: 'text', text: JSON.stringify(res, null, 2) }]
|
|
1630
|
-
}
|
|
1631
|
-
};
|
|
1632
|
-
}
|
|
1633
|
-
|
|
1634
|
-
if (name === 'agent_smart_onboarding') {
|
|
1635
|
-
const { detectProjectMode, inspectProjectContext } = safeRequire('./smart_onboarding.js');
|
|
1636
|
-
const targetDir = (args && args.targetDir) || process.cwd();
|
|
1637
|
-
const mode = detectProjectMode(targetDir);
|
|
1638
|
-
const context = inspectProjectContext(targetDir);
|
|
1639
|
-
return {
|
|
1640
|
-
jsonrpc: '2.0',
|
|
1641
|
-
id,
|
|
1642
|
-
result: {
|
|
1643
|
-
content: [{ type: 'text', text: JSON.stringify({ mode, context }, null, 2) }]
|
|
1644
|
-
}
|
|
1645
|
-
};
|
|
1646
|
-
}
|
|
1647
|
-
|
|
1648
|
-
if (name === 'agent_scaffold_feature') {
|
|
1649
|
-
const { scaffoldFeatureFast } = safeRequire('./fast_feature_scaffold.js');
|
|
1650
|
-
const result = scaffoldFeatureFast(args || {}, {
|
|
1651
|
-
rootDir: ROOT_DIR,
|
|
1652
|
-
writeToDisk: Boolean(args && args.writeToDisk)
|
|
1653
|
-
});
|
|
1654
|
-
return {
|
|
1655
|
-
jsonrpc: '2.0',
|
|
1656
|
-
id,
|
|
1657
|
-
result: {
|
|
1658
|
-
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }]
|
|
1659
|
-
}
|
|
1660
|
-
};
|
|
1661
|
-
}
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
if (name === 'agent_extract_code_skeleton') {
|
|
1672
|
-
const { extractCodeSkeleton } = safeRequire('./ast_skeletonizer.js');
|
|
1673
|
-
const code = (args && args.code) || '';
|
|
1674
|
-
const language = (args && args.language) || 'javascript';
|
|
1675
|
-
const result = extractCodeSkeleton(code, language);
|
|
1676
|
-
return {
|
|
1677
|
-
jsonrpc: '2.0',
|
|
1678
|
-
id,
|
|
1679
|
-
result: {
|
|
1680
|
-
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }]
|
|
1681
|
-
}
|
|
1682
|
-
};
|
|
1683
|
-
}
|
|
1684
|
-
|
|
1685
|
-
if (name === 'agent_finops_ledger') {
|
|
1686
|
-
const { FinopsLedger } = safeRequire('./finops_ledger.js');
|
|
1687
|
-
const ledger = new FinopsLedger({ rootDir: ROOT_DIR });
|
|
1688
|
-
const action = (args && args.action) || 'summary';
|
|
1689
|
-
let result;
|
|
1690
|
-
|
|
1691
|
-
if (action === 'record') {
|
|
1692
|
-
result = ledger.recordSpend(args.ticketKey || 'UNASSIGNED', {
|
|
1693
|
-
tokensInput: args.tokensInput || 0,
|
|
1694
|
-
tokensOutput: args.tokensOutput || 0,
|
|
1695
|
-
model: args.model || 'claude-3-5-sonnet',
|
|
1696
|
-
agentRole: args.agentRole || 'orchestrator',
|
|
1697
|
-
summary: args.summary || 'Ação registrada'
|
|
1698
|
-
});
|
|
1699
|
-
} else if (action === 'ticket') {
|
|
1700
|
-
result = {
|
|
1701
|
-
metrics: ledger.getTicketMetrics(args.ticketKey || 'UNASSIGNED'),
|
|
1702
|
-
jiraSection: ledger.formatJiraSection(args.ticketKey || 'UNASSIGNED')
|
|
1703
|
-
};
|
|
1704
|
-
} else {
|
|
1705
|
-
result = ledger.getProjectSummary();
|
|
1706
|
-
}
|
|
1707
|
-
|
|
1708
|
-
return {
|
|
1709
|
-
jsonrpc: '2.0',
|
|
1710
|
-
id,
|
|
1711
|
-
result: {
|
|
1712
|
-
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }]
|
|
1713
|
-
}
|
|
1714
|
-
};
|
|
1715
|
-
}
|
|
1716
|
-
|
|
1717
|
-
if (name === 'agent_verify_triad_gate') {
|
|
1718
|
-
const { verifyTriadGateSync } = safeRequire('./smart_onboarding.js');
|
|
1719
|
-
const targetDir = (args && args.targetDir) || process.cwd();
|
|
1720
|
-
let gateResult;
|
|
1721
|
-
try {
|
|
1722
|
-
gateResult = verifyTriadGateSync(targetDir, args || {});
|
|
1723
|
-
} catch (err) {
|
|
1724
|
-
gateResult = {
|
|
1725
|
-
canDevelop: false,
|
|
1726
|
-
verdict: 'BLOQUEADO_REGRA_16',
|
|
1727
|
-
gateMessage: `⛔ Erro ao verificar Gate da Tríade: ${err.message}`,
|
|
1728
|
-
blockers: [err.message]
|
|
1729
|
-
};
|
|
1730
|
-
}
|
|
1731
|
-
return {
|
|
1732
|
-
jsonrpc: '2.0',
|
|
1733
|
-
id,
|
|
1734
|
-
result: {
|
|
1735
|
-
content: [{ type: 'text', text: JSON.stringify(gateResult, null, 2) }]
|
|
1736
|
-
}
|
|
1737
|
-
};
|
|
1738
|
-
}
|
|
1739
|
-
|
|
1740
|
-
if (name === 'agent_set_mcp_profile') {
|
|
1741
|
-
const target = (args && args.profile) || 'all';
|
|
1742
|
-
const res = setMcpProfile(target);
|
|
1743
|
-
return {
|
|
1744
|
-
jsonrpc: '2.0',
|
|
1745
|
-
id,
|
|
1746
|
-
result: {
|
|
1747
|
-
content: [{ type: 'text', text: JSON.stringify(res, null, 2) }]
|
|
1748
|
-
}
|
|
1749
|
-
};
|
|
1750
|
-
}
|
|
1751
|
-
|
|
1752
|
-
if (name === 'agent_validate_api_contract') {
|
|
1753
|
-
const { validateOpenApiContract } = safeRequire('./contract_test_validator.js');
|
|
1754
|
-
const spec = (args && args.spec) || {};
|
|
1755
|
-
const implementedRoutes = (args && args.implementedRoutes) || [];
|
|
1756
|
-
const res = validateOpenApiContract(spec, implementedRoutes);
|
|
1757
|
-
return {
|
|
1758
|
-
jsonrpc: '2.0',
|
|
1759
|
-
id,
|
|
1760
|
-
result: {
|
|
1761
|
-
content: [{ type: 'text', text: JSON.stringify(res, null, 2) }]
|
|
1762
|
-
}
|
|
1763
|
-
};
|
|
1764
|
-
}
|
|
1765
|
-
|
|
1766
|
-
if (name === 'agent_mine_domain_ideas') {
|
|
1767
|
-
const { mineDomainIdeas } = safeRequire('./domain_idea_miner.js');
|
|
1768
|
-
const targetDir = (args && args.targetDir) ? path.resolve(args.targetDir) : ROOT_DIR;
|
|
1769
|
-
const autoApply = args && args.autoApply === true;
|
|
1770
|
-
const dryRun = args && args.dryRun === true;
|
|
1771
|
-
|
|
1772
|
-
const report = mineDomainIdeas(targetDir, {
|
|
1773
|
-
autoApply,
|
|
1774
|
-
dryRun,
|
|
1775
|
-
ideasFilePath: path.join(ROOT_DIR, 'docs', 'IDEAS.md')
|
|
1776
|
-
});
|
|
1777
|
-
|
|
1778
|
-
return {
|
|
1779
|
-
jsonrpc: '2.0',
|
|
1780
|
-
id,
|
|
1781
|
-
result: {
|
|
1782
|
-
content: [
|
|
1783
|
-
{
|
|
1784
|
-
type: 'text',
|
|
1785
|
-
text: JSON.stringify({
|
|
1786
|
-
status: 'SUCCESS',
|
|
1787
|
-
targetDir,
|
|
1788
|
-
scannedFilesCount: report.scannedFilesCount,
|
|
1789
|
-
opportunitiesFound: report.opportunitiesFound,
|
|
1790
|
-
opportunities: report.opportunities,
|
|
1791
|
-
syncResult: report.syncResult
|
|
1792
|
-
}, null, 2)
|
|
1793
|
-
}
|
|
1794
|
-
]
|
|
1795
|
-
}
|
|
1796
|
-
};
|
|
1797
|
-
}
|
|
1798
|
-
|
|
1799
|
-
return {
|
|
1800
|
-
jsonrpc: '2.0',
|
|
1801
|
-
id,
|
|
1802
|
-
error: {
|
|
1803
|
-
code: -32601,
|
|
1804
|
-
message: `Método de tool desconhecido: ${name}`
|
|
1805
|
-
}
|
|
1806
|
-
};
|
|
1807
|
-
}
|
|
1808
|
-
|
|
1809
|
-
function processMessage(message) {
|
|
1810
|
-
const { id, method, params } = message;
|
|
1811
|
-
|
|
1812
|
-
if (method === 'initialize') {
|
|
1813
|
-
return handleInitialize(id);
|
|
1814
|
-
}
|
|
1815
|
-
if (method === 'tools/list') {
|
|
1816
|
-
return handleToolsList(id);
|
|
1817
|
-
}
|
|
1818
|
-
if (method === 'tools/call') {
|
|
1819
|
-
return handleToolCall(id, params);
|
|
1820
|
-
}
|
|
1821
|
-
if (method === 'resources/list') {
|
|
1822
|
-
return handleResourcesList(id);
|
|
1823
|
-
}
|
|
1824
|
-
if (method === 'resources/read') {
|
|
1825
|
-
return handleResourceRead(id, params);
|
|
1826
|
-
}
|
|
1827
|
-
if (method === 'notifications/initialized') {
|
|
1828
|
-
return null; // MCP notification: no response
|
|
1829
|
-
}
|
|
1830
|
-
|
|
1831
|
-
return {
|
|
1832
|
-
jsonrpc: '2.0',
|
|
1833
|
-
id,
|
|
1834
|
-
error: {
|
|
1835
|
-
code: -32601,
|
|
1836
|
-
message: `Método não suportado: ${method}`
|
|
1837
|
-
}
|
|
1838
|
-
};
|
|
1839
|
-
}
|
|
1840
|
-
|
|
1841
|
-
function startServer() {
|
|
1842
|
-
const rl = readline.createInterface({
|
|
1843
|
-
input: process.stdin,
|
|
1844
|
-
output: process.stdout,
|
|
1845
|
-
terminal: false
|
|
1846
|
-
});
|
|
1847
|
-
|
|
1848
|
-
rl.on('line', (line) => {
|
|
1849
|
-
const trimmed = line.trim();
|
|
1850
|
-
if (!trimmed) return;
|
|
1851
|
-
|
|
1852
|
-
try {
|
|
1853
|
-
const request = JSON.parse(trimmed);
|
|
1854
|
-
const response = processMessage(request);
|
|
1855
|
-
if (response) {
|
|
1856
|
-
process.stdout.write(JSON.stringify(response) + '\n');
|
|
1857
|
-
}
|
|
1858
|
-
} catch (err) {
|
|
1859
|
-
const errResponse = {
|
|
1860
|
-
jsonrpc: '2.0',
|
|
1861
|
-
id: null,
|
|
1862
|
-
error: {
|
|
1863
|
-
code: -32700,
|
|
1864
|
-
message: 'Parse error: JSON inválido.',
|
|
1865
|
-
data: String(err)
|
|
1866
|
-
}
|
|
1867
|
-
};
|
|
1868
|
-
process.stdout.write(JSON.stringify(errResponse) + '\n');
|
|
1869
|
-
}
|
|
1870
|
-
});
|
|
1871
|
-
}
|
|
1872
|
-
|
|
1873
|
-
if (require.main === module) {
|
|
1874
|
-
startServer();
|
|
1875
|
-
}
|
|
1876
|
-
|
|
1877
|
-
module.exports = {
|
|
1878
|
-
processMessage,
|
|
1879
|
-
TOOLS,
|
|
1880
|
-
RESOURCES,
|
|
1881
|
-
TOOL_PROFILES,
|
|
1882
|
-
getActiveTools,
|
|
1883
|
-
setMcpProfile
|
|
1884
|
-
};
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* scripts/mcp_server.js
|
|
4
|
+
*
|
|
5
|
+
* Servidor MCP Nativo (Model Context Protocol) — Ponto de Entrada Canônico & CLI
|
|
6
|
+
* Compatível com a especificação JSON-RPC 2.0 / MCP 2024-11-05.
|
|
7
|
+
*
|
|
8
|
+
* Atua como Fachada Canônica e Interface CLI de Alta Performance para o ecossistema
|
|
9
|
+
* agent-master-devsecops, delegando a execução ao dispatcher modular em ./mcp/server.js.
|
|
10
|
+
*
|
|
11
|
+
* Suporta inicialização interativa stdio, seleção dinâmica de perfis (--profile),
|
|
12
|
+
* relatórios executivos (--report), auditoria de conformidade OASIS SARIF v2.1.0 (--sarif),
|
|
13
|
+
* consulta de versões (--version) e graceful shutdown.
|
|
14
|
+
*
|
|
15
|
+
* Versão: 5.1.0 Enterprise
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
'use strict';
|
|
19
|
+
|
|
20
|
+
const { version: PKG_VERSION } = require('../package.json');
|
|
21
|
+
const {
|
|
22
|
+
McpServer,
|
|
23
|
+
defaultServerInstance,
|
|
24
|
+
processMessage,
|
|
25
|
+
processMessageAsync,
|
|
26
|
+
startServer,
|
|
27
|
+
stopServer,
|
|
28
|
+
handleInitialize,
|
|
29
|
+
handleToolsList,
|
|
30
|
+
handleResourcesList,
|
|
31
|
+
handleResourceRead,
|
|
32
|
+
TOOLS,
|
|
33
|
+
RESOURCES,
|
|
34
|
+
TOOL_PROFILES,
|
|
35
|
+
getActiveTools,
|
|
36
|
+
setMcpProfile,
|
|
37
|
+
getActiveProfile,
|
|
38
|
+
auditToSarif,
|
|
39
|
+
formatReport,
|
|
40
|
+
PROTOCOL_VERSION,
|
|
41
|
+
JSONRPC_VERSION
|
|
42
|
+
} = require('./mcp/server.js');
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Analisador funcional puro de argumentos de linha de comando.
|
|
46
|
+
* @param {string[]} argv
|
|
47
|
+
* @returns {Record<string, any>}
|
|
48
|
+
*/
|
|
49
|
+
function parseArgs(argv = []) {
|
|
50
|
+
const args = Array.isArray(argv) ? argv : [];
|
|
51
|
+
const options = {
|
|
52
|
+
help: false,
|
|
53
|
+
version: false,
|
|
54
|
+
sarif: false,
|
|
55
|
+
report: false,
|
|
56
|
+
listTools: false,
|
|
57
|
+
listProfiles: false,
|
|
58
|
+
profile: null
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
for (let i = 0; i < args.length; i++) {
|
|
62
|
+
const arg = String(args[i]);
|
|
63
|
+
if (arg === '--help' || arg === '-h') {
|
|
64
|
+
options.help = true;
|
|
65
|
+
} else if (arg === '--version' || arg === '-v') {
|
|
66
|
+
options.version = true;
|
|
67
|
+
} else if (arg === '--sarif') {
|
|
68
|
+
options.sarif = true;
|
|
69
|
+
} else if (arg === '--report') {
|
|
70
|
+
options.report = true;
|
|
71
|
+
} else if (arg === '--list-tools') {
|
|
72
|
+
options.listTools = true;
|
|
73
|
+
} else if (arg === '--list-profiles') {
|
|
74
|
+
options.listProfiles = true;
|
|
75
|
+
} else if (arg === '--profile' || arg === '-p') {
|
|
76
|
+
if (i + 1 < args.length && !args[i + 1].startsWith('-')) {
|
|
77
|
+
options.profile = String(args[i + 1]);
|
|
78
|
+
i++;
|
|
79
|
+
}
|
|
80
|
+
} else if (arg.startsWith('--profile=')) {
|
|
81
|
+
options.profile = arg.slice('--profile='.length);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return Object.freeze(options);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Formata o texto de ajuda do CLI.
|
|
90
|
+
* @returns {string}
|
|
91
|
+
*/
|
|
92
|
+
function formatHelpText() {
|
|
93
|
+
const profiles = Object.keys(TOOL_PROFILES).join(', ');
|
|
94
|
+
return [
|
|
95
|
+
`Servidor MCP Nativo — Agent Master DevSecOps v${PKG_VERSION}`,
|
|
96
|
+
`Protocolo MCP: ${PROTOCOL_VERSION} | JSON-RPC: ${JSONRPC_VERSION}`,
|
|
97
|
+
'',
|
|
98
|
+
'Uso:',
|
|
99
|
+
' agent-master-mcp [opções]',
|
|
100
|
+
' node scripts/mcp_server.js [opções]',
|
|
101
|
+
'',
|
|
102
|
+
'Opções:',
|
|
103
|
+
' -p, --profile <nome> Inicia o servidor com o perfil especificado',
|
|
104
|
+
` Perfis disponíveis: ${profiles}`,
|
|
105
|
+
' --sarif Executa auditoria e emite relatório OASIS SARIF v2.1.0',
|
|
106
|
+
' --report Emite relatório executivo em Markdown e finaliza',
|
|
107
|
+
' --list-tools Lista ferramentas ativas do perfil atual e finaliza',
|
|
108
|
+
' --list-profiles Lista todos os perfis disponíveis e finaliza',
|
|
109
|
+
' -v, --version Exibe a versão do servidor e do protocolo MCP',
|
|
110
|
+
' -h, --help Exibe esta ajuda operacional',
|
|
111
|
+
'',
|
|
112
|
+
'Exemplo de Configuração para IDEs (Claude Desktop / Cursor):',
|
|
113
|
+
' {',
|
|
114
|
+
' "mcpServers": {',
|
|
115
|
+
' "agent-master": {',
|
|
116
|
+
' "command": "node",',
|
|
117
|
+
' "args": ["scripts/mcp_server.js", "--profile", "consolidated"]',
|
|
118
|
+
' }',
|
|
119
|
+
' }',
|
|
120
|
+
' }'
|
|
121
|
+
].join('\n');
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Executor do ponto de entrada CLI com suporte a injeção de I/O.
|
|
126
|
+
* @param {string[]} argv
|
|
127
|
+
* @param {object} io
|
|
128
|
+
* @returns {number} Código de saída (0 para sucesso, > 0 para erro)
|
|
129
|
+
*/
|
|
130
|
+
function runCli(argv = process.argv.slice(2), io = {}) {
|
|
131
|
+
const stdout = io.stdout || process.stdout;
|
|
132
|
+
const stderr = io.stderr || process.stderr;
|
|
133
|
+
|
|
134
|
+
const options = parseArgs(argv);
|
|
135
|
+
|
|
136
|
+
if (options.help) {
|
|
137
|
+
stdout.write(formatHelpText() + '\n');
|
|
138
|
+
return 0;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (options.version) {
|
|
142
|
+
stdout.write(`agent-master-devsecops v${PKG_VERSION} (MCP Protocol ${PROTOCOL_VERSION})\n`);
|
|
143
|
+
return 0;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (options.sarif) {
|
|
147
|
+
const sarif = auditToSarif();
|
|
148
|
+
stdout.write(JSON.stringify(sarif, null, 2) + '\n');
|
|
149
|
+
return 0;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (options.report) {
|
|
153
|
+
stdout.write(formatReport() + '\n');
|
|
154
|
+
return 0;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (options.listProfiles) {
|
|
158
|
+
const list = Object.entries(TOOL_PROFILES)
|
|
159
|
+
.map(([name, tools]) => ` - ${name.padEnd(16)}: ${tools.length} ferramentas`)
|
|
160
|
+
.join('\n');
|
|
161
|
+
stdout.write(`Perfis de Ferramentas Disponíveis:\n${list}\n`);
|
|
162
|
+
return 0;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (options.profile) {
|
|
166
|
+
const result = setMcpProfile(options.profile);
|
|
167
|
+
if (!result || !result.success) {
|
|
168
|
+
stderr.write(`[AVISO] Perfil desconhecido: "${options.profile}". Mantido perfil "${getActiveProfile()}".\n`);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (options.listTools) {
|
|
173
|
+
const active = getActiveTools();
|
|
174
|
+
const list = active.map(t => ` - ${t.name.padEnd(30)}: ${t.description.slice(0, 60)}...`).join('\n');
|
|
175
|
+
stdout.write(`Ferramentas Ativas (Perfil: ${getActiveProfile()}, Total: ${active.length}):\n${list}\n`);
|
|
176
|
+
return 0;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Em modo teste, não inicia listener bloqueante
|
|
180
|
+
if (io.testMode) {
|
|
181
|
+
return 0;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Configura graceful shutdown no processo real
|
|
185
|
+
const cleanup = () => {
|
|
186
|
+
stopServer();
|
|
187
|
+
process.exit(0);
|
|
188
|
+
};
|
|
189
|
+
process.once('SIGINT', cleanup);
|
|
190
|
+
process.once('SIGTERM', cleanup);
|
|
191
|
+
|
|
192
|
+
startServer();
|
|
193
|
+
return 0;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if (require.main === module) {
|
|
197
|
+
runCli();
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
module.exports = {
|
|
201
|
+
// Fachada Canônica da Classe e Instância
|
|
202
|
+
McpServer,
|
|
203
|
+
defaultServerInstance,
|
|
204
|
+
|
|
205
|
+
// Funções de Despacho e Ciclo de Vida
|
|
206
|
+
processMessage,
|
|
207
|
+
processMessageAsync,
|
|
208
|
+
startServer,
|
|
209
|
+
stopServer,
|
|
210
|
+
handleInitialize,
|
|
211
|
+
handleToolsList,
|
|
212
|
+
handleResourcesList,
|
|
213
|
+
handleResourceRead,
|
|
214
|
+
|
|
215
|
+
// Catálogos e Perfis
|
|
216
|
+
TOOLS,
|
|
217
|
+
RESOURCES,
|
|
218
|
+
TOOL_PROFILES,
|
|
219
|
+
getActiveTools,
|
|
220
|
+
setMcpProfile,
|
|
221
|
+
getActiveProfile,
|
|
222
|
+
|
|
223
|
+
// Auditoria e Relatórios
|
|
224
|
+
auditToSarif,
|
|
225
|
+
formatReport,
|
|
226
|
+
|
|
227
|
+
// Utilitários CLI
|
|
228
|
+
parseArgs,
|
|
229
|
+
formatHelpText,
|
|
230
|
+
runCli,
|
|
231
|
+
|
|
232
|
+
// Constantes de Protocolo
|
|
233
|
+
PROTOCOL_VERSION,
|
|
234
|
+
JSONRPC_VERSION,
|
|
235
|
+
PKG_VERSION
|
|
236
|
+
};
|