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.
Files changed (82) hide show
  1. package/README.md +205 -371
  2. package/agents/AGENT_DEVSECOPS.md +32 -417
  3. package/agents/AGENT_INFRA.md +31 -0
  4. package/agents/AGENT_ORCHESTRATOR.md +39 -264
  5. package/agents/AGENT_QA.md +58 -186
  6. package/agents/AGENT_SCRUM.md +23 -190
  7. package/agents/AGENT_SRE.md +22 -173
  8. package/agents/AGENT_UIUX.md +26 -162
  9. package/docs/ARCHITECTURE.md +152 -148
  10. package/docs/CALCULATIONS.md +17 -17
  11. package/docs/CHANGELOG.md +112 -49
  12. package/docs/ENGINEERING_RULES.md +56 -252
  13. package/docs/IDEAS.md +17 -17
  14. package/docs/LOCAL_BACKLOG.md +20 -0
  15. package/docs/STATE.md +111 -43
  16. package/docs/playbooks/PLAYBOOK_CIRCUIT_BREAKER_LLM.md +58 -58
  17. package/docs/playbooks/PLAYBOOK_OPENTELEMETRY_TRACING.md +58 -58
  18. package/package.json +59 -47
  19. package/scripts/auditors/a11y_auditor.js +462 -0
  20. package/scripts/auditors/code_quality_auditor.js +444 -0
  21. package/scripts/auditors/contract_test_validator.js +396 -0
  22. package/scripts/auditors/eval_harness.js +213 -0
  23. package/scripts/auditors/git_hygiene_linter.js +391 -0
  24. package/scripts/auditors/pr_reviewer.js +627 -0
  25. package/scripts/auditors/sast_scanner.js +442 -0
  26. package/scripts/auditors/sca_dependency_auditor.js +673 -0
  27. package/scripts/{bootstrap_cli.js → bin/bootstrap_cli.js} +597 -468
  28. package/scripts/bin/domain_idea_miner.js +658 -0
  29. package/scripts/bin/smart_onboarding.js +905 -0
  30. package/scripts/{web_inspector.js → bin/web_inspector.js} +578 -355
  31. package/scripts/core/architecture_advisor.js +378 -0
  32. package/scripts/core/ast_skeletonizer.js +413 -0
  33. package/scripts/core/autonomous_remediation_engine.js +305 -0
  34. package/scripts/{circuit_breaker.js → core/circuit_breaker.js} +546 -330
  35. package/scripts/core/context_compressor.js +237 -0
  36. package/scripts/core/fast_feature_scaffold.js +840 -0
  37. package/scripts/core/hot_state_cache.js +238 -0
  38. package/scripts/core/knowledge_gateway.js +888 -0
  39. package/scripts/{magic_prompt_generator.js → core/magic_prompt_generator.js} +250 -205
  40. package/scripts/{multi_agent_orchestrator.js → core/multi_agent_orchestrator.js} +421 -258
  41. package/scripts/{otel_tracer.js → core/otel_tracer.js} +335 -228
  42. package/scripts/{perf_benchmark.js → core/perf_benchmark.js} +212 -153
  43. package/scripts/core/sarif_engine.js +299 -0
  44. package/scripts/{sre_remediation_engine.js → core/sre_remediation_engine.js} +236 -174
  45. package/scripts/{universal_packager.js → core/universal_packager.js} +357 -313
  46. package/scripts/integrations/atlassian_client.js +600 -0
  47. package/scripts/integrations/atlassian_sync_action.js +576 -0
  48. package/scripts/integrations/confluence_sync.js +684 -0
  49. package/scripts/integrations/credentials_guard.js +500 -0
  50. package/scripts/integrations/jira_manager.js +722 -0
  51. package/scripts/mcp/handlers/atlassian_handlers.js +300 -0
  52. package/scripts/mcp/handlers/core_handlers.js +419 -0
  53. package/scripts/mcp/handlers/qa_handlers.js +502 -0
  54. package/scripts/mcp/handlers/rules_handlers.js +379 -0
  55. package/scripts/mcp/handlers/scaffold_handlers.js +334 -0
  56. package/scripts/mcp/handlers/sre_handlers.js +443 -0
  57. package/scripts/mcp/resources_registry.js +453 -0
  58. package/scripts/mcp/server.js +408 -0
  59. package/scripts/mcp/tool_handlers.js +444 -0
  60. package/scripts/mcp/tools_registry.js +1123 -0
  61. package/scripts/mcp_server.js +236 -1884
  62. package/.cursorignore +0 -23
  63. package/agents/compact/AGENT_ORCHESTRATOR_COMPACTO.md +0 -53
  64. package/scripts/a11y_auditor.js +0 -187
  65. package/scripts/ast_skeletonizer.js +0 -220
  66. package/scripts/atlassian_client.js +0 -238
  67. package/scripts/atlassian_sync_action.js +0 -269
  68. package/scripts/code_quality_auditor.js +0 -142
  69. package/scripts/confluence_sync.js +0 -337
  70. package/scripts/context_compressor.js +0 -139
  71. package/scripts/contract_test_validator.js +0 -166
  72. package/scripts/credentials_guard.js +0 -216
  73. package/scripts/domain_idea_miner.js +0 -364
  74. package/scripts/eval_harness.js +0 -100
  75. package/scripts/fast_feature_scaffold.js +0 -338
  76. package/scripts/git_hygiene_linter.js +0 -186
  77. package/scripts/hot_state_cache.js +0 -95
  78. package/scripts/jira_manager.js +0 -408
  79. package/scripts/pr_reviewer.js +0 -373
  80. package/scripts/sast_scanner.js +0 -180
  81. package/scripts/sca_dependency_auditor.js +0 -167
  82. package/scripts/smart_onboarding.js +0 -610
@@ -1,1884 +1,236 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Servidor MCP Nativo (Model Context Protocol) — Agent Master DevSecOps
4
- * Compatível com a especificação JSON-RPC 2.0 / MCP 2024-11-05
5
- * Funciona via stdio para Claude Desktop, Cursor, Antigravity, Windsurf e qualquer harness.
6
- */
7
-
8
- const fs = require('fs');
9
- const path = require('path');
10
- const readline = require('readline');
11
-
12
- const ROOT_DIR = path.resolve(__dirname, '..');
13
-
14
- function resolveDocFile(rootDir, relPath) {
15
- return path.join(rootDir, relPath);
16
- }
17
-
18
- function safeRequire(scriptPath) {
19
- return require(scriptPath);
20
- }
21
-
22
- const TOOLS = [
23
- {
24
- name: 'agent_get_rule',
25
- description: 'Consulta uma das 14 Regras Fundamentais de Engenharia do ecossistema Agent Master.',
26
- inputSchema: {
27
- type: 'object',
28
- properties: {
29
- ruleNumber: {
30
- type: 'integer',
31
- description: 'Número da regra (1 a 14)'
32
- }
33
- },
34
- required: ['ruleNumber']
35
- }
36
- },
37
- {
38
- name: 'agent_validate_idea',
39
- description: 'Aplica a Regra 14 (Ideation Sanity Filter): avalia criticamente uma ideia contra a stack, arquitetura e restrições reais do projeto.',
40
- inputSchema: {
41
- type: 'object',
42
- properties: {
43
- ideaTitle: { type: 'string', description: 'Título da ideia' },
44
- ideaDescription: { type: 'string', description: 'Descrição da proposta' },
45
- projectStack: { type: 'string', description: 'Stack tecnológica do projeto real' },
46
- projectDomain: { type: 'string', description: 'Propósito/domínio do projeto' }
47
- },
48
- required: ['ideaTitle', 'ideaDescription', 'projectStack', 'projectDomain']
49
- }
50
- },
51
- {
52
- name: 'agent_audit_code',
53
- description: 'Aciona o Revisor Crítico Adversário (AGENT_QA.md) para analisar um diff de código contra vulnerabilidades OWASP, ReDoS e integridade de testes.',
54
- inputSchema: {
55
- type: 'object',
56
- properties: {
57
- codeDiff: { type: 'string', description: 'Diff ou código a ser auditado friamente' },
58
- context: { type: 'string', description: 'Contexto da funcionalidade ou card' }
59
- },
60
- required: ['codeDiff']
61
- }
62
- },
63
- {
64
- name: 'agent_full_dev_status',
65
- description: 'Consulta o status atual do Modo Full Developer e a próxima ideia priorizada do backlog.',
66
- inputSchema: {
67
- type: 'object',
68
- properties: {}
69
- }
70
- },
71
- {
72
- name: 'agent_eval_harness',
73
- description: 'Executa avaliação empírica de conformidade da resposta de uma LLM contra as 14 Regras de Engenharia.',
74
- inputSchema: {
75
- type: 'object',
76
- properties: {
77
- modelName: { type: 'string', description: 'Nome do modelo avaliado (ex: Claude 3.5, GPT-4o, Gemini Pro, DeepSeek-R1)' },
78
- promptSent: { type: 'string', description: 'Prompt de instrução enviado à LLM' },
79
- responseReceived: { type: 'string', description: 'Resposta bruta recebida da LLM' }
80
- },
81
- required: ['modelName', 'responseReceived']
82
- }
83
- },
84
- {
85
- name: 'agent_generate_ide_plugins',
86
- description: 'Gera arquivos de configuração e manifestos nativos para IDEs (.vscode e .idea) integrando o servidor MCP e atalhos de prompts.',
87
- inputSchema: {
88
- type: 'object',
89
- properties: {
90
- target: { type: 'string', enum: ['all', 'vscode', 'jetbrains'], description: 'IDE alvo da geração' },
91
- targetDir: { type: 'string', description: 'Diretório raiz do projeto' }
92
- }
93
- }
94
- },
95
- {
96
- name: 'agent_review_pr',
97
- description: 'Executa a auditoria autônoma do Revisor Independente (AGENT_QA.md) contra um diff de código ou número de PR, emitindo veredito canônico e testes de quebra.',
98
- inputSchema: {
99
- type: 'object',
100
- properties: {
101
- diff: { type: 'string', description: 'Diff de código a ser auditado' },
102
- files: { type: 'array', items: { type: 'string' }, description: 'Lista de caminhos de arquivos modificados' }
103
- },
104
- required: ['diff']
105
- }
106
- },
107
- {
108
- name: 'agent_compress_context',
109
- description: 'Destila as instruções e regras do Agent Master em uma versão compacta de alta densidade semântica para modelos locais (Ollama 8B/14B) sob orçamento de 1.500 tokens.',
110
- inputSchema: {
111
- type: 'object',
112
- properties: {
113
- text: { type: 'string', description: 'Texto opcional customizado a ser compactado' },
114
- maxTokens: { type: 'number', description: 'Orçamento máximo de tokens (padrão: 1500)' }
115
- }
116
- }
117
- },
118
- {
119
- name: 'agent_sync_atlassian',
120
- description: 'Registra um Remote Link de commit, branch ou Pull Request do GitHub diretamente em um card do Jira (ex: AGDEV-23).',
121
- inputSchema: {
122
- type: 'object',
123
- properties: {
124
- issueKey: { type: 'string', description: 'Chave do ticket Jira (ex: AGDEV-23, PROJ-53)' },
125
- url: { type: 'string', description: 'URL no GitHub (commit, branch ou PR)' },
126
- title: { type: 'string', description: 'Título descritivo do link' },
127
- type: { type: 'string', enum: ['commit', 'branch', 'pr'], description: 'Tipo do vínculo remoto' }
128
- },
129
- required: ['issueKey', 'url', 'title']
130
- }
131
- },
132
- {
133
- name: 'agent_otel_trace',
134
- description: 'Executa instrumentação de tracing distribuído compatível com OpenTelemetry e W3C TraceContext, gerando flamegraph ASCII e análise de gargalos.',
135
- inputSchema: {
136
- type: 'object',
137
- properties: {
138
- serviceName: { type: 'string', description: 'Nome do serviço instrumentado' },
139
- spans: {
140
- type: 'array',
141
- items: {
142
- type: 'object',
143
- properties: {
144
- name: { type: 'string' },
145
- durationMs: { type: 'number' },
146
- attributes: { type: 'object' }
147
- },
148
- required: ['name', 'durationMs']
149
- },
150
- description: 'Lista de spans a serem traçados'
151
- },
152
- thresholdMs: { type: 'number', description: 'Limiar em milissegundos para alertar gargalos de latência' }
153
- }
154
- }
155
- },
156
- {
157
- name: 'agent_perf_benchmark',
158
- description: 'Executa micro-benchmark de CPU/Throughput e memória Heap, comparando contra o baseline para detecção de regressões de performance (> 10%).',
159
- inputSchema: {
160
- type: 'object',
161
- properties: {
162
- iterations: { type: 'number', description: 'Número de repetições do benchmark (padrão: 100)' },
163
- maxDegradationPct: { type: 'number', description: 'Porcentagem máxima tolerada de degradação (padrão: 10)' }
164
- }
165
- }
166
- },
167
- {
168
- name: 'agent_circuit_breaker',
169
- description: 'Gerencia o Circuit Breaker inteligente e comutação automática de provedores de IA (Anthropic, OpenAI, Groq, Ollama) com auto-cura e mitigação de HTTP 429/5xx.',
170
- inputSchema: {
171
- type: 'object',
172
- properties: {
173
- action: { type: 'string', enum: ['status', 'simulate_failover', 'reset'], description: 'Ação a ser executada' },
174
- failureThreshold: { type: 'number', description: 'Limiar de falhas para rompimento do circuito (padrão: 3)' }
175
- }
176
- }
177
- },
178
- {
179
- name: 'agent_orchestrate_event',
180
- description: 'Despacha um evento no barramento multi-agente determinístico (EVENT_CODE_COMPLETE, EVENT_REVIEW_FAILED, EVENT_METRIC_ANOMALY, EVENT_REFACTOR_PROPOSAL, EVENT_AGENT_SELF_IMPROVE).',
181
- inputSchema: {
182
- type: 'object',
183
- properties: {
184
- eventType: {
185
- type: 'string',
186
- enum: [
187
- 'EVENT_CODE_COMPLETE',
188
- 'EVENT_REVIEW_FAILED',
189
- 'EVENT_REVIEW_PASSED',
190
- 'EVENT_METRIC_ANOMALY',
191
- 'EVENT_REFACTOR_PROPOSAL',
192
- 'EVENT_AGENT_SELF_IMPROVE'
193
- ],
194
- description: 'Tipo do evento canônico'
195
- },
196
- payload: {
197
- type: 'object',
198
- description: 'Dados contextuais do evento (diff, code, metric, finding, etc.)'
199
- }
200
- },
201
- required: ['eventType']
202
- }
203
- },
204
- {
205
- name: 'agent_sast_scan',
206
- description: 'Executa scanner estático SAST e detecção profunda de segredos (CWE-78, CWE-89, CWE-79, CWE-116, CWE-1333 ReDoS, CWE-798 Hardcoded Secrets).',
207
- inputSchema: {
208
- type: 'object',
209
- properties: {
210
- code: { type: 'string', description: 'Código fonte ou diff para auditoria de segurança' },
211
- filename: { type: 'string', description: 'Nome do arquivo analisado (opcional)' }
212
- },
213
- required: ['code']
214
- }
215
- },
216
- {
217
- name: 'agent_audit_quality',
218
- description: 'Audita a qualidade de código, complexidade ciclomática, profundidade de aninhamento e detecta anti-patterns como catch vazio e TODOs pendentes.',
219
- inputSchema: {
220
- type: 'object',
221
- properties: {
222
- code: { type: 'string', description: 'Código fonte para auditoria de qualidade' },
223
- filename: { type: 'string', description: 'Nome do arquivo analisado (opcional)' },
224
- maxComplexity: { type: 'number', description: 'Complexidade ciclomática máxima tolerada (padrão: 15)' }
225
- },
226
- required: ['code']
227
- }
228
- },
229
- {
230
- name: 'agent_sre_telemetry',
231
- description: 'Coleta métricas canônicas de saúde e runtime no padrão Prometheus 0.0.4 (CPU, RSS, Heap V8) e avalia limiares de saturação.',
232
- inputSchema: {
233
- type: 'object',
234
- properties: {
235
- format: { type: 'string', enum: ['prometheus', 'json'], description: 'Formato da saída de métricas (padrão: json)' },
236
- evaluateAlerts: { type: 'boolean', description: 'Se verdadeiro, executa avaliação de limiares de alerta' }
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
+ };