project-mcp-server 2.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 (46) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +335 -0
  3. package/dist/config.d.ts +15 -0
  4. package/dist/config.js +38 -0
  5. package/dist/config.js.map +1 -0
  6. package/dist/index.d.ts +2 -0
  7. package/dist/index.js +28 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/scanner/actions.d.ts +9 -0
  10. package/dist/scanner/actions.js +77 -0
  11. package/dist/scanner/actions.js.map +1 -0
  12. package/dist/scanner/cache.d.ts +4 -0
  13. package/dist/scanner/cache.js +34 -0
  14. package/dist/scanner/cache.js.map +1 -0
  15. package/dist/scanner/components.d.ts +17 -0
  16. package/dist/scanner/components.js +74 -0
  17. package/dist/scanner/components.js.map +1 -0
  18. package/dist/scanner/prisma.d.ts +17 -0
  19. package/dist/scanner/prisma.js +75 -0
  20. package/dist/scanner/prisma.js.map +1 -0
  21. package/dist/scanner/routes.d.ts +11 -0
  22. package/dist/scanner/routes.js +98 -0
  23. package/dist/scanner/routes.js.map +1 -0
  24. package/dist/setup.d.ts +10 -0
  25. package/dist/setup.js +289 -0
  26. package/dist/setup.js.map +1 -0
  27. package/dist/tools/env/index.d.ts +2 -0
  28. package/dist/tools/env/index.js +152 -0
  29. package/dist/tools/env/index.js.map +1 -0
  30. package/dist/tools/generate/index.d.ts +2 -0
  31. package/dist/tools/generate/index.js +320 -0
  32. package/dist/tools/generate/index.js.map +1 -0
  33. package/dist/tools/project/index.d.ts +2 -0
  34. package/dist/tools/project/index.js +193 -0
  35. package/dist/tools/project/index.js.map +1 -0
  36. package/package.json +35 -0
  37. package/skills/commit.md +109 -0
  38. package/skills/infra.md +218 -0
  39. package/skills/nextauth.md +256 -0
  40. package/skills/nextjs.md +262 -0
  41. package/skills/prisma.md +281 -0
  42. package/skills/project-intelligence.SKILL.md +141 -0
  43. package/skills/security.md +353 -0
  44. package/skills/shadcn.md +299 -0
  45. package/skills/testing.md +188 -0
  46. package/skills/zod.md +253 -0
@@ -0,0 +1,152 @@
1
+ import { z } from "zod";
2
+ import { exec } from "node:child_process";
3
+ import { promisify } from "node:util";
4
+ import { access } from "node:fs/promises";
5
+ import { join } from "node:path";
6
+ import { config } from "../../config.js";
7
+ const execAsync = promisify(exec);
8
+ async function run(cmd, cwd) {
9
+ try {
10
+ const { stdout, stderr } = await execAsync(cmd, {
11
+ cwd: cwd ?? config.projectRoot,
12
+ timeout: 30_000
13
+ });
14
+ return { ok: true, output: (stdout + stderr).trim() };
15
+ }
16
+ catch (err) {
17
+ const e = err;
18
+ return {
19
+ ok: false,
20
+ output: ((e.stdout ?? "") + (e.stderr ?? "") + (e.message ?? "")).trim()
21
+ };
22
+ }
23
+ }
24
+ export function registerEnvTools(server) {
25
+ // ─── env_status ────────────────────────────────────────────────────────────
26
+ server.registerTool("env_status", {
27
+ title: "Estado del entorno de desarrollo",
28
+ description: `Verifica el estado del entorno: Docker, .env.local y herramientas de desarrollo.
29
+ Llamar al inicio de una sesión para detectar problemas antes de codear.
30
+
31
+ Returns: estado de cada servicio con detalles de errores si los hay.`,
32
+ inputSchema: z.object({}).strict(),
33
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: false, openWorldHint: false }
34
+ }, async () => {
35
+ const [dockerPs, pnpmInstalled] = await Promise.all([
36
+ run("docker compose ps --format json"),
37
+ run("pnpm --version")
38
+ ]);
39
+ // Verificar .env.local
40
+ const envPath = join(config.projectRoot, ".env.local");
41
+ let envExists = false;
42
+ try {
43
+ await access(envPath);
44
+ envExists = true;
45
+ }
46
+ catch { /* no existe */ }
47
+ // Parsear docker compose status
48
+ let dockerServices = [];
49
+ if (dockerPs.ok && dockerPs.output) {
50
+ try {
51
+ dockerServices = dockerPs.output
52
+ .split("\n")
53
+ .filter(Boolean)
54
+ .map(line => JSON.parse(line))
55
+ .map(s => ({ name: s.Name, status: s.Status }));
56
+ }
57
+ catch { /* format varies */ }
58
+ }
59
+ const status = {
60
+ ok: envExists,
61
+ docker: { running: dockerPs.ok, services: dockerServices },
62
+ env_file: { exists: envExists, path: ".env.local" },
63
+ pnpm: { ok: pnpmInstalled.ok, version: pnpmInstalled.output }
64
+ };
65
+ const lines = [
66
+ `## Estado del entorno`,
67
+ ``,
68
+ dockerPs.ok ? `✓ Docker Compose activo (${dockerServices.length} servicios)` : `✗ Docker Compose no responde`,
69
+ ...dockerServices.map(s => ` ${s.status.includes("Up") ? "↑" : "↓"} ${s.name}: ${s.status}`),
70
+ envExists ? `✓ .env.local presente` : `✗ .env.local no encontrado`,
71
+ pnpmInstalled.ok ? `✓ pnpm ${pnpmInstalled.output}` : `✗ pnpm no disponible`,
72
+ ];
73
+ return {
74
+ content: [{ type: "text", text: lines.join("\n") }],
75
+ structuredContent: status
76
+ };
77
+ });
78
+ // ─── env_run_check ─────────────────────────────────────────────────────────
79
+ server.registerTool("env_run_check", {
80
+ title: "Ejecutar verificaciones de calidad",
81
+ description: `Ejecuta type-check, lint o tests en el proyecto y devuelve el resultado.
82
+ Usar antes de hacer commit o cuando el agente necesita verificar
83
+ que los cambios no rompieron nada.
84
+
85
+ Args:
86
+ - check: qué verificación ejecutar
87
+ - scope: ruta específica a verificar (opcional, ej: "src/app/dashboard")
88
+
89
+ Returns: resultado del comando con errores y warnings.`,
90
+ inputSchema: z.object({
91
+ check: z.enum(["typecheck", "lint", "test", "build"]),
92
+ scope: z.string().optional()
93
+ .describe("Ruta específica a verificar (relativa al proyecto)")
94
+ }).strict(),
95
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: false, openWorldHint: false }
96
+ }, async ({ check, scope }) => {
97
+ const commands = {
98
+ typecheck: "pnpm tsc --noEmit",
99
+ lint: scope ? `pnpm eslint ${scope}` : "pnpm lint",
100
+ test: scope ? `pnpm test ${scope}` : "pnpm test --run",
101
+ build: "pnpm build"
102
+ };
103
+ const cmd = commands[check] ?? commands["typecheck"];
104
+ const result = await run(cmd);
105
+ const lines = [
106
+ `## ${check} ${result.ok ? "✓" : "✗"}`,
107
+ ``,
108
+ result.output || "(sin output)"
109
+ ];
110
+ if (!result.ok) {
111
+ lines.push("", `El check falló. Revisá los errores antes de continuar.`);
112
+ }
113
+ return {
114
+ content: [{ type: "text", text: lines.join("\n") }],
115
+ structuredContent: { check, ok: result.ok, output: result.output }
116
+ };
117
+ });
118
+ // ─── env_prisma_status ─────────────────────────────────────────────────────
119
+ server.registerTool("env_prisma_status", {
120
+ title: "Estado de migraciones de Prisma",
121
+ description: `Verifica si hay migraciones pendientes y el estado actual de la DB.
122
+ Llamar antes de arrancar trabajo con la base de datos o cuando
123
+ hay cambios en los schemas de Prisma.
124
+
125
+ Returns: migraciones aplicadas, pendientes y estado de conexión.`,
126
+ inputSchema: z.object({}).strict(),
127
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: false, openWorldHint: false }
128
+ }, async () => {
129
+ const result = await run("pnpm prisma migrate status");
130
+ const hasPending = result.output.includes("following migration") &&
131
+ result.output.includes("have not yet been applied");
132
+ const isInSync = result.output.includes("Database schema is up to date");
133
+ const lines = [
134
+ `## Estado de Prisma`,
135
+ ``,
136
+ isInSync ? `✓ Schema sincronizado — sin migraciones pendientes` :
137
+ hasPending ? `✗ Hay migraciones pendientes — correr: pnpm prisma migrate dev` :
138
+ `? Estado desconocido`,
139
+ ``,
140
+ result.output
141
+ ];
142
+ return {
143
+ content: [{ type: "text", text: lines.join("\n") }],
144
+ structuredContent: {
145
+ inSync: isInSync,
146
+ hasPending,
147
+ output: result.output
148
+ }
149
+ };
150
+ });
151
+ }
152
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/env/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerGenerateTools(server: McpServer): void;
@@ -0,0 +1,320 @@
1
+ import { z } from "zod";
2
+ import { scanPrismaSchemas } from "../../scanner/prisma.js";
3
+ function toPascalCase(str) {
4
+ return str.replace(/(^\w|[-_\s]\w)/g, m => m.replace(/[-_\s]/, "").toUpperCase());
5
+ }
6
+ function toCamelCase(str) {
7
+ const pascal = toPascalCase(str);
8
+ return pascal.charAt(0).toLowerCase() + pascal.slice(1);
9
+ }
10
+ export function registerGenerateTools(server) {
11
+ // ─── generate_action ───────────────────────────────────────────────────────
12
+ server.registerTool("generate_action", {
13
+ title: "Generar Server Action",
14
+ description: `Genera una Server Action siguiendo los patrones del proyecto:
15
+ - "use server" al inicio
16
+ - Validación con Zod 4 usando safeParse
17
+ - Autenticación con auth() de NextAuth si se requiere
18
+ - Tipos de retorno explícitos
19
+ - Revalidación de cache si aplica
20
+
21
+ Args:
22
+ - entity: nombre de la entidad (ej: "user", "post", "invoice")
23
+ - operation: tipo de operación CRUD
24
+ - with_auth: si requiere sesión autenticada (default: true)
25
+ - prisma_schema: en qué schema de Prisma está la entidad
26
+
27
+ Returns: código TypeScript listo para copiar a server/actions/[entity].ts`,
28
+ inputSchema: z.object({
29
+ entity: z.string().min(1).describe("Nombre de la entidad en singular (ej: 'user')"),
30
+ operation: z.enum(["create", "update", "delete", "get", "list"]),
31
+ with_auth: z.boolean().default(true),
32
+ prisma_schema: z.enum(["auth", "rbac", "audit", "base"]).default("base")
33
+ }).strict(),
34
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false }
35
+ }, async ({ entity, operation, with_auth, prisma_schema }) => {
36
+ const pascal = toPascalCase(entity);
37
+ const camel = toCamelCase(entity);
38
+ // Buscar el modelo en Prisma para conocer los campos
39
+ const models = await scanPrismaSchemas();
40
+ const model = models.find(m => m.name.toLowerCase() === entity.toLowerCase());
41
+ // Campos de datos (no relaciones, no id, no timestamps)
42
+ const dataFields = model?.fields.filter(f => !f.isRelation && f.name !== "id" &&
43
+ f.name !== "createdAt" && f.name !== "updatedAt") ?? [];
44
+ const zodFields = dataFields.length > 0
45
+ ? dataFields.map(f => {
46
+ const base = f.type === "String" ? "z.string().min(1)" :
47
+ f.type === "Int" ? "z.number().int()" :
48
+ f.type === "Boolean" ? "z.boolean()" :
49
+ f.type === "DateTime" ? "z.coerce.date()" : "z.string()";
50
+ return ` ${f.name}: ${f.isOptional ? base + ".optional()" : base}`;
51
+ }).join(",\n")
52
+ : ` // Agregá los campos de ${pascal} acá`;
53
+ const schemaImport = prisma_schema === "base"
54
+ ? `import { prismaPostgres } from "@/lib/db/postgres"`
55
+ : `import { prismaPostgres } from "@/lib/db/postgres"`;
56
+ const authBlock = with_auth ? `
57
+ const session = await auth()
58
+ if (!session?.user) return { success: false, error: "No autenticado" }
59
+ ` : "";
60
+ const authImport = with_auth ? `\nimport { auth } from "@/lib/auth"` : "";
61
+ let body;
62
+ switch (operation) {
63
+ case "create":
64
+ body = `
65
+ const parsed = ${pascal}Schema.safeParse({
66
+ ${dataFields.map(f => ` ${f.name}: formData.get("${f.name}")`).join(",\n") || ` // extraer campos de formData`}
67
+ })
68
+ if (!parsed.success) return { success: false, error: parsed.error.flatten().fieldErrors }
69
+
70
+ const ${camel} = await prismaPostgres.${camel}.create({ data: parsed.data })
71
+ revalidateTag("${camel}s")
72
+ return { success: true, data: ${camel} }`;
73
+ break;
74
+ case "update":
75
+ body = `
76
+ const parsed = ${pascal}Schema.partial().safeParse({
77
+ ${dataFields.map(f => ` ${f.name}: formData.get("${f.name}")`).join(",\n") || ` // extraer campos de formData`}
78
+ })
79
+ if (!parsed.success) return { success: false, error: parsed.error.flatten().fieldErrors }
80
+
81
+ const ${camel} = await prismaPostgres.${camel}.update({
82
+ where: { id },
83
+ data: parsed.data
84
+ })
85
+ revalidateTag("${camel}s")
86
+ return { success: true, data: ${camel} }`;
87
+ break;
88
+ case "delete":
89
+ body = `
90
+ await prismaPostgres.${camel}.delete({ where: { id } })
91
+ revalidateTag("${camel}s")
92
+ return { success: true }`;
93
+ break;
94
+ case "get":
95
+ body = `
96
+ const ${camel} = await prismaPostgres.${camel}.findUnique({
97
+ where: { id },
98
+ select: {
99
+ id: true,
100
+ ${dataFields.map(f => ` ${f.name}: true`).join(",\n") || " // seleccionar campos necesarios"}
101
+ }
102
+ })
103
+ if (!${camel}) return { success: false, error: "${pascal} no encontrado" }
104
+ return { success: true, data: ${camel} }`;
105
+ break;
106
+ case "list":
107
+ body = `
108
+ const ${camel}s = await prismaPostgres.${camel}.findMany({
109
+ select: {
110
+ id: true,
111
+ ${dataFields.slice(0, 4).map(f => ` ${f.name}: true`).join(",\n") || " // seleccionar campos necesarios"}
112
+ },
113
+ orderBy: { ${model?.hasTimestamps ? "createdAt" : "id"}: "desc" },
114
+ take: 50
115
+ })
116
+ return { success: true, data: ${camel}s }`;
117
+ break;
118
+ default:
119
+ body = ` // implementar lógica acá`;
120
+ }
121
+ const params = operation === "update" || operation === "delete" || operation === "get"
122
+ ? `id: string${operation === "update" ? ", formData: FormData" : ""}`
123
+ : operation === "create" ? "formData: FormData" : "";
124
+ const code = `"use server"
125
+
126
+ import { z } from "zod"
127
+ import { revalidateTag } from "next/cache"${authImport}
128
+ ${schemaImport}
129
+
130
+ const ${pascal}Schema = z.object({
131
+ ${zodFields}
132
+ })
133
+
134
+ type ActionResult<T = void> =
135
+ | { success: true; data?: T }
136
+ | { success: false; error: Record<string, string[]> | string }
137
+
138
+ export async function ${operation}${pascal}(${params}): Promise<ActionResult> {${authBlock}${body}
139
+ }`;
140
+ return {
141
+ content: [{ type: "text", text: code }],
142
+ structuredContent: { entity, operation, file: `server/actions/${entity}s.ts` }
143
+ };
144
+ });
145
+ // ─── generate_page ─────────────────────────────────────────────────────────
146
+ server.registerTool("generate_page", {
147
+ title: "Generar página Next.js",
148
+ description: `Genera una página Next.js 16 siguiendo el patrón del proyecto:
149
+ - RSC por defecto
150
+ - Metadata dinámica si necesita SEO
151
+ - Layout con estructura del dashboard si es una ruta protegida
152
+ - Suspense boundaries y loading state
153
+
154
+ Args:
155
+ - path: ruta de la página (ej: "/dashboard/users/[id]")
156
+ - type: tipo de página
157
+ - with_auth: si requiere sesión (agrega redirect si no hay sesión)
158
+
159
+ Returns: código de la página listo para src/app/[ruta]/page.tsx`,
160
+ inputSchema: z.object({
161
+ path: z.string().describe("Ruta de la página (ej: /dashboard/users/[id])"),
162
+ type: z.enum(["list", "detail", "form", "dashboard"]),
163
+ with_auth: z.boolean().default(true),
164
+ with_metadata: z.boolean().default(false)
165
+ }).strict(),
166
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false }
167
+ }, async ({ path: routePath, type, with_auth, with_metadata }) => {
168
+ const segments = routePath.split("/").filter(Boolean);
169
+ const dynamicParams = segments.filter(s => s.startsWith("[") && s.endsWith("]"))
170
+ .map(s => s.slice(1, -1));
171
+ const entity = segments.find(s => !s.startsWith("[") && !s.startsWith("(")) ?? "entity";
172
+ const pascal = toPascalCase(entity.replace(/s$/, "")); // plurals → singular
173
+ const paramsType = dynamicParams.length > 0
174
+ ? `{ params: { ${dynamicParams.map(p => `${p}: string`).join("; ")} } }`
175
+ : "";
176
+ const authBlock = with_auth ? `
177
+ const session = await auth()
178
+ if (!session) redirect("/login")
179
+ ` : "";
180
+ const authImports = with_auth
181
+ ? `import { auth } from "@/lib/auth"\nimport { redirect } from "next/navigation"\n`
182
+ : "";
183
+ const metadataBlock = with_metadata ? `
184
+ export async function generateMetadata({ params }: ${paramsType || "{}"}): Promise<Metadata> {
185
+ // const item = await get${pascal}(params.id)
186
+ return { title: "${pascal}" }
187
+ }
188
+ ` : "";
189
+ const metadataImport = with_metadata ? `import type { Metadata } from "next"\n` : "";
190
+ let body;
191
+ switch (type) {
192
+ case "list":
193
+ body = ` // const items = await prismaPostgres.${entity.toLowerCase()}.findMany({ take: 50 })
194
+
195
+ return (
196
+ <div className="space-y-6">
197
+ <div className="flex items-center justify-between">
198
+ <h1 className="text-2xl font-semibold">${pascal}s</h1>
199
+ {/* <CreateButton /> */}
200
+ </div>
201
+ {/* <${pascal}List items={items} /> */}
202
+ </div>
203
+ )`;
204
+ break;
205
+ case "detail":
206
+ body = ` // const item = await prismaPostgres.${entity.toLowerCase()}.findUnique({
207
+ // where: { id: params.${dynamicParams[0] ?? "id"} }
208
+ // })
209
+ // if (!item) notFound()
210
+
211
+ return (
212
+ <div className="space-y-6">
213
+ <h1 className="text-2xl font-semibold">${pascal}</h1>
214
+ {/* <${pascal}Detail item={item} /> */}
215
+ </div>
216
+ )`;
217
+ break;
218
+ case "form":
219
+ body = ` return (
220
+ <div className="max-w-2xl space-y-6">
221
+ <h1 className="text-2xl font-semibold">Nuevo ${pascal}</h1>
222
+ {/* <Create${pascal}Form /> */}
223
+ </div>
224
+ )`;
225
+ break;
226
+ default:
227
+ body = ` return (
228
+ <div className="space-y-6">
229
+ <h1 className="text-2xl font-semibold">Dashboard</h1>
230
+ </div>
231
+ )`;
232
+ }
233
+ const code = `${metadataImport}${authImports}
234
+ export default async function ${pascal}Page(${paramsType ? `props: ${paramsType}` : ""}) {${authBlock}
235
+ ${body}
236
+ }
237
+ ${metadataBlock}`;
238
+ const fsPath = `src/app${routePath}/page.tsx`;
239
+ return {
240
+ content: [{ type: "text", text: code.trim() }],
241
+ structuredContent: { path: routePath, fsPath, dynamicParams }
242
+ };
243
+ });
244
+ // ─── generate_component ────────────────────────────────────────────────────
245
+ server.registerTool("generate_component", {
246
+ title: "Generar componente React",
247
+ description: `Genera un componente React siguiendo las convenciones del proyecto:
248
+ - RSC por defecto, "use client" solo si se especifica
249
+ - Tipado con TypeScript estricto
250
+ - Usa cn() para merge de clases Tailwind
251
+ - Props interface explícita
252
+
253
+ Args:
254
+ - name: nombre del componente en PascalCase
255
+ - feature: feature a la que pertenece (carpeta en components/)
256
+ - type: tipo de componente`,
257
+ inputSchema: z.object({
258
+ name: z.string().describe("Nombre en PascalCase (ej: 'UserCard', 'InvoiceTable')"),
259
+ feature: z.string().describe("Feature a la que pertenece (ej: 'users', 'dashboard')"),
260
+ type: z.enum(["display", "form", "layout", "interactive"]),
261
+ is_client: z.boolean().default(false)
262
+ .describe("Si necesita 'use client' (hooks, eventos)")
263
+ }).strict(),
264
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false }
265
+ }, async ({ name, feature, type, is_client }) => {
266
+ const clientDirective = is_client ? `"use client"\n\n` : "";
267
+ const propsExample = type === "display"
268
+ ? ` // data: YourDataType`
269
+ : type === "form"
270
+ ? ` // onSubmit?: (data: FormData) => void`
271
+ : type === "interactive"
272
+ ? ` // defaultOpen?: boolean`
273
+ : ` // children: React.ReactNode`;
274
+ const bodyExample = type === "display"
275
+ ? ` <div className={cn("rounded-lg border p-4", className)}>
276
+ {/* contenido */}
277
+ </div>`
278
+ : type === "form"
279
+ ? ` <form className={cn("space-y-4", className)}>
280
+ {/* campos */}
281
+ <Button type="submit">Guardar</Button>
282
+ </form>`
283
+ : type === "interactive"
284
+ ? ` <div className={cn("", className)}>
285
+ {/* estado: {open ? "abierto" : "cerrado"} */}
286
+ </div>`
287
+ : ` <div className={cn("", className)}>
288
+ {children}
289
+ </div>`;
290
+ const imports = type === "form"
291
+ ? `import { Button } from "@/components/ui/button"\n`
292
+ : "";
293
+ const stateExample = (is_client && type === "interactive")
294
+ ? ` const [open, setOpen] = React.useState(false)\n`
295
+ : "";
296
+ const reactImport = (is_client && type === "interactive")
297
+ ? `import * as React from "react"\n`
298
+ : "";
299
+ const code = `${clientDirective}${reactImport}import { cn } from "@/lib/utils"
300
+ ${imports}
301
+ interface ${name}Props {
302
+ ${propsExample}
303
+ className?: string
304
+ ${type === "layout" ? " children: React.ReactNode\n" : ""}
305
+ }
306
+
307
+ export function ${name}({ ${type === "layout" ? "children, " : ""}className }: ${name}Props) {
308
+ ${stateExample}
309
+ return (
310
+ ${bodyExample}
311
+ )
312
+ }`;
313
+ const fsPath = `src/components/${feature}/${name.replace(/([A-Z])/g, (_, l, i) => i > 0 ? `-${l.toLowerCase()}` : l.toLowerCase())}.tsx`;
314
+ return {
315
+ content: [{ type: "text", text: code }],
316
+ structuredContent: { name, feature, fsPath, isClient: is_client }
317
+ };
318
+ });
319
+ }
320
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/generate/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerProjectTools(server: McpServer): void;