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.
- package/LICENSE +21 -0
- package/README.md +335 -0
- package/dist/config.d.ts +15 -0
- package/dist/config.js +38 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +28 -0
- package/dist/index.js.map +1 -0
- package/dist/scanner/actions.d.ts +9 -0
- package/dist/scanner/actions.js +77 -0
- package/dist/scanner/actions.js.map +1 -0
- package/dist/scanner/cache.d.ts +4 -0
- package/dist/scanner/cache.js +34 -0
- package/dist/scanner/cache.js.map +1 -0
- package/dist/scanner/components.d.ts +17 -0
- package/dist/scanner/components.js +74 -0
- package/dist/scanner/components.js.map +1 -0
- package/dist/scanner/prisma.d.ts +17 -0
- package/dist/scanner/prisma.js +75 -0
- package/dist/scanner/prisma.js.map +1 -0
- package/dist/scanner/routes.d.ts +11 -0
- package/dist/scanner/routes.js +98 -0
- package/dist/scanner/routes.js.map +1 -0
- package/dist/setup.d.ts +10 -0
- package/dist/setup.js +289 -0
- package/dist/setup.js.map +1 -0
- package/dist/tools/env/index.d.ts +2 -0
- package/dist/tools/env/index.js +152 -0
- package/dist/tools/env/index.js.map +1 -0
- package/dist/tools/generate/index.d.ts +2 -0
- package/dist/tools/generate/index.js +320 -0
- package/dist/tools/generate/index.js.map +1 -0
- package/dist/tools/project/index.d.ts +2 -0
- package/dist/tools/project/index.js +193 -0
- package/dist/tools/project/index.js.map +1 -0
- package/package.json +35 -0
- package/skills/commit.md +109 -0
- package/skills/infra.md +218 -0
- package/skills/nextauth.md +256 -0
- package/skills/nextjs.md +262 -0
- package/skills/prisma.md +281 -0
- package/skills/project-intelligence.SKILL.md +141 -0
- package/skills/security.md +353 -0
- package/skills/shadcn.md +299 -0
- package/skills/testing.md +188 -0
- package/skills/zod.md +253 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Fernando Secchi
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
# project-mcp-server
|
|
2
|
+
|
|
3
|
+
[](https://github.com/fernandosecchi/project-mcp-server/actions/workflows/ci.yml)
|
|
4
|
+
[](LICENSE)
|
|
5
|
+
[](https://nodejs.org/)
|
|
6
|
+
[](https://modelcontextprotocol.io)
|
|
7
|
+
|
|
8
|
+
MCP server con inteligencia de proyecto para Next.js + Prisma. Dos pasos y listo:
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
# 1. Instalar (una sola vez)
|
|
12
|
+
git clone https://github.com/fernandosecchi/project-mcp-server.git ~/.project-mcp
|
|
13
|
+
cd ~/.project-mcp && npm install && npm run build
|
|
14
|
+
|
|
15
|
+
# 2. Configurar (desde tu proyecto)
|
|
16
|
+
cd /ruta/a/tu-proyecto
|
|
17
|
+
node ~/.project-mcp/dist/setup.js
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
El setup detecta tus agentes (Claude Code, Cursor, Open Code, Gemini CLI, Codex, VS Code), configura el MCP y copia las skills. **Prerequisito**: Node.js 20+.
|
|
21
|
+
|
|
22
|
+
Para actualizar: `cd ~/.project-mcp && git pull && npm install && npm run build`
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Qué es
|
|
27
|
+
|
|
28
|
+
Tres capas de inteligencia para tu agente de IA:
|
|
29
|
+
|
|
30
|
+
- **Inteligencia del proyecto** — escanea rutas, Server Actions, modelos Prisma y componentes en tiempo real
|
|
31
|
+
- **Control del entorno** — verifica Docker, migraciones y ejecuta type-check/lint/test/build
|
|
32
|
+
- **Generación con convenciones propias** — genera código que lee tu schema de Prisma real
|
|
33
|
+
|
|
34
|
+
Sin bases de datos, sin servicios externos. Solo Node.js.
|
|
35
|
+
|
|
36
|
+
Se integra con [Gentleman AI Ecosystem](https://github.com/Gentleman-Programming/gentle-ai) (Engram + SDD + Skills) para memoria persistente y workflow de desarrollo.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Configuración manual
|
|
41
|
+
|
|
42
|
+
Si preferís configurar a mano en vez de usar el setup:
|
|
43
|
+
|
|
44
|
+
### Variables de entorno
|
|
45
|
+
|
|
46
|
+
| Variable | Default | Descripción |
|
|
47
|
+
|---|---|---|
|
|
48
|
+
| `MCP_PROJECT_ROOT` | `process.cwd()` | Raíz del proyecto a analizar |
|
|
49
|
+
|
|
50
|
+
### Claude Code
|
|
51
|
+
|
|
52
|
+
Editá `~/.claude/config.json`:
|
|
53
|
+
|
|
54
|
+
```json
|
|
55
|
+
{
|
|
56
|
+
"mcpServers": {
|
|
57
|
+
"project": {
|
|
58
|
+
"command": "node",
|
|
59
|
+
"args": ["~/.project-mcp/dist/index.js"],
|
|
60
|
+
"env": {
|
|
61
|
+
"MCP_PROJECT_ROOT": "/ruta/absoluta/tu-proyecto"
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Verificar: abrí Claude Code en tu proyecto → `/mcp` → debe aparecer `project` con 10 tools.
|
|
69
|
+
|
|
70
|
+
### Open Code
|
|
71
|
+
|
|
72
|
+
Editá `~/.config/opencode/config.json`:
|
|
73
|
+
|
|
74
|
+
```json
|
|
75
|
+
{
|
|
76
|
+
"mcp": {
|
|
77
|
+
"project": {
|
|
78
|
+
"type": "local",
|
|
79
|
+
"command": "node",
|
|
80
|
+
"args": ["~/.project-mcp/dist/index.js"],
|
|
81
|
+
"env": {
|
|
82
|
+
"MCP_PROJECT_ROOT": "/ruta/absoluta/tu-proyecto"
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Gemini CLI
|
|
90
|
+
|
|
91
|
+
Editá `~/.gemini/config.json`:
|
|
92
|
+
|
|
93
|
+
```json
|
|
94
|
+
{
|
|
95
|
+
"mcpServers": {
|
|
96
|
+
"project": {
|
|
97
|
+
"command": "node",
|
|
98
|
+
"args": ["~/.project-mcp/dist/index.js"],
|
|
99
|
+
"env": {
|
|
100
|
+
"MCP_PROJECT_ROOT": "/ruta/absoluta/tu-proyecto"
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Codex CLI
|
|
108
|
+
|
|
109
|
+
Editá `~/.codex/config.json`:
|
|
110
|
+
|
|
111
|
+
```json
|
|
112
|
+
{
|
|
113
|
+
"mcpServers": {
|
|
114
|
+
"project": {
|
|
115
|
+
"command": "node",
|
|
116
|
+
"args": ["~/.project-mcp/dist/index.js"],
|
|
117
|
+
"env": {
|
|
118
|
+
"MCP_PROJECT_ROOT": "/ruta/absoluta/tu-proyecto"
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Cursor
|
|
126
|
+
|
|
127
|
+
Settings → MCP → Add server:
|
|
128
|
+
|
|
129
|
+
```json
|
|
130
|
+
{
|
|
131
|
+
"project": {
|
|
132
|
+
"command": "node",
|
|
133
|
+
"args": ["~/.project-mcp/dist/index.js"],
|
|
134
|
+
"env": {
|
|
135
|
+
"MCP_PROJECT_ROOT": "/ruta/absoluta/tu-proyecto"
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### VS Code (GitHub Copilot)
|
|
142
|
+
|
|
143
|
+
`.vscode/mcp.json` en el workspace:
|
|
144
|
+
|
|
145
|
+
```json
|
|
146
|
+
{
|
|
147
|
+
"servers": {
|
|
148
|
+
"project": {
|
|
149
|
+
"type": "stdio",
|
|
150
|
+
"command": "node",
|
|
151
|
+
"args": ["~/.project-mcp/dist/index.js"],
|
|
152
|
+
"env": {
|
|
153
|
+
"MCP_PROJECT_ROOT": "${workspaceFolder}"
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## Tools disponibles (10)
|
|
163
|
+
|
|
164
|
+
### Inteligencia del proyecto
|
|
165
|
+
|
|
166
|
+
| Tool | Descripción |
|
|
167
|
+
|---|---|
|
|
168
|
+
| `project_scan` | Mapa completo: rutas, actions, modelos, componentes |
|
|
169
|
+
| `project_routes` | Lista rutas del App Router con rendering, params y métodos |
|
|
170
|
+
| `project_actions` | Lista Server Actions con schema Zod y flags de auth |
|
|
171
|
+
| `project_models` | Lista modelos de Prisma con campos por schema |
|
|
172
|
+
|
|
173
|
+
### Control del entorno
|
|
174
|
+
|
|
175
|
+
| Tool | Descripción |
|
|
176
|
+
|---|---|
|
|
177
|
+
| `env_status` | Estado de Docker, .env.local y herramientas de desarrollo |
|
|
178
|
+
| `env_run_check` | Ejecuta typecheck, lint, test o build |
|
|
179
|
+
| `env_prisma_status` | Migraciones pendientes y estado de la DB |
|
|
180
|
+
|
|
181
|
+
### Generación
|
|
182
|
+
|
|
183
|
+
| Tool | Descripción |
|
|
184
|
+
|---|---|
|
|
185
|
+
| `generate_action` | Server Action con Zod, auth, revalidación — basado en tu schema Prisma real |
|
|
186
|
+
| `generate_page` | Página RSC con auth, metadata y estructura correcta |
|
|
187
|
+
| `generate_component` | Componente con cn(), tipado explícito y directiva correcta |
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## Integración con Gentleman AI Ecosystem
|
|
192
|
+
|
|
193
|
+
Este MCP está diseñado para funcionar junto con [Engram](https://github.com/Gentleman-Programming/engram) (memoria persistente) y el [orquestador SDD](https://github.com/Gentleman-Programming/gentle-ai) (workflow de desarrollo).
|
|
194
|
+
|
|
195
|
+
### Cómo funciona
|
|
196
|
+
|
|
197
|
+
Engram se encarga de la **memoria** (decisiones, bugs, patrones, contexto entre sesiones). Este MCP se encarga de la **inteligencia del proyecto** (escaneo real del código, generación basada en el schema).
|
|
198
|
+
|
|
199
|
+
El skill `project-intelligence.SKILL.md` (incluido en `skills/`) le indica al orquestador SDD cuándo usar cada tool:
|
|
200
|
+
|
|
201
|
+
| Fase SDD | Tools del MCP |
|
|
202
|
+
|----------|---------------|
|
|
203
|
+
| `sdd-explore` | `project_scan` — mapa completo del proyecto |
|
|
204
|
+
| `sdd-spec` / `sdd-design` | `project_models`, `project_routes`, `project_actions` |
|
|
205
|
+
| `sdd-apply` | `generate_action`, `generate_page`, `generate_component` |
|
|
206
|
+
| `sdd-verify` | `env_run_check`, `env_prisma_status` |
|
|
207
|
+
| `sdd-archive` | `env_status` — confirmar entorno sano |
|
|
208
|
+
|
|
209
|
+
### Setup con Gentleman
|
|
210
|
+
|
|
211
|
+
1. Instalar [gentle-ai](https://github.com/Gentleman-Programming/gentle-ai) (`brew install gentleman-programming/tap/gentle-ai`)
|
|
212
|
+
2. Instalar este MCP server (ver arriba)
|
|
213
|
+
3. Correr `node ~/.project-mcp/dist/setup.js` — copia las skills automáticamente
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## Workflow sugerido
|
|
218
|
+
|
|
219
|
+
### Sin Gentleman (standalone)
|
|
220
|
+
|
|
221
|
+
```
|
|
222
|
+
1. env_status()
|
|
223
|
+
→ verificar que el entorno está sano antes de codear
|
|
224
|
+
|
|
225
|
+
2. project_scan()
|
|
226
|
+
→ mapa actual de rutas, actions y modelos
|
|
227
|
+
|
|
228
|
+
3. project_actions(feature: "users")
|
|
229
|
+
→ ver patterns existentes antes de crear uno nuevo
|
|
230
|
+
|
|
231
|
+
4. generate_action(entity: "user", operation: "create")
|
|
232
|
+
→ código base generado con TU schema Prisma real
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### Con Gentleman (SDD)
|
|
236
|
+
|
|
237
|
+
```
|
|
238
|
+
1. Engram: mem_context() → contexto de sesiones anteriores
|
|
239
|
+
2. MCP: project_scan() → mapa del proyecto actual
|
|
240
|
+
3. SDD: el orquestador delega fases a sub-agentes
|
|
241
|
+
→ cada sub-agente usa las tools del MCP según el skill project-intelligence
|
|
242
|
+
4. Engram: mem_save() → guardar decisiones y aprendizajes
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
## Skills incluidas (10)
|
|
248
|
+
|
|
249
|
+
El directorio `skills/` incluye skills en formato Gentleman (YAML frontmatter):
|
|
250
|
+
|
|
251
|
+
| Skill | Stack |
|
|
252
|
+
|---|---|
|
|
253
|
+
| `nextjs.md` | Next.js 16 + React 19 |
|
|
254
|
+
| `prisma.md` | Prisma 7 multi-schema |
|
|
255
|
+
| `nextauth.md` | NextAuth.js v5 |
|
|
256
|
+
| `zod.md` | Zod 4 validación |
|
|
257
|
+
| `shadcn.md` | shadcn/ui + Tailwind CSS 4 |
|
|
258
|
+
| `testing.md` | Vitest + Testing Library |
|
|
259
|
+
| `infra.md` | Docker, env vars, DB local |
|
|
260
|
+
| `security.md` | OWASP para Next.js + Prisma |
|
|
261
|
+
| `commit.md` | Conventional Commits y PRs |
|
|
262
|
+
| `project-intelligence.SKILL.md` | Integración SDD |
|
|
263
|
+
|
|
264
|
+
El setup las copia automáticamente al directorio de skills de tu agente.
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## Estructura del proyecto
|
|
269
|
+
|
|
270
|
+
```
|
|
271
|
+
project-mcp-server/
|
|
272
|
+
├── src/
|
|
273
|
+
│ ├── index.ts ← entry point (MCP server)
|
|
274
|
+
│ ├── setup.ts ← setup interactivo
|
|
275
|
+
│ ├── config.ts ← configuración desde env vars
|
|
276
|
+
│ ├── scanner/
|
|
277
|
+
│ │ ├── cache.ts ← TTL cache para escaneos
|
|
278
|
+
│ │ ├── routes.ts ← App Router scanner
|
|
279
|
+
│ │ ├── actions.ts ← Server Actions scanner
|
|
280
|
+
│ │ ├── prisma.ts ← multi-schema Prisma parser
|
|
281
|
+
│ │ └── components.ts ← shadcn + custom components
|
|
282
|
+
│ └── tools/
|
|
283
|
+
│ ├── project/index.ts ← 4 tools de inteligencia
|
|
284
|
+
│ ├── env/index.ts ← 3 tools de entorno
|
|
285
|
+
│ └── generate/index.ts ← 3 tools de generación
|
|
286
|
+
├── skills/ ← archivos .md de skills (formato Gentleman)
|
|
287
|
+
├── dist/ ← compilado (no commitear)
|
|
288
|
+
├── package.json
|
|
289
|
+
└── tsconfig.json
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
## Actualizar
|
|
295
|
+
|
|
296
|
+
```bash
|
|
297
|
+
cd ~/.project-mcp && git pull && npm install && npm run build
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
No hay que reiniciar el LLM — el servidor se actualiza al próximo restart del proceso MCP.
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
## Testing local
|
|
305
|
+
|
|
306
|
+
```bash
|
|
307
|
+
# Inspeccionar con MCP Inspector (UI visual)
|
|
308
|
+
npm run inspect
|
|
309
|
+
|
|
310
|
+
# Test manual de una tool
|
|
311
|
+
echo '{
|
|
312
|
+
"jsonrpc": "2.0",
|
|
313
|
+
"id": 1,
|
|
314
|
+
"method": "tools/call",
|
|
315
|
+
"params": {
|
|
316
|
+
"name": "env_status",
|
|
317
|
+
"arguments": {}
|
|
318
|
+
}
|
|
319
|
+
}' | MCP_PROJECT_ROOT=/tu/proyecto node dist/index.js 2>/dev/null
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
## Créditos
|
|
325
|
+
|
|
326
|
+
- [Gentleman Programming](https://github.com/Gentleman-Programming) (Alan Buscaglia) — Engram, Gentle AI, SDD, formato de skills y la filosofía de ecosistema que inspira este proyecto
|
|
327
|
+
- [Anthropic](https://github.com/modelcontextprotocol) — Model Context Protocol y SDK
|
|
328
|
+
- [Everything Claude Code](https://github.com/affaan-m/everything-claude-code) (Affaan M) — Inspiración para el skill de seguridad
|
|
329
|
+
- [Vercel](https://github.com/vercel/next.js), [Prisma](https://github.com/prisma/prisma), [shadcn](https://github.com/shadcn-ui/ui), [Zod](https://github.com/colinhacks/zod), [NextAuth.js](https://github.com/nextauthjs/next-auth), [Vitest](https://github.com/vitest-dev/vitest), [Tailwind CSS](https://github.com/tailwindlabs/tailwindcss)
|
|
330
|
+
|
|
331
|
+
Ver [ACKNOWLEDGMENTS.md](ACKNOWLEDGMENTS.md) para el detalle completo.
|
|
332
|
+
|
|
333
|
+
## Licencia
|
|
334
|
+
|
|
335
|
+
MIT — ver [LICENSE](LICENSE)
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare const config: {
|
|
2
|
+
readonly projectRoot: string;
|
|
3
|
+
readonly scanner: {
|
|
4
|
+
readonly appDir: "src/app";
|
|
5
|
+
readonly actionsDir: "server/actions";
|
|
6
|
+
readonly schemasDir: "src/types/schemas";
|
|
7
|
+
readonly componentsUiDir: "src/components/ui";
|
|
8
|
+
readonly prismaDir: "prisma/schema";
|
|
9
|
+
readonly cacheTtlMs: 30000;
|
|
10
|
+
};
|
|
11
|
+
readonly skills: {
|
|
12
|
+
readonly dir: string;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
export type Config = typeof config;
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
function requireEnv(name, fallback) {
|
|
4
|
+
const val = process.env[name] ?? fallback;
|
|
5
|
+
if (!val)
|
|
6
|
+
throw new Error(`Variable de entorno requerida: ${name}`);
|
|
7
|
+
return val;
|
|
8
|
+
}
|
|
9
|
+
function resolveProjectRoot() {
|
|
10
|
+
const fromEnv = process.env["MCP_PROJECT_ROOT"];
|
|
11
|
+
if (fromEnv && existsSync(fromEnv))
|
|
12
|
+
return resolve(fromEnv);
|
|
13
|
+
// Detectar desde cwd buscando indicadores del proyecto
|
|
14
|
+
const cwd = process.cwd();
|
|
15
|
+
const markers = ["CLAUDE.md", "next.config.ts", "next.config.js", "package.json"];
|
|
16
|
+
for (const marker of markers) {
|
|
17
|
+
if (existsSync(resolve(cwd, marker)))
|
|
18
|
+
return cwd;
|
|
19
|
+
}
|
|
20
|
+
return cwd;
|
|
21
|
+
}
|
|
22
|
+
export const config = {
|
|
23
|
+
projectRoot: resolveProjectRoot(),
|
|
24
|
+
scanner: {
|
|
25
|
+
// Rutas relativas al projectRoot
|
|
26
|
+
appDir: "src/app",
|
|
27
|
+
actionsDir: "server/actions",
|
|
28
|
+
schemasDir: "src/types/schemas",
|
|
29
|
+
componentsUiDir: "src/components/ui",
|
|
30
|
+
prismaDir: "prisma/schema",
|
|
31
|
+
cacheTtlMs: 30_000 // 30 segundos
|
|
32
|
+
},
|
|
33
|
+
skills: {
|
|
34
|
+
// Directorio de skills relativo a este archivo compilado
|
|
35
|
+
dir: new URL("../skills", import.meta.url).pathname
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAEnC,SAAS,UAAU,CAAC,IAAY,EAAE,QAAiB;IACjD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAA;IACzC,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,IAAI,EAAE,CAAC,CAAA;IACnE,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,SAAS,kBAAkB;IACzB,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAA;IAC/C,IAAI,OAAO,IAAI,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,OAAO,CAAC,OAAO,CAAC,CAAA;IAE3D,uDAAuD;IACvD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAA;IACzB,MAAM,OAAO,GAAG,CAAC,WAAW,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,cAAc,CAAC,CAAA;IACjF,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;YAAE,OAAO,GAAG,CAAA;IAClD,CAAC;IAED,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,WAAW,EAAE,kBAAkB,EAAE;IAEjC,OAAO,EAAE;QACP,iCAAiC;QACjC,MAAM,EAAE,SAAS;QACjB,UAAU,EAAE,gBAAgB;QAC5B,UAAU,EAAE,mBAAmB;QAC/B,eAAe,EAAE,mBAAmB;QACpC,SAAS,EAAE,eAAe;QAC1B,UAAU,EAAE,MAAM,CAAC,cAAc;KAClC;IAED,MAAM,EAAE;QACN,yDAAyD;QACzD,GAAG,EAAE,IAAI,GAAG,CAAC,WAAW,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ;KACpD;CACO,CAAA"}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { registerProjectTools } from "./tools/project/index.js";
|
|
5
|
+
import { registerEnvTools } from "./tools/env/index.js";
|
|
6
|
+
import { registerGenerateTools } from "./tools/generate/index.js";
|
|
7
|
+
import { config } from "./config.js";
|
|
8
|
+
const server = new McpServer({
|
|
9
|
+
name: "project-mcp-server",
|
|
10
|
+
version: "2.0.0"
|
|
11
|
+
});
|
|
12
|
+
registerProjectTools(server);
|
|
13
|
+
registerEnvTools(server);
|
|
14
|
+
registerGenerateTools(server);
|
|
15
|
+
async function main() {
|
|
16
|
+
console.error(`✓ project-mcp-server v2.0.0 iniciado`);
|
|
17
|
+
console.error(` Proyecto: ${config.projectRoot}`);
|
|
18
|
+
console.error(` Tools: project_scan, project_routes, project_actions, project_models,`);
|
|
19
|
+
console.error(` env_status, env_run_check, env_prisma_status,`);
|
|
20
|
+
console.error(` generate_action, generate_page, generate_component`);
|
|
21
|
+
const transport = new StdioServerTransport();
|
|
22
|
+
await server.connect(transport);
|
|
23
|
+
}
|
|
24
|
+
main().catch((err) => {
|
|
25
|
+
console.error("Error fatal:", err);
|
|
26
|
+
process.exit(1);
|
|
27
|
+
});
|
|
28
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAA;AAChF,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAA;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AACvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAA;AACjE,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEpC,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,IAAI,EAAE,oBAAoB;IAC1B,OAAO,EAAE,OAAO;CACjB,CAAC,CAAA;AAEF,oBAAoB,CAAC,MAAM,CAAC,CAAA;AAC5B,gBAAgB,CAAC,MAAM,CAAC,CAAA;AACxB,qBAAqB,CAAC,MAAM,CAAC,CAAA;AAE7B,KAAK,UAAU,IAAI;IACjB,OAAO,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAA;IACrD,OAAO,CAAC,KAAK,CAAC,eAAe,MAAM,CAAC,WAAW,EAAE,CAAC,CAAA;IAClD,OAAO,CAAC,KAAK,CAAC,yEAAyE,CAAC,CAAA;IACxF,OAAO,CAAC,KAAK,CAAC,wDAAwD,CAAC,CAAA;IACvE,OAAO,CAAC,KAAK,CAAC,6DAA6D,CAAC,CAAA;IAE5E,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAA;IAC5C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;AACjC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IAC5B,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,GAAG,CAAC,CAAA;IAClC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACjB,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { readdir, readFile } from "node:fs/promises";
|
|
2
|
+
import { join, relative } from "node:path";
|
|
3
|
+
import { existsSync } from "node:fs";
|
|
4
|
+
import { config } from "../config.js";
|
|
5
|
+
import { cached } from "./cache.js";
|
|
6
|
+
function extractFunctions(content) {
|
|
7
|
+
const results = [];
|
|
8
|
+
// Detectar exports de async functions
|
|
9
|
+
const fnRegex = /export\s+async\s+function\s+(\w+)\s*\(([^)]*)\)/g;
|
|
10
|
+
let match;
|
|
11
|
+
while ((match = fnRegex.exec(content)) !== null) {
|
|
12
|
+
const name = match[1] ?? "";
|
|
13
|
+
const rawParams = match[2] ?? "";
|
|
14
|
+
const params = rawParams
|
|
15
|
+
.split(",")
|
|
16
|
+
.map(p => p.trim().split(":")[0]?.trim() ?? "")
|
|
17
|
+
.filter(p => p.length > 0 && p !== "_");
|
|
18
|
+
results.push({ name, params });
|
|
19
|
+
}
|
|
20
|
+
return results;
|
|
21
|
+
}
|
|
22
|
+
function detectZodSchema(content, fnName) {
|
|
23
|
+
// Buscar patrones como: const parsed = XxxSchema.safeParse(...) o XxxSchema.parse(...)
|
|
24
|
+
const patterns = [
|
|
25
|
+
/const\s+\w+\s*=\s*(\w+Schema)\.(?:safe)?[Pp]arse/g,
|
|
26
|
+
/(\w+Schema)\.(?:safe)?[Pp]arse\(/g,
|
|
27
|
+
new RegExp(`${fnName}Schema`, "g")
|
|
28
|
+
];
|
|
29
|
+
for (const pattern of patterns) {
|
|
30
|
+
const m = pattern.exec(content);
|
|
31
|
+
if (m)
|
|
32
|
+
return m[1];
|
|
33
|
+
}
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
async function scanFile(filePath) {
|
|
37
|
+
const content = await readFile(filePath, "utf-8").catch(() => "");
|
|
38
|
+
if (!content)
|
|
39
|
+
return [];
|
|
40
|
+
// Verificar que tiene "use server"
|
|
41
|
+
const first300 = content.slice(0, 300);
|
|
42
|
+
if (!first300.includes('"use server"') && !first300.includes("'use server'"))
|
|
43
|
+
return [];
|
|
44
|
+
const relativePath = relative(config.projectRoot, filePath);
|
|
45
|
+
const functions = extractFunctions(content);
|
|
46
|
+
return functions.map(({ name, params }) => ({
|
|
47
|
+
name,
|
|
48
|
+
file: relativePath,
|
|
49
|
+
zodSchema: detectZodSchema(content, name),
|
|
50
|
+
params,
|
|
51
|
+
hasAuth: content.includes("await auth()") || content.includes("const session = await auth"),
|
|
52
|
+
hasRevalidate: content.includes("revalidateTag(") || content.includes("revalidatePath(")
|
|
53
|
+
}));
|
|
54
|
+
}
|
|
55
|
+
async function walkDir(dir) {
|
|
56
|
+
const entries = await readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
57
|
+
const files = [];
|
|
58
|
+
for (const entry of entries) {
|
|
59
|
+
const full = join(dir, entry.name);
|
|
60
|
+
if (entry.isDirectory())
|
|
61
|
+
files.push(...await walkDir(full));
|
|
62
|
+
else if (entry.name.endsWith(".ts") || entry.name.endsWith(".tsx"))
|
|
63
|
+
files.push(full);
|
|
64
|
+
}
|
|
65
|
+
return files;
|
|
66
|
+
}
|
|
67
|
+
export async function scanActions() {
|
|
68
|
+
return cached("actions", async () => {
|
|
69
|
+
const actionsDir = join(config.projectRoot, config.scanner.actionsDir);
|
|
70
|
+
if (!existsSync(actionsDir))
|
|
71
|
+
return [];
|
|
72
|
+
const files = await walkDir(actionsDir);
|
|
73
|
+
const results = await Promise.all(files.map(scanFile));
|
|
74
|
+
return results.flat().sort((a, b) => a.name.localeCompare(b.name));
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=actions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"actions.js","sourceRoot":"","sources":["../../src/scanner/actions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare function getCached<T>(key: string): T | null;
|
|
2
|
+
export declare function setCached<T>(key: string, data: T, ttlMs?: number): void;
|
|
3
|
+
export declare function invalidate(prefix?: string): void;
|
|
4
|
+
export declare function cached<T>(key: string, fn: () => Promise<T>, ttlMs?: number): Promise<T>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { config } from "../config.js";
|
|
2
|
+
const store = new Map();
|
|
3
|
+
export function getCached(key) {
|
|
4
|
+
const entry = store.get(key);
|
|
5
|
+
if (!entry)
|
|
6
|
+
return null;
|
|
7
|
+
if (Date.now() > entry.expiresAt) {
|
|
8
|
+
store.delete(key);
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
return entry.data;
|
|
12
|
+
}
|
|
13
|
+
export function setCached(key, data, ttlMs = config.scanner.cacheTtlMs) {
|
|
14
|
+
store.set(key, { data, expiresAt: Date.now() + ttlMs });
|
|
15
|
+
}
|
|
16
|
+
export function invalidate(prefix) {
|
|
17
|
+
if (!prefix) {
|
|
18
|
+
store.clear();
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
for (const key of store.keys()) {
|
|
22
|
+
if (key.startsWith(prefix))
|
|
23
|
+
store.delete(key);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export async function cached(key, fn, ttlMs = config.scanner.cacheTtlMs) {
|
|
27
|
+
const hit = getCached(key);
|
|
28
|
+
if (hit !== null)
|
|
29
|
+
return hit;
|
|
30
|
+
const data = await fn();
|
|
31
|
+
setCached(key, data, ttlMs);
|
|
32
|
+
return data;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/scanner/cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAOrC,MAAM,KAAK,GAAG,IAAI,GAAG,EAA+B,CAAA;AAEpD,MAAM,UAAU,SAAS,CAAI,GAAW;IACtC,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAA8B,CAAA;IACzD,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAA;IACvB,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC;QACjC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QACjB,OAAO,IAAI,CAAA;IACb,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAA;AACnB,CAAC;AAED,MAAM,UAAU,SAAS,CAAI,GAAW,EAAE,IAAO,EAAE,QAAgB,MAAM,CAAC,OAAO,CAAC,UAAoB;IACpG,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE,CAAC,CAAA;AACzD,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAAe;IACxC,IAAI,CAAC,MAAM,EAAE,CAAC;QAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QAAC,OAAM;IAAC,CAAC;IACtC,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;QAC/B,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC;YAAE,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;IAC/C,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,MAAM,CAC1B,GAAW,EACX,EAAoB,EACpB,QAAgB,MAAM,CAAC,OAAO,CAAC,UAAU;IAEzC,MAAM,GAAG,GAAG,SAAS,CAAI,GAAG,CAAC,CAAA;IAC7B,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,GAAG,CAAA;IAC5B,MAAM,IAAI,GAAG,MAAM,EAAE,EAAE,CAAA;IACvB,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,CAAC,CAAA;IAC3B,OAAO,IAAI,CAAA;AACb,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface InstalledComponent {
|
|
2
|
+
name: string;
|
|
3
|
+
file: string;
|
|
4
|
+
exports: string[];
|
|
5
|
+
usesRadix: boolean;
|
|
6
|
+
usesCva: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface CustomComponent {
|
|
9
|
+
name: string;
|
|
10
|
+
file: string;
|
|
11
|
+
feature: string;
|
|
12
|
+
isClient: boolean;
|
|
13
|
+
}
|
|
14
|
+
export declare function scanComponents(): Promise<{
|
|
15
|
+
ui: InstalledComponent[];
|
|
16
|
+
custom: CustomComponent[];
|
|
17
|
+
}>;
|