refine-mcp 0.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 (39) hide show
  1. package/dist/detection/compressor.d.ts +26 -0
  2. package/dist/detection/compressor.js +446 -0
  3. package/dist/detection/concern-map.d.ts +16 -0
  4. package/dist/detection/concern-map.js +236 -0
  5. package/dist/detection/context-extractor.d.ts +39 -0
  6. package/dist/detection/context-extractor.js +390 -0
  7. package/dist/detection/file-tree.d.ts +33 -0
  8. package/dist/detection/file-tree.js +174 -0
  9. package/dist/index.d.ts +10 -0
  10. package/dist/index.js +48 -0
  11. package/dist/prompts/index.d.ts +9 -0
  12. package/dist/prompts/index.js +125 -0
  13. package/dist/resources/identity.d.ts +6 -0
  14. package/dist/resources/identity.js +30 -0
  15. package/dist/resources/index.d.ts +6 -0
  16. package/dist/resources/index.js +14 -0
  17. package/dist/resources/prd.d.ts +6 -0
  18. package/dist/resources/prd.js +30 -0
  19. package/dist/resources/roadmap.d.ts +6 -0
  20. package/dist/resources/roadmap.js +30 -0
  21. package/dist/resources/tokens.d.ts +6 -0
  22. package/dist/resources/tokens.js +30 -0
  23. package/dist/setup.d.ts +11 -0
  24. package/dist/setup.js +429 -0
  25. package/dist/tools/checkin.d.ts +6 -0
  26. package/dist/tools/checkin.js +72 -0
  27. package/dist/tools/complete.d.ts +6 -0
  28. package/dist/tools/complete.js +56 -0
  29. package/dist/tools/get-prompt.d.ts +7 -0
  30. package/dist/tools/get-prompt.js +68 -0
  31. package/dist/tools/get-skill.d.ts +6 -0
  32. package/dist/tools/get-skill.js +57 -0
  33. package/dist/tools/refine-run.d.ts +22 -0
  34. package/dist/tools/refine-run.js +150 -0
  35. package/dist/utils/api.d.ts +12 -0
  36. package/dist/utils/api.js +69 -0
  37. package/dist/utils/config.d.ts +9 -0
  38. package/dist/utils/config.js +24 -0
  39. package/package.json +33 -0
package/dist/setup.js ADDED
@@ -0,0 +1,429 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Setup wizard: npx @refine.build/mcp setup
4
+ *
5
+ * 1. Pede token (ou abre browser)
6
+ * 2. Detecta IDE (Claude Code, Cursor, Windsurf)
7
+ * 3. Gera config pro IDE detectado
8
+ * 4. Copia CLAUDE.md pro projeto se nao existe
9
+ * 5. Confirma setup
10
+ */
11
+ import { execSync } from "node:child_process";
12
+ import { existsSync, mkdirSync, writeFileSync } from "node:fs";
13
+ import { join } from "node:path";
14
+ import { createInterface } from "node:readline";
15
+ function detectIDE() {
16
+ const cwd = process.cwd();
17
+ const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
18
+ // Cursor: .cursor/ dir exists
19
+ if (existsSync(join(cwd, ".cursor"))) {
20
+ return { ide: "cursor", label: "Cursor" };
21
+ }
22
+ // Windsurf: check config path
23
+ if (existsSync(join(home, ".codeium", "windsurf"))) {
24
+ return { ide: "windsurf", label: "Windsurf" };
25
+ }
26
+ // Gemini CLI / Antigravity: .gemini/ dir or GEMINI.md
27
+ if (existsSync(join(cwd, ".gemini")) || existsSync(join(cwd, "GEMINI.md"))) {
28
+ return { ide: "gemini", label: "Gemini CLI / Antigravity" };
29
+ }
30
+ // Replit: replit.nix or .replit
31
+ if (existsSync(join(cwd, "replit.nix")) || existsSync(join(cwd, ".replit"))) {
32
+ return { ide: "replit", label: "Replit" };
33
+ }
34
+ // Claude Code: check if CLAUDE.md exists
35
+ if (existsSync(join(cwd, "CLAUDE.md"))) {
36
+ return { ide: "claude-code", label: "Claude Code" };
37
+ }
38
+ // Codex: AGENTS.md is sufficient (OpenAI Codex reads AGENTS.md natively)
39
+ // Detected last since AGENTS.md might have been created by us
40
+ return { ide: "unknown", label: "Desconhecido" };
41
+ }
42
+ // --- Geração de config ---
43
+ function generateClaudeCodeCommand(token) {
44
+ return `claude mcp add refine -- npx -y @refine.build/mcp --token ${token}`;
45
+ }
46
+ function generateCursorConfig(token) {
47
+ const config = {
48
+ mcpServers: {
49
+ refine: {
50
+ command: "npx",
51
+ args: ["-y", "@refine.build/mcp", "--token", token],
52
+ },
53
+ },
54
+ };
55
+ return JSON.stringify(config, null, 2);
56
+ }
57
+ function generateWindsurfConfig(token) {
58
+ const config = {
59
+ mcpServers: {
60
+ refine: {
61
+ command: "npx",
62
+ args: ["-y", "@refine.build/mcp", "--token", token],
63
+ },
64
+ },
65
+ };
66
+ return JSON.stringify(config, null, 2);
67
+ }
68
+ function generateWindowsConfig(token) {
69
+ const config = {
70
+ mcpServers: {
71
+ refine: {
72
+ command: "cmd",
73
+ args: ["/c", "npx", "-y", "@refine.build/mcp", "--token", token],
74
+ },
75
+ },
76
+ };
77
+ return JSON.stringify(config, null, 2);
78
+ }
79
+ // --- AGENTS.md (padrao universal) ---
80
+ const AGENTS_MD_CONTENT = `# AGENTS.md — refine.build Product Builder Pipeline
81
+
82
+ > Este arquivo e lido automaticamente por Claude Code, Cursor, Windsurf, Codex, Gemini CLI, Replit, Aider, Zed, Warp, RooCode e outros agentes compatíveis com o padrao AGENTS.md.
83
+
84
+ ## Pipeline
85
+
86
+ Este projeto segue o pipeline de 13 skills do Product Builder (refine.build).
87
+ O MCP server @refine.build/mcp esta configurado e sincroniza o progresso automaticamente.
88
+
89
+ ## Tools MCP disponiveis
90
+
91
+ - **refine_checkin** — Escaneia o projeto e detecta a etapa ativa. Chame no inicio de cada sessao e apos mudancas significativas.
92
+ - **refine_get_skill** — Retorna a skill ativa, fase e o que fazer.
93
+ - **refine_complete_skill** — Marca a skill atual como concluida e desbloqueia a proxima.
94
+ - **refine_get_prompt** — Retorna o system prompt completo da skill pra conduzir o trabalho.
95
+
96
+ ## Regras
97
+
98
+ 1. No inicio de cada sessao, chame refine_checkin para verificar a skill ativa.
99
+ 2. Apos criar ou modificar arquivos significativos (paginas, componentes, features, configuracoes), chame refine_checkin novamente.
100
+ 3. Quando o builder disser que terminou uma etapa, chame refine_complete_skill.
101
+ 4. Antes de iniciar uma nova skill, chame refine_get_prompt para obter as instrucoes completas.
102
+ 5. Sempre informe ao builder em qual skill ele esta e o que falta fazer.
103
+
104
+ ## Roadmap-first: nunca implemente sem mapear
105
+
106
+ Quando o builder pedir para criar algo novo, corrigir um bug ou adicionar uma feature:
107
+ 1. Abra docs/roadmap.md e verifique se ja existe uma task mapeada para isso.
108
+ 2. Se ja existe, siga a task normalmente.
109
+ 3. Se NAO existe, antes de qualquer codigo:
110
+ - Proponha a task ao builder com: titulo, complexidade (simples/media/complexa), arquivos envolvidos e notas.
111
+ - Espere o builder aprovar.
112
+ - Insira a task no roadmap.md na fase correta, com o proximo TASK number disponivel.
113
+ - So entao implemente.
114
+ 4. Ao concluir, marque [x] na task do roadmap.md. O checkin sincroniza o progresso automaticamente.
115
+ `;
116
+ // --- Regras do pipeline (IDE-specific, fallback) ---
117
+ const CLAUDE_MD_RULES = `## Refine.build — Product Builder Pipeline
118
+ Este projeto segue o pipeline de 13 skills do Product Builder.
119
+ Use os tools do MCP refine para manter o progresso sincronizado.
120
+
121
+ ### Regras:
122
+ 1. No inicio de cada sessao, chame refine_checkin para verificar a skill ativa.
123
+ 2. Apos criar ou modificar arquivos significativos (paginas, componentes, features, configuracoes), chame refine_checkin novamente.
124
+ 3. Quando o builder disser que terminou uma etapa, chame refine_complete_skill.
125
+ 4. Antes de iniciar uma nova skill, chame refine_get_prompt para obter as instrucoes completas.
126
+ 5. Sempre informe ao builder em qual skill ele esta e o que falta fazer.
127
+
128
+ ### Roadmap-first: nunca implemente sem mapear
129
+ Quando o builder pedir para criar algo novo, corrigir um bug ou adicionar uma feature:
130
+ 1. Abra docs/roadmap.md e verifique se ja existe uma task mapeada para isso.
131
+ 2. Se ja existe, siga a task normalmente.
132
+ 3. Se NAO existe, antes de qualquer codigo:
133
+ - Proponha a task ao builder com: titulo, complexidade (simples/media/complexa), arquivos envolvidos e notas.
134
+ - Espere o builder aprovar.
135
+ - Insira a task no roadmap.md na fase correta, com o proximo TASK number disponivel.
136
+ - So entao implemente.
137
+ 4. Ao concluir, marque [x] na task do roadmap.md. O checkin sincroniza o progresso automaticamente.
138
+ `;
139
+ const CURSOR_RULES = `You are working on a project that follows the Product Builder 19-skill pipeline.
140
+ The refine MCP server is connected. Use its tools:
141
+ - Call refine_checkin at session start and after significant file changes.
142
+ - Call refine_complete_skill when a phase is done.
143
+ - Call refine_get_prompt before starting a new skill.
144
+ - Always tell the builder which skill they're on and what's next.
145
+
146
+ ROADMAP-FIRST RULE:
147
+ When the builder asks to create, fix or add anything:
148
+ 1. Check docs/roadmap.md for an existing task.
149
+ 2. If none exists, propose a task (title, complexity, files, notes) and wait for approval.
150
+ 3. Insert the task in roadmap.md before writing any code.
151
+ 4. After completing, mark [x] in roadmap.md. The MCP checkin syncs progress automatically.
152
+ `;
153
+ // --- Lovable Knowledge text (TASK-088F) ---
154
+ function printLovableKnowledgeInstructions() {
155
+ const text = generateLovableKnowledgeText();
156
+ console.log("");
157
+ console.log(" Lovable nao le AGENTS.md, entao cole o texto abaixo em:");
158
+ console.log(" Settings > Knowledge (limite: 10.000 chars)");
159
+ console.log("");
160
+ console.log(" --- INICIO DO TEXTO ---");
161
+ console.log(text);
162
+ console.log(" --- FIM DO TEXTO ---");
163
+ console.log("");
164
+ // Tentar copiar pro clipboard
165
+ try {
166
+ if (process.platform === "darwin") {
167
+ execSync("pbcopy", { input: text });
168
+ console.log(" Texto copiado pro clipboard!");
169
+ }
170
+ else if (process.platform === "linux") {
171
+ execSync("xclip -selection clipboard", { input: text });
172
+ console.log(" Texto copiado pro clipboard!");
173
+ }
174
+ }
175
+ catch {
176
+ // Clipboard nao disponivel, ok
177
+ }
178
+ console.log("");
179
+ }
180
+ function generateLovableKnowledgeText() {
181
+ // Versao compacta das regras, otimizada pro limite de 10k chars do Lovable
182
+ return `# refine.build — Product Builder Pipeline
183
+
184
+ Este projeto segue o pipeline de 13 skills do Product Builder (refine.build).
185
+
186
+ ## Regras
187
+
188
+ 1. Antes de criar algo, verifique docs/roadmap.md pra tasks existentes.
189
+ 2. Se nao existe task, proponha: titulo, complexidade, arquivos, notas. Espere aprovacao.
190
+ 3. Insira a task no roadmap.md antes de codar.
191
+ 4. Ao concluir, marque [x] na task do roadmap.md.
192
+
193
+ ## Skills do Pipeline (ordem)
194
+
195
+ 1. Product Strategy — Coleta de ideia, validacao, hook cycle
196
+ 2. Identity — Nome, personalidade, tom visual
197
+ 3. Design System — Tokens, cores, tipografia, componentes
198
+ 4. Page Builder — Construir telas seguindo specs do PRD
199
+ 5. Feature Dev — Conectar backend, CRUD, funcionalidades
200
+ 6. Quality Auditor — Testes, responsividade, schema sync
201
+ 7. Ship — Deploy, seguranca, performance, pre-launch
202
+
203
+ ## Convenções
204
+
205
+ - Imports: usar @/ alias pra src/
206
+ - Styling: apenas tokens semanticos do design system
207
+ - Componentes: shadcn/ui como base
208
+ - Backend: Convex (mutations/queries). Auth check em tudo
209
+ - Testes: Vitest. Testar logica, nao UI
210
+ `;
211
+ }
212
+ // --- Readline helper ---
213
+ function ask(rl, question) {
214
+ return new Promise((resolve) => {
215
+ rl.question(question, (answer) => resolve(answer.trim()));
216
+ });
217
+ }
218
+ // --- Main ---
219
+ async function main() {
220
+ const cwd = process.cwd();
221
+ const isWindows = process.platform === "win32";
222
+ console.log("");
223
+ console.log(" refine.build — Setup MCP");
224
+ console.log(" ========================");
225
+ console.log("");
226
+ const rl = createInterface({
227
+ input: process.stdin,
228
+ output: process.stdout,
229
+ });
230
+ // 1. Token
231
+ let token = "";
232
+ const argIndex = process.argv.indexOf("--token");
233
+ if (argIndex !== -1 && process.argv[argIndex + 1]) {
234
+ token = process.argv[argIndex + 1];
235
+ console.log(` Token: ${token.slice(0, 8)}...`);
236
+ }
237
+ else {
238
+ console.log(" Gere seu token em: https://refine.build/account/mcp");
239
+ console.log("");
240
+ token = await ask(rl, " Cole seu token: ");
241
+ if (!token) {
242
+ console.log("\n Token obrigatorio. Abortando.");
243
+ rl.close();
244
+ process.exit(1);
245
+ }
246
+ }
247
+ // 2. Detectar IDE
248
+ const detected = detectIDE();
249
+ console.log(`\n IDE detectado: ${detected.label}`);
250
+ let ide = detected.ide;
251
+ if (ide === "unknown") {
252
+ console.log(" Nao consegui detectar automaticamente.");
253
+ console.log(" 1) Claude Code");
254
+ console.log(" 2) Cursor");
255
+ console.log(" 3) Windsurf");
256
+ console.log(" 4) Codex (OpenAI)");
257
+ console.log(" 5) Gemini CLI / Antigravity");
258
+ console.log(" 6) Replit");
259
+ console.log(" 7) Lovable");
260
+ const choice = await ask(rl, "\n Qual IDE? (1-7): ");
261
+ const ideMap = {
262
+ "1": "claude-code",
263
+ "2": "cursor",
264
+ "3": "windsurf",
265
+ "4": "codex",
266
+ "5": "gemini",
267
+ "6": "replit",
268
+ "7": "lovable",
269
+ };
270
+ ide = ideMap[choice] ?? "unknown";
271
+ if (ide === "unknown") {
272
+ console.log("\n Opcao invalida. Abortando.");
273
+ rl.close();
274
+ process.exit(1);
275
+ }
276
+ }
277
+ // 3. Gerar config
278
+ console.log("");
279
+ switch (ide) {
280
+ case "claude-code": {
281
+ const cmd = generateClaudeCodeCommand(token);
282
+ console.log(" Execute este comando no terminal:");
283
+ console.log("");
284
+ console.log(` ${cmd}`);
285
+ console.log("");
286
+ break;
287
+ }
288
+ case "cursor": {
289
+ const configPath = join(cwd, ".cursor", "mcp.json");
290
+ const config = generateCursorConfig(token);
291
+ const shouldWrite = await ask(rl, ` Criar ${configPath}? (s/n): `);
292
+ if (shouldWrite.toLowerCase() === "s") {
293
+ mkdirSync(join(cwd, ".cursor"), { recursive: true });
294
+ if (existsSync(configPath)) {
295
+ console.log(` Arquivo ja existe. Adicione manualmente:`);
296
+ console.log("");
297
+ console.log(config);
298
+ }
299
+ else {
300
+ writeFileSync(configPath, config, "utf-8");
301
+ console.log(` Criado: ${configPath}`);
302
+ }
303
+ }
304
+ else {
305
+ console.log("\n Adicione ao .cursor/mcp.json:");
306
+ console.log("");
307
+ console.log(config);
308
+ }
309
+ console.log("");
310
+ break;
311
+ }
312
+ case "windsurf": {
313
+ const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
314
+ const configPath = join(home, ".codeium", "windsurf", "mcp_config.json");
315
+ const config = isWindows ? generateWindowsConfig(token) : generateWindsurfConfig(token);
316
+ console.log(` Adicione ao ${configPath}:`);
317
+ console.log("");
318
+ console.log(config);
319
+ console.log("");
320
+ break;
321
+ }
322
+ case "codex": {
323
+ // Codex usa AGENTS.md (gerado no step 4) + nao suporta MCP nativo
324
+ console.log(" Codex le o AGENTS.md automaticamente (gerado no proximo passo).");
325
+ console.log(" MCP nao suportado nativamente pelo Codex — regras via AGENTS.md.");
326
+ console.log("");
327
+ break;
328
+ }
329
+ case "gemini": {
330
+ console.log(" Gemini CLI le o AGENTS.md automaticamente.");
331
+ console.log("");
332
+ break;
333
+ }
334
+ case "replit": {
335
+ console.log(" Replit suporta MCP nativo.");
336
+ console.log(" Va em: Integrations > MCP Servers > Add MCP server");
337
+ console.log(` Nome: refine`);
338
+ console.log(` URL: https://mcp.refine.build/sse?token=${token}`);
339
+ console.log("");
340
+ console.log(" Replit Agent tambem le o AGENTS.md (gerado no proximo passo).");
341
+ console.log("");
342
+ break;
343
+ }
344
+ case "lovable": {
345
+ console.log(" Lovable suporta MCP nativo (planos pagos).");
346
+ console.log(" Va em: Settings > Connectors > Personal Connectors > New MCP server");
347
+ console.log(` Nome: refine`);
348
+ console.log(` URL: https://mcp.refine.build/sse?token=${token}`);
349
+ console.log(" Auth: Bearer token");
350
+ console.log("");
351
+ console.log(" Lovable NAO le AGENTS.md. Cole as regras em Project Knowledge:");
352
+ printLovableKnowledgeInstructions();
353
+ break;
354
+ }
355
+ }
356
+ // 4. Gerar AGENTS.md (padrao universal)
357
+ const agentsMdPath = join(cwd, "AGENTS.md");
358
+ let rulesCreated = false;
359
+ if (!existsSync(agentsMdPath)) {
360
+ writeFileSync(agentsMdPath, AGENTS_MD_CONTENT, "utf-8");
361
+ console.log(" Criado: AGENTS.md (padrao universal, lido por todos os agentes)");
362
+ rulesCreated = true;
363
+ }
364
+ else {
365
+ console.log(" AGENTS.md ja existe (nao sobrescrito).");
366
+ }
367
+ // 5. Copiar regras IDE-specific como complemento
368
+ const claudeMdPath = join(cwd, "CLAUDE.md");
369
+ const cursorRulesPath = join(cwd, ".cursorrules");
370
+ const windsurfRulesPath = join(cwd, ".windsurfrules");
371
+ if (!existsSync(claudeMdPath)) {
372
+ writeFileSync(claudeMdPath, CLAUDE_MD_RULES, "utf-8");
373
+ console.log(" Criado: CLAUDE.md");
374
+ rulesCreated = true;
375
+ }
376
+ else {
377
+ console.log(" CLAUDE.md ja existe (nao sobrescrito).");
378
+ }
379
+ if (ide === "cursor" && !existsSync(cursorRulesPath)) {
380
+ writeFileSync(cursorRulesPath, CURSOR_RULES, "utf-8");
381
+ console.log(" Criado: .cursorrules");
382
+ rulesCreated = true;
383
+ }
384
+ if (ide === "windsurf" && !existsSync(windsurfRulesPath)) {
385
+ writeFileSync(windsurfRulesPath, CURSOR_RULES, "utf-8");
386
+ console.log(" Criado: .windsurfrules");
387
+ rulesCreated = true;
388
+ }
389
+ // Gemini: GEMINI.md + .agent/rules/refine.md
390
+ if (ide === "gemini") {
391
+ const geminiMdPath = join(cwd, "GEMINI.md");
392
+ if (!existsSync(geminiMdPath)) {
393
+ writeFileSync(geminiMdPath, AGENTS_MD_CONTENT, "utf-8");
394
+ console.log(" Criado: GEMINI.md");
395
+ rulesCreated = true;
396
+ }
397
+ const agentRulesDir = join(cwd, ".agent", "rules");
398
+ const agentRulePath = join(agentRulesDir, "refine.md");
399
+ if (!existsSync(agentRulePath)) {
400
+ mkdirSync(agentRulesDir, { recursive: true });
401
+ writeFileSync(agentRulePath, AGENTS_MD_CONTENT, "utf-8");
402
+ console.log(" Criado: .agent/rules/refine.md");
403
+ rulesCreated = true;
404
+ }
405
+ }
406
+ // Replit: replit.md
407
+ if (ide === "replit") {
408
+ const replitMdPath = join(cwd, "replit.md");
409
+ if (!existsSync(replitMdPath)) {
410
+ writeFileSync(replitMdPath, AGENTS_MD_CONTENT, "utf-8");
411
+ console.log(" Criado: replit.md");
412
+ rulesCreated = true;
413
+ }
414
+ }
415
+ // 6. Confirmar
416
+ console.log("");
417
+ console.log(" ========================");
418
+ console.log(" MCP configurado!");
419
+ if (rulesCreated) {
420
+ console.log(" Regras do pipeline copiadas pro projeto.");
421
+ }
422
+ console.log(" A IA do seu IDE agora sincroniza com o refine.build.");
423
+ console.log("");
424
+ rl.close();
425
+ }
426
+ main().catch((error) => {
427
+ console.error("Erro no setup:", error);
428
+ process.exit(1);
429
+ });
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Tool refine_checkin: escaneia file tree do builder e detecta skill ativa.
3
+ * Chama automaticamente no inicio de cada sessao.
4
+ */
5
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
6
+ export declare function registerCheckinTool(server: McpServer): void;
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Tool refine_checkin: escaneia file tree do builder e detecta skill ativa.
3
+ * Chama automaticamente no inicio de cada sessao.
4
+ */
5
+ import { z } from "zod";
6
+ import { detectSkill, scanFileTree } from "../detection/file-tree.js";
7
+ import { apiPost } from "../utils/api.js";
8
+ export function registerCheckinTool(server) {
9
+ server.registerTool("refine_checkin", {
10
+ description: "Escaneia o projeto do builder e detecta a etapa ativa no fluxo guiado do refine.build. Chame no inicio de cada sessao.",
11
+ annotations: {
12
+ readOnlyHint: false,
13
+ destructiveHint: false,
14
+ idempotentHint: true,
15
+ openWorldHint: true,
16
+ },
17
+ inputSchema: z.object({
18
+ projectId: z.string().optional().describe("ID do projeto no refine.build (opcional)"),
19
+ }),
20
+ }, async ({ projectId }) => {
21
+ const cwd = process.cwd();
22
+ // 1. Scan file tree
23
+ const summary = await scanFileTree(cwd);
24
+ // 2. Detect skill
25
+ const detectedSkill = detectSkill(summary);
26
+ // 3. POST pro backend
27
+ const response = await apiPost("/api/mcp/checkin", {
28
+ projectId,
29
+ fileTreeSummary: summary,
30
+ detectedSkill,
31
+ });
32
+ if (!response.ok || !response.data) {
33
+ return {
34
+ content: [
35
+ {
36
+ type: "text",
37
+ text: `Erro no checkin: ${response.error ?? "Sem resposta do servidor"}`,
38
+ },
39
+ ],
40
+ };
41
+ }
42
+ const d = response.data;
43
+ if (d.error) {
44
+ return {
45
+ content: [
46
+ {
47
+ type: "text",
48
+ text: `${d.error}${d.hint ? `. ${d.hint}` : ""}`,
49
+ },
50
+ ],
51
+ };
52
+ }
53
+ // 4. Formatar resposta pra IA do IDE
54
+ const lines = [
55
+ `Etapa ativa: ${d.skillName} (fase ${d.skillPhase})`,
56
+ `O que fazer: ${d.skillDescription}`,
57
+ d.nextSkill ? `Proxima etapa: ${d.nextSkill}` : "Ultima etapa do fluxo!",
58
+ `Progresso: ${d.progressPercent}% (${d.completedSkills}/${d.totalSkills} etapas)`,
59
+ `Projeto: ${d.projectId}`,
60
+ "",
61
+ `Deteccao local: ${detectedSkill} | Scan: ${summary.pages.length} paginas, ${summary.tests.length} testes, ${summary.mutations.length} mutations, ${summary.cssVarCount} CSS vars`,
62
+ ];
63
+ // Adicionar progresso do roadmap.md se disponivel
64
+ if (summary.roadmapTasks) {
65
+ const rt = summary.roadmapTasks;
66
+ const pct = rt.total > 0 ? Math.round((rt.done / rt.total) * 100) : 0;
67
+ lines.push(`Roadmap: ${rt.done}/${rt.total} tasks (${pct}%)`);
68
+ }
69
+ const text = lines.join("\n");
70
+ return { content: [{ type: "text", text }] };
71
+ });
72
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Tool refine_complete_skill: marca skill ativa como concluida e avanca pro proximo.
3
+ * Usar quando o builder diz "terminei" ou quando a IA detecta que a skill foi concluida.
4
+ */
5
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
6
+ export declare function registerCompleteSkillTool(server: McpServer): void;
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Tool refine_complete_skill: marca skill ativa como concluida e avanca pro proximo.
3
+ * Usar quando o builder diz "terminei" ou quando a IA detecta que a skill foi concluida.
4
+ */
5
+ import { z } from "zod";
6
+ import { apiPost } from "../utils/api.js";
7
+ export function registerCompleteSkillTool(server) {
8
+ server.registerTool("refine_complete_skill", {
9
+ description: "Marca a etapa ativa como concluida e avanca pra proxima. Use quando o builder completar uma etapa no IDE.",
10
+ annotations: {
11
+ readOnlyHint: false,
12
+ destructiveHint: false,
13
+ idempotentHint: false,
14
+ openWorldHint: true,
15
+ },
16
+ inputSchema: z.object({
17
+ skillId: z.string().describe("ID da skill a completar (ex: 'page-builder', 'onboarding')"),
18
+ projectId: z.string().optional().describe("ID do projeto (opcional, usa o mais recente)"),
19
+ evidence: z
20
+ .array(z.string())
21
+ .optional()
22
+ .describe("Lista de arquivos criados/modificados como evidencia (opcional)"),
23
+ }),
24
+ }, async ({ skillId, projectId, evidence }) => {
25
+ const body = { skillId };
26
+ if (projectId)
27
+ body.projectId = projectId;
28
+ if (evidence)
29
+ body.evidence = evidence;
30
+ const response = await apiPost("/api/mcp/complete-skill", body);
31
+ if (!response.ok || !response.data) {
32
+ return {
33
+ content: [
34
+ {
35
+ type: "text",
36
+ text: `Erro ao completar skill: ${response.error ?? "Sem resposta do servidor"}`,
37
+ },
38
+ ],
39
+ };
40
+ }
41
+ const d = response.data;
42
+ if (d.error) {
43
+ return {
44
+ content: [{ type: "text", text: `Erro: ${d.error}` }],
45
+ };
46
+ }
47
+ const lines = [
48
+ `Skill concluida: ${d.completedSkill}`,
49
+ d.nextSkill
50
+ ? `Proxima skill: ${d.nextSkill}`
51
+ : "Pipeline completo! Todas as skills foram concluidas.",
52
+ `Progresso: ${d.progressPercent}%`,
53
+ ];
54
+ return { content: [{ type: "text", text: lines.join("\n") }] };
55
+ });
56
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Tool refine_get_prompt: retorna system prompt completo de uma skill.
3
+ * Tenta composicao (POST compose-skill com contexto local) primeiro,
4
+ * fallback pro GET skill-prompt se composicao falhar.
5
+ */
6
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
7
+ export declare function registerGetPromptTool(server: McpServer): void;
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Tool refine_get_prompt: retorna system prompt completo de uma skill.
3
+ * Tenta composicao (POST compose-skill com contexto local) primeiro,
4
+ * fallback pro GET skill-prompt se composicao falhar.
5
+ */
6
+ import { z } from "zod";
7
+ import { extractProjectContext } from "../detection/context-extractor.js";
8
+ import { apiGet, apiPost } from "../utils/api.js";
9
+ export function registerGetPromptTool(server) {
10
+ server.registerTool("refine_get_prompt", {
11
+ description: "Retorna o system prompt completo de uma etapa do fluxo. Use como instrucao pra conduzir a etapa no IDE do builder.",
12
+ annotations: {
13
+ readOnlyHint: true,
14
+ destructiveHint: false,
15
+ idempotentHint: true,
16
+ openWorldHint: true,
17
+ },
18
+ inputSchema: z.object({
19
+ skill: z.string().describe("ID da skill (ex: 'page-builder', 'onboarding', 'motion')"),
20
+ projectId: z
21
+ .string()
22
+ .optional()
23
+ .describe("ID do projeto pra injetar contexto do plano de produto (opcional)"),
24
+ }),
25
+ }, async ({ skill, projectId }) => {
26
+ // 1. Tentar composicao
27
+ const context = await extractProjectContext(process.cwd());
28
+ const composeBody = { skillName: skill, projectId, context };
29
+ const composed = await apiPost("/api/mcp/compose-skill", composeBody);
30
+ if (composed.ok && composed.data?.prompt) {
31
+ const d = composed.data;
32
+ const lines = [
33
+ `Skill: ${d.skillName}`,
34
+ `Fonte: composed (template v${d.templateVersion}, ${d.craftRulesCount} craft rules)`,
35
+ "",
36
+ "---",
37
+ "",
38
+ d.prompt,
39
+ ];
40
+ return { content: [{ type: "text", text: lines.join("\n") }] };
41
+ }
42
+ // 2. Fallback: GET prompt cru
43
+ const params = { skill };
44
+ if (projectId)
45
+ params.projectId = projectId;
46
+ const response = await apiGet("/api/mcp/skill-prompt", params);
47
+ if (!response.ok || !response.data) {
48
+ return {
49
+ content: [
50
+ {
51
+ type: "text",
52
+ text: `Erro ao buscar prompt: ${composed.error ?? response.error ?? "Sem resposta do servidor"}`,
53
+ },
54
+ ],
55
+ };
56
+ }
57
+ const d = response.data;
58
+ const lines = [
59
+ `Skill: ${d.skillName} (${d.skillId})`,
60
+ `Fonte: fallback (${d.source})`,
61
+ "",
62
+ "---",
63
+ "",
64
+ d.prompt,
65
+ ];
66
+ return { content: [{ type: "text", text: lines.join("\n") }] };
67
+ });
68
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Tool refine_get_skill: retorna skill ativa + metadata + contexto PRD.
3
+ * A IA do IDE usa isso pra informar o builder onde esta no pipeline.
4
+ */
5
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
6
+ export declare function registerGetSkillTool(server: McpServer): void;