@maestro-ai/mcp-server 2.6.1 → 5.0.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 (153) hide show
  1. package/dist/content/.version.json +16 -0
  2. package/dist/data/project-templates.d.ts +37 -0
  3. package/dist/data/project-templates.d.ts.map +1 -0
  4. package/dist/data/project-templates.js +208 -0
  5. package/dist/data/project-templates.js.map +1 -0
  6. package/dist/errors/index.d.ts +84 -0
  7. package/dist/errors/index.d.ts.map +1 -0
  8. package/dist/errors/index.js +158 -0
  9. package/dist/errors/index.js.map +1 -0
  10. package/dist/flows/onboarding-orchestrator.d.ts.map +1 -1
  11. package/dist/flows/onboarding-orchestrator.js +126 -91
  12. package/dist/flows/onboarding-orchestrator.js.map +1 -1
  13. package/dist/gates/validator.d.ts +2 -1
  14. package/dist/gates/validator.d.ts.map +1 -1
  15. package/dist/gates/validator.js +33 -2
  16. package/dist/gates/validator.js.map +1 -1
  17. package/dist/index.js +19 -164
  18. package/dist/index.js.map +1 -1
  19. package/dist/middleware/flow-engine.middleware.d.ts +14 -0
  20. package/dist/middleware/flow-engine.middleware.d.ts.map +1 -0
  21. package/dist/middleware/flow-engine.middleware.js +51 -0
  22. package/dist/middleware/flow-engine.middleware.js.map +1 -0
  23. package/dist/middleware/index.d.ts +36 -0
  24. package/dist/middleware/index.d.ts.map +1 -0
  25. package/dist/middleware/index.js +45 -0
  26. package/dist/middleware/index.js.map +1 -0
  27. package/dist/middleware/persistence.middleware.d.ts +14 -0
  28. package/dist/middleware/persistence.middleware.d.ts.map +1 -0
  29. package/dist/middleware/persistence.middleware.js +55 -0
  30. package/dist/middleware/persistence.middleware.js.map +1 -0
  31. package/dist/middleware/skill-injection.middleware.d.ts +15 -0
  32. package/dist/middleware/skill-injection.middleware.d.ts.map +1 -0
  33. package/dist/middleware/skill-injection.middleware.js +63 -0
  34. package/dist/middleware/skill-injection.middleware.js.map +1 -0
  35. package/dist/middleware/state-loader.middleware.d.ts +13 -0
  36. package/dist/middleware/state-loader.middleware.d.ts.map +1 -0
  37. package/dist/middleware/state-loader.middleware.js +36 -0
  38. package/dist/middleware/state-loader.middleware.js.map +1 -0
  39. package/dist/router.d.ts +46 -0
  40. package/dist/router.d.ts.map +1 -0
  41. package/dist/router.js +441 -0
  42. package/dist/router.js.map +1 -0
  43. package/dist/services/content-resolver.service.d.ts +96 -0
  44. package/dist/services/content-resolver.service.d.ts.map +1 -0
  45. package/dist/services/content-resolver.service.js +280 -0
  46. package/dist/services/content-resolver.service.js.map +1 -0
  47. package/dist/services/flow-engine.d.ts +82 -0
  48. package/dist/services/flow-engine.d.ts.map +1 -0
  49. package/dist/services/flow-engine.js +270 -0
  50. package/dist/services/flow-engine.js.map +1 -0
  51. package/dist/services/onboarding.service.d.ts +20 -0
  52. package/dist/services/onboarding.service.d.ts.map +1 -0
  53. package/dist/services/onboarding.service.js +49 -0
  54. package/dist/services/onboarding.service.js.map +1 -0
  55. package/dist/services/skill-loader.service.d.ts +81 -0
  56. package/dist/services/skill-loader.service.d.ts.map +1 -0
  57. package/dist/services/skill-loader.service.js +321 -0
  58. package/dist/services/skill-loader.service.js.map +1 -0
  59. package/dist/services/specialist.service.d.ts +20 -0
  60. package/dist/services/specialist.service.d.ts.map +1 -0
  61. package/dist/services/specialist.service.js +115 -0
  62. package/dist/services/specialist.service.js.map +1 -0
  63. package/dist/services/state.service.d.ts +59 -0
  64. package/dist/services/state.service.d.ts.map +1 -0
  65. package/dist/services/state.service.js +131 -0
  66. package/dist/services/state.service.js.map +1 -0
  67. package/dist/stdio.js +329 -437
  68. package/dist/stdio.js.map +1 -1
  69. package/dist/tests/content-resolver.test.d.ts +5 -0
  70. package/dist/tests/content-resolver.test.d.ts.map +1 -0
  71. package/dist/tests/content-resolver.test.js +157 -0
  72. package/dist/tests/content-resolver.test.js.map +1 -0
  73. package/dist/tests/middleware.test.d.ts +5 -0
  74. package/dist/tests/middleware.test.d.ts.map +1 -0
  75. package/dist/tests/middleware.test.js +228 -0
  76. package/dist/tests/middleware.test.js.map +1 -0
  77. package/dist/tests/skill-loader.test.d.ts +5 -0
  78. package/dist/tests/skill-loader.test.d.ts.map +1 -0
  79. package/dist/tests/skill-loader.test.js +242 -0
  80. package/dist/tests/skill-loader.test.js.map +1 -0
  81. package/dist/tools/aprovar-gate.d.ts.map +1 -1
  82. package/dist/tools/aprovar-gate.js +35 -0
  83. package/dist/tools/aprovar-gate.js.map +1 -1
  84. package/dist/tools/brainstorm.d.ts.map +1 -1
  85. package/dist/tools/brainstorm.js +90 -49
  86. package/dist/tools/brainstorm.js.map +1 -1
  87. package/dist/tools/classificar.d.ts.map +1 -1
  88. package/dist/tools/classificar.js +20 -1
  89. package/dist/tools/classificar.js.map +1 -1
  90. package/dist/tools/confirmar-classificacao.d.ts.map +1 -1
  91. package/dist/tools/confirmar-classificacao.js +20 -1
  92. package/dist/tools/confirmar-classificacao.js.map +1 -1
  93. package/dist/tools/consolidated/analisar.d.ts +56 -0
  94. package/dist/tools/consolidated/analisar.d.ts.map +1 -0
  95. package/dist/tools/consolidated/analisar.js +96 -0
  96. package/dist/tools/consolidated/analisar.js.map +1 -0
  97. package/dist/tools/consolidated/avancar.d.ts +67 -0
  98. package/dist/tools/consolidated/avancar.d.ts.map +1 -0
  99. package/dist/tools/consolidated/avancar.js +132 -0
  100. package/dist/tools/consolidated/avancar.js.map +1 -0
  101. package/dist/tools/consolidated/checkpoint-tool.d.ts +66 -0
  102. package/dist/tools/consolidated/checkpoint-tool.d.ts.map +1 -0
  103. package/dist/tools/consolidated/checkpoint-tool.js +111 -0
  104. package/dist/tools/consolidated/checkpoint-tool.js.map +1 -0
  105. package/dist/tools/consolidated/validar.d.ts +63 -0
  106. package/dist/tools/consolidated/validar.d.ts.map +1 -0
  107. package/dist/tools/consolidated/validar.js +104 -0
  108. package/dist/tools/consolidated/validar.js.map +1 -0
  109. package/dist/tools/contexto.d.ts.map +1 -1
  110. package/dist/tools/contexto.js +18 -0
  111. package/dist/tools/contexto.js.map +1 -1
  112. package/dist/tools/discovery.d.ts +10 -10
  113. package/dist/tools/discovery.d.ts.map +1 -1
  114. package/dist/tools/discovery.js +82 -56
  115. package/dist/tools/discovery.js.map +1 -1
  116. package/dist/tools/iniciar-projeto.d.ts +48 -0
  117. package/dist/tools/iniciar-projeto.d.ts.map +1 -1
  118. package/dist/tools/iniciar-projeto.js +234 -45
  119. package/dist/tools/iniciar-projeto.js.map +1 -1
  120. package/dist/tools/maestro-tool.d.ts +51 -0
  121. package/dist/tools/maestro-tool.d.ts.map +1 -0
  122. package/dist/tools/maestro-tool.js +224 -0
  123. package/dist/tools/maestro-tool.js.map +1 -0
  124. package/dist/tools/prd-writer.d.ts +1 -1
  125. package/dist/tools/prd-writer.d.ts.map +1 -1
  126. package/dist/tools/prd-writer.js +138 -2
  127. package/dist/tools/prd-writer.js.map +1 -1
  128. package/dist/tools/proximo.d.ts.map +1 -1
  129. package/dist/tools/proximo.js +22 -16
  130. package/dist/tools/proximo.js.map +1 -1
  131. package/dist/tools/salvar.d.ts.map +1 -1
  132. package/dist/tools/salvar.js +13 -0
  133. package/dist/tools/salvar.js.map +1 -1
  134. package/dist/tools/setup-inicial.d.ts.map +1 -1
  135. package/dist/tools/setup-inicial.js +12 -0
  136. package/dist/tools/setup-inicial.js.map +1 -1
  137. package/dist/tools/status.d.ts.map +1 -1
  138. package/dist/tools/status.js +6 -0
  139. package/dist/tools/status.js.map +1 -1
  140. package/dist/tools/validar-gate.d.ts.map +1 -1
  141. package/dist/tools/validar-gate.js +25 -0
  142. package/dist/tools/validar-gate.js.map +1 -1
  143. package/dist/types/index.d.ts +20 -1
  144. package/dist/types/index.d.ts.map +1 -1
  145. package/dist/types/index.js.map +1 -1
  146. package/dist/types/response.d.ts +49 -0
  147. package/dist/types/response.d.ts.map +1 -1
  148. package/dist/types/response.js.map +1 -1
  149. package/dist/utils/smart-defaults.d.ts +56 -0
  150. package/dist/utils/smart-defaults.d.ts.map +1 -0
  151. package/dist/utils/smart-defaults.js +113 -0
  152. package/dist/utils/smart-defaults.js.map +1 -0
  153. package/package.json +1 -1
package/dist/stdio.js CHANGED
@@ -5,46 +5,73 @@
5
5
  * Uso: node dist/stdio.js [diretorio]
6
6
  * Ou via npx após publicar no npm
7
7
  *
8
- * Se nenhum diretório for fornecido, usa o diretório de trabalho atual
8
+ * v5: Skills como MCP Resources, MCP Prompts capability,
9
+ * tools consolidadas (8 públicas + legadas backward-compatible)
10
+ *
11
+ * NOTA: Usa router centralizado (router.ts) para roteamento de tools.
12
+ * Não duplicar switch/case aqui - todas as tools são registradas no router.
9
13
  */
10
14
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
11
15
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
12
- import { ListResourcesRequestSchema, ReadResourceRequestSchema, ListToolsRequestSchema, CallToolRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
16
+ import { ListResourcesRequestSchema, ReadResourceRequestSchema, ListToolsRequestSchema, CallToolRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
13
17
  import { listarEspecialistas, listarTemplates, listarGuias, lerEspecialista, lerTemplate, lerGuia, lerPrompt, setProjectDirectory, } from "./utils/files.js";
14
- import { iniciarProjeto, confirmarProjeto } from "./tools/iniciar-projeto.js";
15
- import { carregarProjeto } from "./tools/carregar-projeto.js";
16
- import { proximo } from "./tools/proximo.js";
17
- import { status } from "./tools/status.js";
18
- import { validarGate } from "./tools/validar-gate.js";
19
- import { contexto } from "./tools/contexto.js";
20
- import { classificar } from "./tools/classificar.js";
21
- import { salvar } from "./tools/salvar.js";
22
- import { injetar_conteudo } from "./tools/injetar-conteudo.js";
23
- // 🆕 FASE 1: Knowledge Base
24
- import { recordADR, recordADRSchema, recordPattern, recordPatternSchema, getContext, getContextSchema, searchKnowledge, searchKnowledgeSchema, } from "./tools/fase1/knowledge.tools.js";
25
- // 🆕 FASE 1: Checkpoint
26
- import { createCheckpoint, createCheckpointSchema, rollbackTotal, rollbackTotalSchema, rollbackPartial, rollbackPartialSchema, listCheckpoints, listCheckpointsSchema, } from "./tools/fase1/checkpoint.tools.js";
27
- // 🆕 FASE 1: Validation
28
- import { validateDependencies, validateDependenciesSchema, validateSecurity, validateSecuritySchema, checkCompliance, checkComplianceSchema, } from "./tools/fase1/validation.tools.js";
29
- // 🆕 FASE 1: Risk, AutoFix, Discovery
30
- import { evaluateRisk, evaluateRiskSchema, autoFix, autoFixSchema, discoverCodebase, discoverCodebaseSchema, } from "./tools/fase1/misc.tools.js";
18
+ import { routeToolCall, getRegisteredTools, getToolCount } from "./router.js";
19
+ import { ContentResolverService } from "./services/content-resolver.service.js";
20
+ import { SkillLoaderService } from "./services/skill-loader.service.js";
21
+ import { createStateService } from "./services/state.service.js";
22
+ import { getSpecialistPersona } from "./services/specialist.service.js";
23
+ import { getFaseComStitch } from "./flows/types.js";
31
24
  // Criar servidor MCP
32
25
  const server = new Server({
33
26
  name: "mcp-maestro",
34
- version: "1.0.0",
27
+ version: "5.0.0",
35
28
  }, {
36
29
  capabilities: {
37
30
  resources: {},
38
31
  tools: {},
32
+ prompts: {},
39
33
  },
40
34
  });
41
- // ==================== RESOURCES ====================
35
+ // ==================== RESOURCES (v5: Skills expandidas) ====================
42
36
  server.setRequestHandler(ListResourcesRequestSchema, async () => {
43
37
  const especialistas = await listarEspecialistas();
44
38
  const templates = await listarTemplates();
45
39
  const guias = await listarGuias();
40
+ // v5: Listar skills como resources estruturados
41
+ const contentResolver = new ContentResolverService(projectsDir);
42
+ const skills = await contentResolver.listAvailableSkills();
43
+ const skillResources = [];
44
+ for (const skillName of skills) {
45
+ // SKILL.md principal
46
+ skillResources.push({
47
+ uri: `maestro://skills/${skillName}/SKILL.md`,
48
+ name: `Skill: ${skillName}`,
49
+ mimeType: "text/markdown",
50
+ });
51
+ // Templates da skill
52
+ const skillTemplates = await contentResolver.listSkillResources(skillName, "templates");
53
+ for (const t of skillTemplates) {
54
+ skillResources.push({
55
+ uri: `maestro://skills/${skillName}/templates/${t}`,
56
+ name: `${skillName} Template: ${t}`,
57
+ mimeType: "text/markdown",
58
+ });
59
+ }
60
+ // Checklists da skill
61
+ const checklists = await contentResolver.listSkillResources(skillName, "checklists");
62
+ for (const c of checklists) {
63
+ skillResources.push({
64
+ uri: `maestro://skills/${skillName}/checklists/${c}`,
65
+ name: `${skillName} Checklist: ${c}`,
66
+ mimeType: "text/markdown",
67
+ });
68
+ }
69
+ }
46
70
  return {
47
71
  resources: [
72
+ // v5: Skills estruturadas (prioridade)
73
+ ...skillResources,
74
+ // Legacy: especialistas, templates, guias
48
75
  ...especialistas.map((e) => ({
49
76
  uri: `maestro://especialista/${encodeURIComponent(e)}`,
50
77
  name: `Especialista: ${e}`,
@@ -70,6 +97,30 @@ server.setRequestHandler(ListResourcesRequestSchema, async () => {
70
97
  });
71
98
  server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
72
99
  const { uri } = request.params;
100
+ // v5: Skills como resources
101
+ if (uri.startsWith("maestro://skills/")) {
102
+ const path = uri.replace("maestro://skills/", "");
103
+ const parts = path.split("/");
104
+ const skillName = parts[0];
105
+ const contentResolver = new ContentResolverService(projectsDir);
106
+ if (parts.length === 2 && parts[1] === "SKILL.md") {
107
+ // maestro://skills/{skill}/SKILL.md
108
+ const content = await contentResolver.readSkillFile(skillName, "SKILL.md");
109
+ if (!content)
110
+ throw new Error(`SKILL.md não encontrado: ${skillName}`);
111
+ return { contents: [{ uri, mimeType: "text/markdown", text: content }] };
112
+ }
113
+ if (parts.length === 3) {
114
+ // maestro://skills/{skill}/{tipo}/{arquivo}
115
+ const tipo = parts[1];
116
+ const arquivo = parts[2];
117
+ const content = await contentResolver.readSkillResource(skillName, tipo, arquivo);
118
+ if (!content)
119
+ throw new Error(`Resource não encontrado: ${uri}`);
120
+ return { contents: [{ uri, mimeType: "text/markdown", text: content }] };
121
+ }
122
+ }
123
+ // Legacy: especialistas
73
124
  if (uri.startsWith("maestro://especialista/")) {
74
125
  const nome = decodeURIComponent(uri.replace("maestro://especialista/", ""));
75
126
  const conteudo = await lerEspecialista(nome);
@@ -92,445 +143,286 @@ server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
92
143
  return { contents: [{ uri, mimeType: "text/markdown", text: conteudo }] };
93
144
  }
94
145
  if (uri === "maestro://system-prompt") {
95
- const conteudo = `# Maestro - Instruções para IA (Modo Stateless)
146
+ const conteudo = `# Maestro v5 Instruções para IA
96
147
 
97
- Você está usando o Maestro, um guia de desenvolvimento assistido por IA.
148
+ Você está usando o Maestro v5, um orquestrador de desenvolvimento assistido por IA.
98
149
 
99
- ## Modo Stateless
150
+ ## Modo Híbrido (v5)
100
151
 
101
- Este MCP opera em modo stateless. A IA deve:
102
- 1. Ler arquivos de estado do projeto (.maestro/estado.json)
103
- 2. Passar o conteúdo como parâmetro nas chamadas de tools
104
- 3. Salvar os arquivos retornados no campo \`files\` das respostas
152
+ O Maestro v5 opera em modo híbrido:
153
+ - **Estado carregado automaticamente** de .maestro/estado.json (não precisa passar como parâmetro)
154
+ - **Skills injetadas ativamente** nas respostas das tools (não precisa ler manualmente)
155
+ - **Persistência automática** o MCP salva estado e arquivos diretamente
156
+ - **Fallback stateless** — estado_json como parâmetro ainda aceito para compatibilidade
105
157
 
106
158
  ## Comportamentos Automáticos
107
159
 
108
160
  Quando o usuário disser "próximo", "avançar", "terminei" ou "pronto":
109
- 1. Leia .maestro/estado.json do projeto
110
- 2. Identifique o entregável desenvolvido
111
- 3. Chame \`proximo\` passando entregavel, estado_json e diretorio
112
- 4. Salve os arquivos retornados
161
+ 1. Chame \`avancar(diretorio: "<path>")\`
162
+ 2. O Maestro detecta contexto automaticamente
163
+ 3. O contexto do especialista vem incluído na resposta
164
+ 4. Siga as instruções do especialista e template retornados
113
165
 
114
- ## Tools Disponíveis (Stateless)
166
+ ## Tools Disponíveis (v5 Consolidadas)
115
167
 
116
- - \`iniciar_projeto(nome, diretorio)\` - Inicia novo projeto
117
- - \`carregar_projeto(estado_json, diretorio)\` - Carrega projeto existente
118
- - \`proximo(entregavel, estado_json, diretorio)\` - Salva e avança fase
119
- - \`status(estado_json, diretorio)\` - Retorna estado atual
120
- - \`validar_gate(estado_json, diretorio)\` - Valida checklist
121
- - \`classificar(estado_json, diretorio)\` - Reclassifica projeto
122
- - \`contexto(estado_json, diretorio)\` - Retorna contexto
123
- - \`salvar(conteudo, tipo, estado_json, diretorio)\` - Salva rascunhos/anexos
168
+ | Tool | Descrição |
169
+ |------|-----------|
170
+ | \`maestro(diretorio)\` | Entry point inteligente — detecta contexto e guia |
171
+ | \`avancar(diretorio, entregavel?)\` | Avança fase (onboarding ou desenvolvimento) |
172
+ | \`status(diretorio)\` | Status completo do projeto |
173
+ | \`validar(diretorio, tipo?)\` | Valida gate, entregável ou compliance |
174
+ | \`contexto(diretorio)\` | Contexto acumulado (ADRs, padrões) |
175
+ | \`salvar(diretorio, conteudo, tipo)\` | Salva rascunhos/anexos |
176
+ | \`checkpoint(diretorio, acao)\` | Gerencia checkpoints e rollbacks |
177
+ | \`analisar(diretorio, tipo?)\` | Análise de código (segurança, qualidade, etc.) |
178
+
179
+ > **Nota:** Tools legadas (proximo, validar_gate, etc.) ainda funcionam para backward compatibility.
124
180
  `;
125
181
  return { contents: [{ uri, mimeType: "text/markdown", text: conteudo }] };
126
182
  }
127
183
  throw new Error(`Resource não encontrado: ${uri}`);
128
184
  });
129
- // ==================== TOOLS ====================
130
- server.setRequestHandler(ListToolsRequestSchema, async () => ({
131
- tools: [
132
- {
133
- name: "iniciar_projeto",
134
- description: "Inicia novo projeto (stateless). Retorna arquivos para IA salvar.",
135
- inputSchema: {
136
- type: "object",
137
- properties: {
138
- nome: { type: "string", description: "Nome do projeto" },
139
- descricao: { type: "string", description: "Descrição opcional" },
140
- diretorio: { type: "string", description: "Diretório absoluto do projeto" },
141
- ide: { type: "string", enum: ["windsurf", "cursor", "antigravity"], description: "IDE alvo para injection" },
142
- },
143
- required: ["nome", "diretorio"],
144
- },
145
- },
146
- {
147
- name: "confirmar_projeto",
148
- description: "Confirma criação do projeto com tipo e complexidade. Injeta conteúdo automaticamente.",
149
- inputSchema: {
150
- type: "object",
151
- properties: {
152
- nome: { type: "string", description: "Nome do projeto" },
153
- descricao: { type: "string", description: "Descrição opcional" },
154
- diretorio: { type: "string", description: "Diretório absoluto do projeto" },
155
- tipo_artefato: { type: "string", enum: ["poc", "script", "internal", "product"], description: "Tipo de artefato" },
156
- nivel_complexidade: { type: "string", enum: ["simples", "medio", "complexo"], description: "Nível de complexidade" },
157
- ide: { type: "string", enum: ["windsurf", "cursor", "antigravity"], description: "IDE alvo para injection" },
158
- },
159
- required: ["nome", "diretorio", "tipo_artefato", "nivel_complexidade", "ide"],
160
- },
161
- },
162
- {
163
- name: "carregar_projeto",
164
- description: "Carrega projeto existente (stateless). Requer estado_json.",
165
- inputSchema: {
166
- type: "object",
167
- properties: {
168
- estado_json: { type: "string", description: "Conteúdo de .maestro/estado.json" },
169
- diretorio: { type: "string", description: "Diretório do projeto" },
170
- },
171
- required: ["estado_json", "diretorio"],
172
- },
173
- },
174
- {
175
- name: "proximo",
176
- description: "Salva entregável e avança fase (stateless). Requer estado_json.",
177
- inputSchema: {
178
- type: "object",
179
- properties: {
180
- entregavel: { type: "string", description: "Conteúdo do entregável" },
181
- estado_json: { type: "string", description: "Conteúdo de .maestro/estado.json" },
182
- diretorio: { type: "string", description: "Diretório do projeto" },
183
- nome_arquivo: { type: "string", description: "Nome do arquivo" },
184
- },
185
- required: ["entregavel", "estado_json", "diretorio"],
186
- },
187
- },
188
- {
189
- name: "status",
190
- description: "Retorna status do projeto (stateless). Requer estado_json.",
191
- inputSchema: {
192
- type: "object",
193
- properties: {
194
- estado_json: { type: "string", description: "Conteúdo de .maestro/estado.json" },
195
- diretorio: { type: "string", description: "Diretório do projeto" },
196
- },
197
- required: ["estado_json", "diretorio"],
198
- },
199
- },
200
- {
201
- name: "validar_gate",
202
- description: "Valida checklist de saída (stateless). Requer estado_json.",
203
- inputSchema: {
204
- type: "object",
205
- properties: {
206
- fase: { type: "number", description: "Número da fase" },
207
- entregavel: { type: "string", description: "Conteúdo para validar" },
208
- estado_json: { type: "string", description: "Conteúdo de .maestro/estado.json" },
209
- diretorio: { type: "string", description: "Diretório do projeto" },
210
- },
211
- required: ["estado_json", "diretorio"],
212
- },
213
- },
214
- {
215
- name: "contexto",
216
- description: "Retorna contexto do projeto (stateless). Requer estado_json.",
217
- inputSchema: {
218
- type: "object",
219
- properties: {
220
- estado_json: { type: "string", description: "Conteúdo de .maestro/estado.json" },
221
- diretorio: { type: "string", description: "Diretório do projeto" },
222
- },
223
- required: ["estado_json", "diretorio"],
224
- },
225
- },
226
- {
227
- name: "classificar",
228
- description: "Reclassifica complexidade (stateless). Requer estado_json.",
229
- inputSchema: {
230
- type: "object",
231
- properties: {
232
- prd: { type: "string", description: "Conteúdo do PRD" },
233
- nivel: { type: "string", enum: ["simples", "medio", "complexo"] },
234
- estado_json: { type: "string", description: "Conteúdo de .maestro/estado.json" },
235
- diretorio: { type: "string", description: "Diretório do projeto" },
236
- },
237
- required: ["estado_json", "diretorio"],
185
+ // ==================== PROMPTS (v5: System Prompt Automático) ====================
186
+ server.setRequestHandler(ListPromptsRequestSchema, async () => {
187
+ return {
188
+ prompts: [
189
+ {
190
+ name: "maestro-specialist",
191
+ description: "Persona + instruções do especialista da fase atual do projeto",
192
+ arguments: [
193
+ {
194
+ name: "diretorio",
195
+ description: "Diretório do projeto",
196
+ required: true,
197
+ },
198
+ ],
238
199
  },
239
- },
240
- {
241
- name: "salvar",
242
- description: "Salva conteúdo (stateless). Requer estado_json.",
243
- inputSchema: {
244
- type: "object",
245
- properties: {
246
- conteudo: { type: "string", description: "Conteúdo a salvar" },
247
- tipo: { type: "string", enum: ["rascunho", "anexo", "entregavel"] },
248
- estado_json: { type: "string", description: "Conteúdo de .maestro/estado.json" },
249
- diretorio: { type: "string", description: "Diretório do projeto" },
250
- },
251
- required: ["conteudo", "tipo", "estado_json", "diretorio"],
200
+ {
201
+ name: "maestro-context",
202
+ description: "Contexto completo do projeto para a sessão de trabalho",
203
+ arguments: [
204
+ {
205
+ name: "diretorio",
206
+ description: "Diretório do projeto",
207
+ required: true,
208
+ },
209
+ ],
252
210
  },
253
- },
254
- {
255
- name: "injetar_conteudo",
256
- description: "Injeta conteúdo base (especialistas, templates, guias) no projeto. Use force:true para sobrescrever.",
257
- inputSchema: {
258
- type: "object",
259
- properties: {
260
- diretorio: { type: "string", description: "Diretório absoluto do projeto" },
261
- source: { type: "string", enum: ["builtin", "custom"], description: "Fonte do conteúdo (padrão: builtin)" },
262
- custom_path: { type: "string", description: "Caminho customizado se source=custom" },
263
- force: { type: "boolean", description: "Sobrescrever se já existe (padrão: false)" },
264
- },
265
- required: ["diretorio"],
211
+ {
212
+ name: "maestro-template",
213
+ description: "Template do entregável esperado para a fase atual",
214
+ arguments: [
215
+ {
216
+ name: "diretorio",
217
+ description: "Diretório do projeto",
218
+ required: true,
219
+ },
220
+ ],
266
221
  },
267
- },
268
- // 🆕 FASE 1: KNOWLEDGE BASE
269
- {
270
- name: "record_adr",
271
- description: "Registra Architecture Decision Record com decisão, contexto, alternativas e consequências",
272
- inputSchema: recordADRSchema,
273
- },
274
- {
275
- name: "record_pattern",
276
- description: "Registra padrão identificado com contexto, problema e solução",
277
- inputSchema: recordPatternSchema,
278
- },
279
- {
280
- name: "get_context",
281
- description: "Retorna contexto relevante para fase específica (ADRs, padrões, decisões)",
282
- inputSchema: getContextSchema,
283
- },
284
- {
285
- name: "search_knowledge",
286
- description: "Busca na base de conhecimento por query",
287
- inputSchema: searchKnowledgeSchema,
288
- },
289
- // 🆕 FASE 1: CHECKPOINT
290
- {
291
- name: "create_checkpoint",
292
- description: "Cria checkpoint do projeto antes de mudanças arriscadas",
293
- inputSchema: createCheckpointSchema,
294
- },
295
- {
296
- name: "rollback_total",
297
- description: "Rollback total para um checkpoint",
298
- inputSchema: rollbackTotalSchema,
299
- },
300
- {
301
- name: "rollback_partial",
302
- description: "Rollback parcial (apenas módulos específicos)",
303
- inputSchema: rollbackPartialSchema,
304
- },
305
- {
306
- name: "list_checkpoints",
307
- description: "Lista todos os checkpoints disponíveis",
308
- inputSchema: listCheckpointsSchema,
309
- },
310
- // 🆕 FASE 1: VALIDATION
311
- {
312
- name: "validate_dependencies",
313
- description: "Valida dependências e detecta hallucinations",
314
- inputSchema: validateDependenciesSchema,
315
- },
316
- {
317
- name: "validate_security",
318
- description: "Valida segurança contra OWASP Top 10",
319
- inputSchema: validateSecuritySchema,
320
- },
321
- {
322
- name: "check_compliance",
323
- description: "Verifica compliance (LGPD, PCI-DSS, HIPAA)",
324
- inputSchema: checkComplianceSchema,
325
- },
326
- // 🆕 FASE 1: RISK, AUTOFIX, DISCOVERY
327
- {
328
- name: "evaluate_risk",
329
- description: "Avalia risco de uma operação",
330
- inputSchema: evaluateRiskSchema,
331
- },
332
- {
333
- name: "auto_fix",
334
- description: "Tenta corrigir automaticamente erros de código",
335
- inputSchema: autoFixSchema,
336
- },
337
- {
338
- name: "discover_codebase",
339
- description: "Analisa codebase e detecta arquitetura/stack",
340
- inputSchema: discoverCodebaseSchema,
341
- },
342
- ],
343
- }));
344
- server.setRequestHandler(CallToolRequestSchema, async (request) => {
345
- const { name, arguments: args } = request.params;
346
- const a = args;
347
- const typedArgs = a || {};
222
+ ],
223
+ };
224
+ });
225
+ server.setRequestHandler(GetPromptRequestSchema, async (request) => {
226
+ const { name, arguments: promptArgs } = request.params;
227
+ const diretorio = promptArgs?.diretorio || projectsDir;
228
+ if (name === "maestro-specialist") {
229
+ return await buildSpecialistPrompt(diretorio);
230
+ }
231
+ if (name === "maestro-context") {
232
+ return await buildContextPrompt(diretorio);
233
+ }
234
+ if (name === "maestro-template") {
235
+ return await buildTemplatePrompt(diretorio);
236
+ }
237
+ throw new Error(`Prompt não encontrado: ${name}`);
238
+ });
239
+ /**
240
+ * Constrói prompt dinâmico do especialista da fase atual.
241
+ */
242
+ async function buildSpecialistPrompt(diretorio) {
243
+ const stateService = createStateService(diretorio);
244
+ const estado = await stateService.load();
245
+ if (!estado) {
246
+ return {
247
+ description: "Nenhum projeto encontrado",
248
+ messages: [{
249
+ role: "user",
250
+ content: { type: "text", text: "Nenhum projeto ativo neste diretório. Use `maestro(diretorio)` para começar." },
251
+ }],
252
+ };
253
+ }
254
+ const faseInfo = getFaseComStitch(estado.nivel, estado.fase_atual, estado.usar_stitch);
255
+ if (!faseInfo) {
256
+ return {
257
+ description: `Projeto: ${estado.nome}`,
258
+ messages: [{
259
+ role: "user",
260
+ content: { type: "text", text: `Projeto ${estado.nome} — fase ${estado.fase_atual} não encontrada no fluxo.` },
261
+ }],
262
+ };
263
+ }
264
+ const mode = (estado.config?.mode || "balanced");
265
+ const contentResolver = new ContentResolverService(diretorio);
266
+ const skillLoader = new SkillLoaderService(contentResolver);
348
267
  try {
349
- switch (name) {
350
- case "iniciar_projeto":
351
- return await iniciarProjeto({
352
- nome: typedArgs.nome,
353
- descricao: typedArgs.descricao,
354
- diretorio: typedArgs.diretorio,
355
- ide: typedArgs.ide,
356
- modo: typedArgs.modo,
357
- });
358
- case "confirmar_projeto":
359
- return await confirmarProjeto({
360
- nome: typedArgs.nome,
361
- descricao: typedArgs.descricao,
362
- diretorio: typedArgs.diretorio,
363
- tipo_artefato: typedArgs.tipo_artefato,
364
- nivel_complexidade: typedArgs.nivel_complexidade,
365
- ide: typedArgs.ide,
366
- modo: typedArgs.modo,
367
- });
368
- case "carregar_projeto":
369
- return await carregarProjeto({
370
- estado_json: typedArgs.estado_json,
371
- diretorio: typedArgs.diretorio,
372
- });
373
- case "proximo":
374
- return await proximo({
375
- entregavel: typedArgs.entregavel,
376
- estado_json: typedArgs.estado_json,
377
- diretorio: typedArgs.diretorio,
378
- nome_arquivo: typedArgs.nome_arquivo,
379
- });
380
- case "status":
381
- return await status({
382
- estado_json: typedArgs.estado_json,
383
- diretorio: typedArgs.diretorio,
384
- });
385
- case "validar_gate":
386
- return await validarGate({
387
- fase: typedArgs.fase,
388
- entregavel: typedArgs.entregavel,
389
- estado_json: typedArgs.estado_json,
390
- diretorio: typedArgs.diretorio,
391
- });
392
- case "contexto":
393
- return await contexto({
394
- estado_json: typedArgs.estado_json,
395
- diretorio: typedArgs.diretorio,
396
- });
397
- case "classificar":
398
- return await classificar({
399
- prd: typedArgs.prd,
400
- nivel: typedArgs.nivel,
401
- estado_json: typedArgs.estado_json,
402
- diretorio: typedArgs.diretorio,
403
- });
404
- case "salvar":
405
- return await salvar({
406
- conteudo: typedArgs.conteudo,
407
- tipo: typedArgs.tipo,
408
- estado_json: typedArgs.estado_json,
409
- diretorio: typedArgs.diretorio,
410
- nome_arquivo: typedArgs.nome_arquivo,
411
- });
412
- case "injetar_conteudo":
413
- return await injetar_conteudo({
414
- diretorio: typedArgs.diretorio,
415
- source: typedArgs.source,
416
- custom_path: typedArgs.custom_path,
417
- force: typedArgs.force,
418
- });
419
- // 🆕 FASE 1: KNOWLEDGE BASE
420
- case "record_adr":
421
- return await recordADR({
422
- decision: typedArgs.decision,
423
- context: typedArgs.context,
424
- alternatives: typedArgs.alternatives,
425
- consequences: typedArgs.consequences,
426
- risks: typedArgs.risks,
427
- estado_json: typedArgs.estado_json,
428
- diretorio: typedArgs.diretorio,
429
- });
430
- case "record_pattern":
431
- return await recordPattern({
432
- name: typedArgs.name,
433
- context: typedArgs.context,
434
- problem: typedArgs.problem,
435
- solution: typedArgs.solution,
436
- examples: typedArgs.examples,
437
- relatedPatterns: typedArgs.relatedPatterns,
438
- estado_json: typedArgs.estado_json,
439
- diretorio: typedArgs.diretorio,
440
- });
441
- case "get_context":
442
- return await getContext({
443
- fase: typedArgs.fase,
444
- estado_json: typedArgs.estado_json,
445
- diretorio: typedArgs.diretorio,
446
- });
447
- case "search_knowledge":
448
- return await searchKnowledge({
449
- query: typedArgs.query,
450
- estado_json: typedArgs.estado_json,
451
- diretorio: typedArgs.diretorio,
452
- });
453
- // 🆕 FASE 1: CHECKPOINT
454
- case "create_checkpoint":
455
- return await createCheckpoint({
456
- reason: typedArgs.reason,
457
- auto: typedArgs.auto,
458
- estado_json: typedArgs.estado_json,
459
- diretorio: typedArgs.diretorio,
460
- });
461
- case "rollback_total":
462
- return await rollbackTotal({
463
- checkpointId: typedArgs.checkpointId,
464
- estado_json: typedArgs.estado_json,
465
- diretorio: typedArgs.diretorio,
466
- });
467
- case "rollback_partial":
468
- return await rollbackPartial({
469
- checkpointId: typedArgs.checkpointId,
470
- modules: typedArgs.modules,
471
- estado_json: typedArgs.estado_json,
472
- diretorio: typedArgs.diretorio,
473
- });
474
- case "list_checkpoints":
475
- return await listCheckpoints({
476
- estado_json: typedArgs.estado_json,
477
- diretorio: typedArgs.diretorio,
478
- });
479
- // 🆕 FASE 1: VALIDATION
480
- case "validate_dependencies":
481
- return await validateDependencies({
482
- code: typedArgs.code,
483
- language: typedArgs.language,
484
- estado_json: typedArgs.estado_json,
485
- diretorio: typedArgs.diretorio,
486
- });
487
- case "validate_security":
488
- return await validateSecurity({
489
- code: typedArgs.code,
490
- language: typedArgs.language,
491
- estado_json: typedArgs.estado_json,
492
- diretorio: typedArgs.diretorio,
493
- });
494
- case "check_compliance":
495
- return await checkCompliance({
496
- code: typedArgs.code,
497
- standard: typedArgs.standard,
498
- estado_json: typedArgs.estado_json,
499
- diretorio: typedArgs.diretorio,
500
- });
501
- // 🆕 FASE 1: RISK, AUTOFIX, DISCOVERY
502
- case "evaluate_risk":
503
- return await evaluateRisk({
504
- operation: typedArgs.operation,
505
- context: typedArgs.context,
506
- estado_json: typedArgs.estado_json,
507
- diretorio: typedArgs.diretorio,
508
- });
509
- case "auto_fix":
510
- return await autoFix({
511
- code: typedArgs.code,
512
- error: typedArgs.error,
513
- estado_json: typedArgs.estado_json,
514
- diretorio: typedArgs.diretorio,
515
- });
516
- case "discover_codebase":
517
- return await discoverCodebase({
518
- estado_json: typedArgs.estado_json,
519
- diretorio: typedArgs.diretorio,
520
- });
521
- default:
522
- return {
523
- content: [{ type: "text", text: `Tool não encontrada: ${name}` }],
524
- isError: true,
525
- };
268
+ const contextPkg = await skillLoader.loadForPhase(faseInfo.nome, mode);
269
+ if (contextPkg) {
270
+ return {
271
+ description: `Especialista: ${contextPkg.specialist?.name || faseInfo.nome} — Fase ${estado.fase_atual}/${estado.total_fases}`,
272
+ messages: [{
273
+ role: "user",
274
+ content: {
275
+ type: "text",
276
+ text: `# Especialista da Fase: ${faseInfo.nome}\n\n${skillLoader.formatAsMarkdown(contextPkg)}`,
277
+ },
278
+ }],
279
+ };
526
280
  }
527
281
  }
528
282
  catch (error) {
283
+ console.warn("[Prompt] Falha ao carregar skill:", error);
284
+ }
285
+ // Fallback: persona básica
286
+ const specialist = getSpecialistPersona(faseInfo.nome);
287
+ return {
288
+ description: `Especialista: ${specialist?.name || faseInfo.nome}`,
289
+ messages: [{
290
+ role: "user",
291
+ content: {
292
+ type: "text",
293
+ text: specialist
294
+ ? `# ${specialist.name}\n\n**Tom:** ${specialist.tone}\n**Expertise:** ${specialist.expertise.join(", ")}\n**Instruções:** ${specialist.instructions}`
295
+ : `Fase ${estado.fase_atual}: ${faseInfo.nome}`,
296
+ },
297
+ }],
298
+ };
299
+ }
300
+ /**
301
+ * Constrói prompt de contexto completo do projeto.
302
+ */
303
+ async function buildContextPrompt(diretorio) {
304
+ const stateService = createStateService(diretorio);
305
+ const estado = await stateService.load();
306
+ if (!estado) {
307
+ return {
308
+ description: "Nenhum projeto encontrado",
309
+ messages: [{
310
+ role: "user",
311
+ content: { type: "text", text: "Nenhum projeto ativo neste diretório." },
312
+ }],
313
+ };
314
+ }
315
+ const faseInfo = getFaseComStitch(estado.nivel, estado.fase_atual, estado.usar_stitch);
316
+ const contextText = `# Contexto do Projeto: ${estado.nome}
317
+
318
+ ## Estado
319
+ | Campo | Valor |
320
+ |-------|-------|
321
+ | **Nível** | ${estado.nivel.toUpperCase()} |
322
+ | **Fase Atual** | ${estado.fase_atual}/${estado.total_fases} — ${faseInfo?.nome || "N/A"} |
323
+ | **Gates Validados** | ${estado.gates_validados?.join(", ") || "nenhum"} |
324
+
325
+ ## Entregáveis Salvos
326
+ ${Object.entries(estado.entregaveis || {}).map(([k, v]) => `- **${k}:** ${v}`).join("\n") || "Nenhum ainda."}
327
+
328
+ ## Próximo Passo
329
+ Trabalhe com o especialista **${faseInfo?.especialista || "N/A"}** para gerar: **${faseInfo?.entregavel_esperado || "N/A"}**
330
+ `;
331
+ return {
332
+ description: `Projeto: ${estado.nome} — Fase ${estado.fase_atual}/${estado.total_fases}`,
333
+ messages: [{
334
+ role: "user",
335
+ content: { type: "text", text: contextText },
336
+ }],
337
+ };
338
+ }
339
+ /**
340
+ * Constrói prompt do template da fase atual.
341
+ */
342
+ async function buildTemplatePrompt(diretorio) {
343
+ const stateService = createStateService(diretorio);
344
+ const estado = await stateService.load();
345
+ if (!estado) {
346
+ return {
347
+ description: "Nenhum projeto encontrado",
348
+ messages: [{
349
+ role: "user",
350
+ content: { type: "text", text: "Nenhum projeto ativo neste diretório." },
351
+ }],
352
+ };
353
+ }
354
+ const faseInfo = getFaseComStitch(estado.nivel, estado.fase_atual, estado.usar_stitch);
355
+ if (!faseInfo) {
529
356
  return {
530
- content: [{ type: "text", text: `Erro: ${String(error)}` }],
531
- isError: true,
357
+ description: `Projeto: ${estado.nome}`,
358
+ messages: [{
359
+ role: "user",
360
+ content: { type: "text", text: `Projeto ${estado.nome} — fase ${estado.fase_atual} não encontrada.` },
361
+ }],
532
362
  };
533
363
  }
364
+ const contentResolver = new ContentResolverService(diretorio);
365
+ const skillLoader = new SkillLoaderService(contentResolver);
366
+ try {
367
+ const templateContent = await skillLoader.loadTemplate(faseInfo.nome);
368
+ if (templateContent) {
369
+ return {
370
+ description: `Template: ${faseInfo.entregavel_esperado || faseInfo.nome}`,
371
+ messages: [{
372
+ role: "user",
373
+ content: {
374
+ type: "text",
375
+ text: `# Template do Entregável: ${faseInfo.entregavel_esperado || faseInfo.nome}
376
+
377
+ ## Fase ${estado.fase_atual}/${estado.total_fases}: ${faseInfo.nome}
378
+
379
+ Use este template como base para gerar o entregável:
380
+
381
+ ---
382
+
383
+ ${templateContent}
384
+
385
+ ---
386
+
387
+ > 💡 Dica: Preencha todas as seções marcadas com [...] ou indicadores de conteúdo.`,
388
+ },
389
+ }],
390
+ };
391
+ }
392
+ }
393
+ catch (error) {
394
+ console.warn("[Prompt] Falha ao carregar template:", error);
395
+ }
396
+ // Fallback: estrutura básica
397
+ return {
398
+ description: `Template: ${faseInfo.entregavel_esperado || faseInfo.nome}`,
399
+ messages: [{
400
+ role: "user",
401
+ content: {
402
+ type: "text",
403
+ text: `# Template do Entregável: ${faseInfo.entregavel_esperado || faseInfo.nome}
404
+
405
+ ## Fase ${estado.fase_atual}/${estado.total_fases}: ${faseInfo.nome}
406
+
407
+ ### Estrutura Esperada
408
+
409
+ ${faseInfo.gate_checklist.map((item, i) => `${i + 1}. ${item}`).join("\n")}
410
+
411
+ ---
412
+
413
+ > ℹ️ Template específico não disponível. Use a lista acima como guia.`,
414
+ },
415
+ }],
416
+ };
417
+ }
418
+ // ==================== TOOLS (via Router Centralizado) ====================
419
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
420
+ tools: getRegisteredTools(),
421
+ }));
422
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
423
+ const { name, arguments: args } = request.params;
424
+ const rawArgs = args || {};
425
+ return await routeToolCall(name, rawArgs);
534
426
  });
535
427
  // ==================== START ====================
536
428
  // Obter diretório dos argumentos ou usar cwd
@@ -540,7 +432,7 @@ setProjectDirectory(projectsDir);
540
432
  async function main() {
541
433
  const transport = new StdioServerTransport();
542
434
  await server.connect(transport);
543
- console.error(`MCP Maestro (stdio) iniciado - Modo Stateless`);
435
+ console.error(`MCP Maestro v5 (stdio) iniciado ${getToolCount()} tools públicas`);
544
436
  console.error(`Diretório de projetos: ${projectsDir}`);
545
437
  }
546
438
  main().catch(console.error);