cmp-standards 2.0.1 → 2.6.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/README.md +633 -541
- package/dist/cli/index.js +239 -7
- package/dist/cli/index.js.map +1 -1
- package/dist/dashboard/server.d.ts.map +1 -1
- package/dist/dashboard/server.js +203 -39
- package/dist/dashboard/server.js.map +1 -1
- package/dist/db/cloud.d.ts +174 -0
- package/dist/db/cloud.d.ts.map +1 -0
- package/dist/db/cloud.js +241 -0
- package/dist/db/cloud.js.map +1 -0
- package/dist/db/drizzle-client.d.ts +3 -3
- package/dist/db/drizzle-client.d.ts.map +1 -1
- package/dist/db/drizzle-client.js +57 -58
- package/dist/db/drizzle-client.js.map +1 -1
- package/dist/db/errors.d.ts +76 -0
- package/dist/db/errors.d.ts.map +1 -0
- package/dist/db/errors.js +135 -0
- package/dist/db/errors.js.map +1 -0
- package/dist/db/turso-client.d.ts +178 -0
- package/dist/db/turso-client.d.ts.map +1 -0
- package/dist/db/turso-client.js +455 -0
- package/dist/db/turso-client.js.map +1 -0
- package/dist/db/upstash-client.d.ts +161 -0
- package/dist/db/upstash-client.d.ts.map +1 -0
- package/dist/db/upstash-client.js +325 -0
- package/dist/db/upstash-client.js.map +1 -0
- package/dist/eslint/rules/no-async-useeffect.js +6 -6
- package/dist/hooks/cloud-post-tool-use.d.ts +30 -0
- package/dist/hooks/cloud-post-tool-use.d.ts.map +1 -0
- package/dist/hooks/cloud-post-tool-use.js +116 -0
- package/dist/hooks/cloud-post-tool-use.js.map +1 -0
- package/dist/hooks/cloud-pre-tool-use.d.ts +19 -0
- package/dist/hooks/cloud-pre-tool-use.d.ts.map +1 -0
- package/dist/hooks/cloud-pre-tool-use.js +149 -0
- package/dist/hooks/cloud-pre-tool-use.js.map +1 -0
- package/dist/hooks/cloud-session-start.d.ts +32 -0
- package/dist/hooks/cloud-session-start.d.ts.map +1 -0
- package/dist/hooks/cloud-session-start.js +257 -0
- package/dist/hooks/cloud-session-start.js.map +1 -0
- package/dist/hooks/index.d.ts +3 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +5 -0
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/memory-checkpoint.d.ts.map +1 -1
- package/dist/hooks/memory-checkpoint.js +12 -20
- package/dist/hooks/memory-checkpoint.js.map +1 -1
- package/dist/hooks/pre-tool-use.d.ts +2 -8
- package/dist/hooks/pre-tool-use.d.ts.map +1 -1
- package/dist/hooks/pre-tool-use.js +7 -106
- package/dist/hooks/pre-tool-use.js.map +1 -1
- package/dist/hooks/session-start.d.ts +2 -1
- package/dist/hooks/session-start.d.ts.map +1 -1
- package/dist/hooks/session-start.js +111 -77
- package/dist/hooks/session-start.js.map +1 -1
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +225 -2
- package/dist/mcp/server.js.map +1 -1
- package/dist/schema/plans.d.ts +194 -0
- package/dist/schema/plans.d.ts.map +1 -0
- package/dist/schema/plans.js +180 -0
- package/dist/schema/plans.js.map +1 -0
- package/dist/schema/tracking.d.ts +644 -0
- package/dist/schema/tracking.d.ts.map +1 -0
- package/dist/schema/tracking.js +204 -0
- package/dist/schema/tracking.js.map +1 -0
- package/dist/services/ContextGenerator.d.ts +16 -0
- package/dist/services/ContextGenerator.d.ts.map +1 -0
- package/dist/services/ContextGenerator.js +62 -0
- package/dist/services/ContextGenerator.js.map +1 -0
- package/dist/services/PlanManager.d.ts +99 -0
- package/dist/services/PlanManager.d.ts.map +1 -0
- package/dist/services/PlanManager.js +372 -0
- package/dist/services/PlanManager.js.map +1 -0
- package/dist/services/ProjectScaffold.d.ts.map +1 -1
- package/dist/services/ProjectScaffold.js +109 -81
- package/dist/services/ProjectScaffold.js.map +1 -1
- package/dist/services/TaskTracker.d.ts +1 -1
- package/dist/services/TaskTracker.d.ts.map +1 -1
- package/dist/services/TaskTracker.js +4 -8
- package/dist/services/TaskTracker.js.map +1 -1
- package/dist/services/WorkPlanManager.d.ts +1 -1
- package/dist/services/WorkPlanManager.d.ts.map +1 -1
- package/dist/services/WorkPlanManager.js +8 -14
- package/dist/services/WorkPlanManager.js.map +1 -1
- package/dist/services/auto-inject.d.ts +1 -0
- package/dist/services/auto-inject.d.ts.map +1 -1
- package/dist/services/auto-inject.js +12 -17
- package/dist/services/auto-inject.js.map +1 -1
- package/dist/services/context-injector.d.ts +105 -0
- package/dist/services/context-injector.d.ts.map +1 -0
- package/dist/services/context-injector.js +357 -0
- package/dist/services/context-injector.js.map +1 -0
- package/dist/services/cross-project-sync.d.ts +2 -0
- package/dist/services/cross-project-sync.d.ts.map +1 -1
- package/dist/services/cross-project-sync.js +26 -21
- package/dist/services/cross-project-sync.js.map +1 -1
- package/dist/services/index.d.ts +15 -15
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/index.js +18 -20
- package/dist/services/index.js.map +1 -1
- package/dist/services/memory-consolidation.d.ts.map +1 -1
- package/dist/services/memory-consolidation.js +30 -27
- package/dist/services/memory-consolidation.js.map +1 -1
- package/dist/services/memory-router.d.ts +98 -0
- package/dist/services/memory-router.d.ts.map +1 -0
- package/dist/services/memory-router.js +373 -0
- package/dist/services/memory-router.js.map +1 -0
- package/dist/services/pattern-tracker.d.ts +93 -0
- package/dist/services/pattern-tracker.d.ts.map +1 -0
- package/dist/services/pattern-tracker.js +347 -0
- package/dist/services/pattern-tracker.js.map +1 -0
- package/dist/services/semantic-search.d.ts +33 -35
- package/dist/services/semantic-search.d.ts.map +1 -1
- package/dist/services/semantic-search.js +207 -165
- package/dist/services/semantic-search.js.map +1 -1
- package/dist/utils/env-loader.d.ts +41 -0
- package/dist/utils/env-loader.d.ts.map +1 -0
- package/dist/utils/env-loader.js +78 -0
- package/dist/utils/env-loader.js.map +1 -0
- package/dist/utils/git.d.ts +52 -0
- package/dist/utils/git.d.ts.map +1 -0
- package/dist/utils/git.js +267 -0
- package/dist/utils/git.js.map +1 -0
- package/dist/utils/paths.d.ts +39 -5
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js +88 -7
- package/dist/utils/paths.js.map +1 -1
- package/package.json +100 -94
- package/standards/README.md +50 -0
- package/standards/experts/expert-routing.md +215 -0
- package/standards/general/code-quality.md +86 -0
- package/standards/general/memory-usage.md +205 -0
- package/standards/general/sync-workflow.md +235 -0
- package/standards/general/workflow.md +82 -0
- package/standards/hooks/mandatory-tracking.md +446 -0
- package/standards/infrastructure/cloud-database.md +287 -0
- package/standards/mcp/server-design.md +243 -0
- package/standards/mcp/tool-patterns.md +354 -0
- package/standards/skills/skill-structure.md +286 -0
- package/standards/skills/workflow-design.md +323 -0
- package/standards/tools/tool-design.md +297 -0
- package/templates/agents/architecture-expert.md +61 -61
- package/templates/agents/database-expert.md +62 -62
- package/templates/agents/documentation-expert.md +57 -57
- package/templates/agents/memory-expert.md +88 -88
- package/templates/agents/performance-expert.md +61 -61
- package/templates/agents/security-expert.md +59 -59
- package/templates/agents/ux-expert.md +63 -63
- package/templates/agents/worker.md +75 -75
- package/templates/ai-skills/SKILL_TEMPLATE.md +55 -55
- package/templates/claude-settings.json +72 -0
- package/templates/commands/experts.md +138 -138
- package/templates/hooks/README.md +158 -158
- package/templates/hooks/project.config.json.template +77 -77
- package/templates/hooks/settings.local.json.template +57 -57
- package/templates/memory-config.json +56 -82
- package/templates/memory-config.schema.json +212 -212
- package/templates/settings.json +58 -58
- package/templates/skills/continue.md +205 -0
- package/templates/workflows/business-improvement.md +264 -264
- package/templates/workflows/expert-review.md +153 -153
- package/templates/workflows/internal-app.md +245 -245
- package/templates/workflows/sync-docs.md +187 -187
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
# Infraestructura de Base de Datos Cloud
|
|
2
|
+
|
|
3
|
+
## Stack Recomendado (100% Gratuito)
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
7
|
+
│ ARQUITECTURA CLOUD │
|
|
8
|
+
├─────────────────────────────────────────────────────────────┤
|
|
9
|
+
│ │
|
|
10
|
+
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
|
11
|
+
│ │ Turso │ │ Upstash │ │ Upstash │ │
|
|
12
|
+
│ │ (SQLite) │ │ (Vector) │ │ (Redis) │ │
|
|
13
|
+
│ │ │ │ │ │ │ │
|
|
14
|
+
│ │ • Tareas │ │ • Embeddings│ │ • Cache │ │
|
|
15
|
+
│ │ • Mejoras │ │ • Semantic │ │ • Sessions │ │
|
|
16
|
+
│ │ • Sesiones │ │ Search │ │ • Config │ │
|
|
17
|
+
│ │ • Memorias │ │ │ │ │ │
|
|
18
|
+
│ └─────────────┘ └─────────────┘ └─────────────┘ │
|
|
19
|
+
│ │ │ │ │
|
|
20
|
+
│ └────────────────┼────────────────┘ │
|
|
21
|
+
│ │ │
|
|
22
|
+
│ ▼ │
|
|
23
|
+
│ ┌─────────────────────┐ │
|
|
24
|
+
│ │ MCP Server │ │
|
|
25
|
+
│ │ (Vercel Edge) │ │
|
|
26
|
+
│ └─────────────────────┘ │
|
|
27
|
+
│ │ │
|
|
28
|
+
│ ▼ │
|
|
29
|
+
│ ┌─────────────────────┐ │
|
|
30
|
+
│ │ Claude Code │ │
|
|
31
|
+
│ └─────────────────────┘ │
|
|
32
|
+
│ │
|
|
33
|
+
└─────────────────────────────────────────────────────────────┘
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Turso (SQLite Edge)
|
|
37
|
+
|
|
38
|
+
**Propósito**: Base de datos principal para tareas, mejoras, memorias.
|
|
39
|
+
|
|
40
|
+
### Free Tier
|
|
41
|
+
- 500M rows read/mes
|
|
42
|
+
- 10M rows written/mes
|
|
43
|
+
- 5GB storage
|
|
44
|
+
- 100 databases
|
|
45
|
+
- Sin tarjeta de crédito
|
|
46
|
+
|
|
47
|
+
### Setup
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# Instalar CLI
|
|
51
|
+
brew install tursodatabase/tap/turso
|
|
52
|
+
|
|
53
|
+
# Login
|
|
54
|
+
turso auth login
|
|
55
|
+
|
|
56
|
+
# Crear database
|
|
57
|
+
turso db create cmp-memory
|
|
58
|
+
|
|
59
|
+
# Obtener URL
|
|
60
|
+
turso db show cmp-memory --url
|
|
61
|
+
# → libsql://cmp-memory-username.turso.io
|
|
62
|
+
|
|
63
|
+
# Crear token
|
|
64
|
+
turso db tokens create cmp-memory
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Configuración
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
// src/db/turso-client.ts
|
|
71
|
+
import { createClient } from '@libsql/client'
|
|
72
|
+
import { drizzle } from 'drizzle-orm/libsql'
|
|
73
|
+
|
|
74
|
+
export function createTursoDB() {
|
|
75
|
+
const client = createClient({
|
|
76
|
+
url: process.env.TURSO_DATABASE_URL!,
|
|
77
|
+
authToken: process.env.TURSO_AUTH_TOKEN!
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
return drizzle(client)
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Variables de Entorno
|
|
85
|
+
|
|
86
|
+
```env
|
|
87
|
+
TURSO_DATABASE_URL=libsql://cmp-memory-username.turso.io
|
|
88
|
+
TURSO_AUTH_TOKEN=eyJ...
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Upstash Vector
|
|
92
|
+
|
|
93
|
+
**Propósito**: Búsqueda semántica de memorias y contexto.
|
|
94
|
+
|
|
95
|
+
### Free Tier
|
|
96
|
+
- 200M vectors
|
|
97
|
+
- 1GB data/metadata
|
|
98
|
+
- 10K queries/día
|
|
99
|
+
- Built-in embeddings
|
|
100
|
+
|
|
101
|
+
### Setup
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
# Crear en dashboard: https://console.upstash.com/vector
|
|
105
|
+
# Obtener UPSTASH_VECTOR_REST_URL y UPSTASH_VECTOR_REST_TOKEN
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Configuración
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
// src/db/vector-client.ts
|
|
112
|
+
import { Index } from '@upstash/vector'
|
|
113
|
+
|
|
114
|
+
export const vectorIndex = new Index({
|
|
115
|
+
url: process.env.UPSTASH_VECTOR_REST_URL!,
|
|
116
|
+
token: process.env.UPSTASH_VECTOR_REST_TOKEN!
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
// Insertar con embedding automático
|
|
120
|
+
await vectorIndex.upsert({
|
|
121
|
+
id: 'mem_123',
|
|
122
|
+
data: 'Este es el contenido de la memoria...',
|
|
123
|
+
metadata: {
|
|
124
|
+
type: 'memory',
|
|
125
|
+
domain: 'video-studio',
|
|
126
|
+
createdAt: new Date().toISOString()
|
|
127
|
+
}
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
// Buscar por similitud
|
|
131
|
+
const results = await vectorIndex.query({
|
|
132
|
+
data: 'buscar memorias sobre video',
|
|
133
|
+
topK: 5,
|
|
134
|
+
includeMetadata: true
|
|
135
|
+
})
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Variables de Entorno
|
|
139
|
+
|
|
140
|
+
```env
|
|
141
|
+
UPSTASH_VECTOR_REST_URL=https://abc-xyz.upstash.io
|
|
142
|
+
UPSTASH_VECTOR_REST_TOKEN=AXxx...
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Upstash Redis
|
|
146
|
+
|
|
147
|
+
**Propósito**: Cache de configuración y sesiones activas.
|
|
148
|
+
|
|
149
|
+
### Free Tier
|
|
150
|
+
- 10K commands/día
|
|
151
|
+
- 256MB storage
|
|
152
|
+
- Global replication
|
|
153
|
+
|
|
154
|
+
### Setup
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
# Crear en dashboard: https://console.upstash.com/redis
|
|
158
|
+
# Obtener UPSTASH_REDIS_REST_URL y UPSTASH_REDIS_REST_TOKEN
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Configuración
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
// src/db/redis-client.ts
|
|
165
|
+
import { Redis } from '@upstash/redis'
|
|
166
|
+
|
|
167
|
+
export const redis = new Redis({
|
|
168
|
+
url: process.env.UPSTASH_REDIS_REST_URL!,
|
|
169
|
+
token: process.env.UPSTASH_REDIS_REST_TOKEN!
|
|
170
|
+
})
|
|
171
|
+
|
|
172
|
+
// Cache de config (TTL 1 hora)
|
|
173
|
+
await redis.set('config:SWARMSCALE', config, { ex: 3600 })
|
|
174
|
+
|
|
175
|
+
// Leer config
|
|
176
|
+
const cached = await redis.get('config:SWARMSCALE')
|
|
177
|
+
|
|
178
|
+
// Sesiones activas
|
|
179
|
+
await redis.hset('sessions:active', {
|
|
180
|
+
[sessionId]: JSON.stringify(sessionData)
|
|
181
|
+
})
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Variables de Entorno
|
|
185
|
+
|
|
186
|
+
```env
|
|
187
|
+
UPSTASH_REDIS_REST_URL=https://def-uvw.upstash.io
|
|
188
|
+
UPSTASH_REDIS_REST_TOKEN=AYyy...
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## Migración desde PlanetScale/Railway
|
|
192
|
+
|
|
193
|
+
### Estrategia
|
|
194
|
+
|
|
195
|
+
1. **Fase 1**: Dual-write (escribir a ambos)
|
|
196
|
+
2. **Fase 2**: Read from Turso, write to both
|
|
197
|
+
3. **Fase 3**: Full migration, keep PlanetScale as backup
|
|
198
|
+
|
|
199
|
+
### Script de Migración
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
// scripts/migrate-to-turso.ts
|
|
203
|
+
import { db as planetscale } from './db/planetscale'
|
|
204
|
+
import { db as turso } from './db/turso'
|
|
205
|
+
|
|
206
|
+
async function migrate() {
|
|
207
|
+
console.log('Fetching memories from PlanetScale...')
|
|
208
|
+
|
|
209
|
+
const memories = await planetscale.query.devItems.findMany({
|
|
210
|
+
where: eq(devItems.system, 'SWARMSCALE')
|
|
211
|
+
})
|
|
212
|
+
|
|
213
|
+
console.log(`Found ${memories.length} memories`)
|
|
214
|
+
|
|
215
|
+
// Batch insert to Turso
|
|
216
|
+
for (const batch of chunk(memories, 100)) {
|
|
217
|
+
await turso.insert(devItems).values(batch)
|
|
218
|
+
console.log(`Migrated ${batch.length} items`)
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
console.log('Migration complete!')
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
## Costos Estimados
|
|
226
|
+
|
|
227
|
+
| Uso | Turso | Vector | Redis | Total |
|
|
228
|
+
|-----|-------|--------|-------|-------|
|
|
229
|
+
| Desarrollo | $0 | $0 | $0 | **$0** |
|
|
230
|
+
| Producción pequeña | $0 | $0 | $0 | **$0** |
|
|
231
|
+
| Producción media | $4.99 | $0 | $0 | **$4.99** |
|
|
232
|
+
| Producción alta | $29 | $60 | $10 | **$99** |
|
|
233
|
+
|
|
234
|
+
## Configuración Completa
|
|
235
|
+
|
|
236
|
+
```env
|
|
237
|
+
# .env.cloud
|
|
238
|
+
|
|
239
|
+
# Turso (SQLite)
|
|
240
|
+
TURSO_DATABASE_URL=libsql://cmp-memory-username.turso.io
|
|
241
|
+
TURSO_AUTH_TOKEN=eyJ...
|
|
242
|
+
|
|
243
|
+
# Upstash Vector
|
|
244
|
+
UPSTASH_VECTOR_REST_URL=https://abc-xyz.upstash.io
|
|
245
|
+
UPSTASH_VECTOR_REST_TOKEN=AXxx...
|
|
246
|
+
|
|
247
|
+
# Upstash Redis
|
|
248
|
+
UPSTASH_REDIS_REST_URL=https://def-uvw.upstash.io
|
|
249
|
+
UPSTASH_REDIS_REST_TOKEN=AYyy...
|
|
250
|
+
|
|
251
|
+
# Embeddings (para generar si no usas built-in de Upstash)
|
|
252
|
+
OPENAI_API_KEY=sk-...
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
## Package Dependencies
|
|
256
|
+
|
|
257
|
+
```json
|
|
258
|
+
{
|
|
259
|
+
"dependencies": {
|
|
260
|
+
"@libsql/client": "^0.5.0",
|
|
261
|
+
"@upstash/vector": "^1.0.0",
|
|
262
|
+
"@upstash/redis": "^1.28.0",
|
|
263
|
+
"drizzle-orm": "^0.30.0"
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
## Fallback Strategy
|
|
269
|
+
|
|
270
|
+
Si un servicio falla, tener fallback:
|
|
271
|
+
|
|
272
|
+
```typescript
|
|
273
|
+
async function getMemories(query: string) {
|
|
274
|
+
try {
|
|
275
|
+
// Primary: Upstash Vector (semantic search)
|
|
276
|
+
return await vectorIndex.query({ data: query, topK: 10 })
|
|
277
|
+
} catch (error) {
|
|
278
|
+
console.error('Vector search failed, falling back to SQL')
|
|
279
|
+
|
|
280
|
+
// Fallback: Turso (SQL LIKE search)
|
|
281
|
+
return await turso.query.devItems.findMany({
|
|
282
|
+
where: like(devItems.content, `%${query}%`),
|
|
283
|
+
limit: 10
|
|
284
|
+
})
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
```
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
# Diseño de Servidores MCP
|
|
2
|
+
|
|
3
|
+
## Estructura Básica
|
|
4
|
+
|
|
5
|
+
Un servidor MCP expone **herramientas** (tools) y **recursos** (resources) a Claude Code.
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
mcp-server/
|
|
9
|
+
├── src/
|
|
10
|
+
│ ├── index.ts # Entry point
|
|
11
|
+
│ ├── server.ts # MCP server setup
|
|
12
|
+
│ ├── tools/ # Tool definitions
|
|
13
|
+
│ │ ├── index.ts
|
|
14
|
+
│ │ └── [tool-name].ts
|
|
15
|
+
│ ├── resources/ # Resource handlers
|
|
16
|
+
│ │ └── index.ts
|
|
17
|
+
│ └── utils/ # Shared utilities
|
|
18
|
+
├── package.json
|
|
19
|
+
└── README.md
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Configuración del Server
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js'
|
|
26
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
|
|
27
|
+
|
|
28
|
+
const server = new Server(
|
|
29
|
+
{
|
|
30
|
+
name: 'my-mcp-server',
|
|
31
|
+
version: '1.0.0',
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
capabilities: {
|
|
35
|
+
tools: {},
|
|
36
|
+
resources: {},
|
|
37
|
+
},
|
|
38
|
+
}
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
// Registrar handlers
|
|
42
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
43
|
+
tools: [/* tool definitions */]
|
|
44
|
+
}))
|
|
45
|
+
|
|
46
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
47
|
+
// Handle tool calls
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
// Conectar
|
|
51
|
+
const transport = new StdioServerTransport()
|
|
52
|
+
await server.connect(transport)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Definición de Tools
|
|
56
|
+
|
|
57
|
+
### Estructura de una Tool
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
{
|
|
61
|
+
name: 'tool_name', // snake_case
|
|
62
|
+
description: 'Qué hace', // Conciso, <100 chars
|
|
63
|
+
inputSchema: {
|
|
64
|
+
type: 'object',
|
|
65
|
+
properties: {
|
|
66
|
+
param1: {
|
|
67
|
+
type: 'string',
|
|
68
|
+
description: 'Para qué sirve'
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
required: ['param1']
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Nombres de Tools
|
|
77
|
+
|
|
78
|
+
- **snake_case**: `memory_search`, `task_create`
|
|
79
|
+
- **Prefijo del dominio**: `memory_*`, `pattern_*`, `task_*`
|
|
80
|
+
- **Verbos claros**: `create`, `get`, `list`, `update`, `delete`, `search`
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
// BIEN
|
|
84
|
+
'memory_search'
|
|
85
|
+
'memory_write'
|
|
86
|
+
'task_start'
|
|
87
|
+
'pattern_detect'
|
|
88
|
+
|
|
89
|
+
// MAL
|
|
90
|
+
'searchMemory' // No camelCase
|
|
91
|
+
'mem_srch' // No abreviaciones
|
|
92
|
+
'doSearch' // Verbo genérico
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Respuestas de Tools
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
// Éxito
|
|
99
|
+
return {
|
|
100
|
+
content: [
|
|
101
|
+
{
|
|
102
|
+
type: 'text',
|
|
103
|
+
text: JSON.stringify(result, null, 2)
|
|
104
|
+
}
|
|
105
|
+
]
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Error
|
|
109
|
+
return {
|
|
110
|
+
content: [
|
|
111
|
+
{
|
|
112
|
+
type: 'text',
|
|
113
|
+
text: `Error: ${error.message}`
|
|
114
|
+
}
|
|
115
|
+
],
|
|
116
|
+
isError: true
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Manejo de Errores
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
async function handleToolCall(name: string, args: unknown) {
|
|
124
|
+
try {
|
|
125
|
+
// Validar input
|
|
126
|
+
const validated = schema.parse(args)
|
|
127
|
+
|
|
128
|
+
// Ejecutar operación
|
|
129
|
+
const result = await executeOperation(validated)
|
|
130
|
+
|
|
131
|
+
return { content: [{ type: 'text', text: JSON.stringify(result) }] }
|
|
132
|
+
|
|
133
|
+
} catch (error) {
|
|
134
|
+
if (error instanceof ZodError) {
|
|
135
|
+
return {
|
|
136
|
+
content: [{ type: 'text', text: `Invalid input: ${error.message}` }],
|
|
137
|
+
isError: true
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Log para debugging, respuesta limpia para Claude
|
|
142
|
+
console.error('Tool error:', error)
|
|
143
|
+
return {
|
|
144
|
+
content: [{ type: 'text', text: `Operation failed: ${error.message}` }],
|
|
145
|
+
isError: true
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Resources
|
|
152
|
+
|
|
153
|
+
Los resources son datos que Claude puede leer (contexto estático).
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
server.setRequestHandler(ListResourcesRequestSchema, async () => ({
|
|
157
|
+
resources: [
|
|
158
|
+
{
|
|
159
|
+
uri: 'memory://recent',
|
|
160
|
+
name: 'Recent Memories',
|
|
161
|
+
description: 'Last 10 memories created',
|
|
162
|
+
mimeType: 'application/json'
|
|
163
|
+
}
|
|
164
|
+
]
|
|
165
|
+
}))
|
|
166
|
+
|
|
167
|
+
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
168
|
+
const { uri } = request.params
|
|
169
|
+
|
|
170
|
+
if (uri === 'memory://recent') {
|
|
171
|
+
const memories = await getRecentMemories()
|
|
172
|
+
return {
|
|
173
|
+
contents: [{
|
|
174
|
+
uri,
|
|
175
|
+
mimeType: 'application/json',
|
|
176
|
+
text: JSON.stringify(memories)
|
|
177
|
+
}]
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
})
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## Testing
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
import { describe, it, expect } from 'vitest'
|
|
187
|
+
|
|
188
|
+
describe('MCP Server', () => {
|
|
189
|
+
it('should list tools', async () => {
|
|
190
|
+
const result = await server.handleRequest({
|
|
191
|
+
method: 'tools/list'
|
|
192
|
+
})
|
|
193
|
+
expect(result.tools).toContainEqual(
|
|
194
|
+
expect.objectContaining({ name: 'memory_search' })
|
|
195
|
+
)
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
it('should handle tool call', async () => {
|
|
199
|
+
const result = await server.handleRequest({
|
|
200
|
+
method: 'tools/call',
|
|
201
|
+
params: {
|
|
202
|
+
name: 'memory_search',
|
|
203
|
+
arguments: { query: 'test' }
|
|
204
|
+
}
|
|
205
|
+
})
|
|
206
|
+
expect(result.isError).toBeFalsy()
|
|
207
|
+
})
|
|
208
|
+
})
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## Configuración en Claude Code
|
|
212
|
+
|
|
213
|
+
```json
|
|
214
|
+
// .claude/mcp.json
|
|
215
|
+
{
|
|
216
|
+
"mcpServers": {
|
|
217
|
+
"my-server": {
|
|
218
|
+
"command": "node",
|
|
219
|
+
"args": ["path/to/server/dist/index.js"],
|
|
220
|
+
"env": {
|
|
221
|
+
"DATABASE_URL": "..."
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
## Best Practices
|
|
229
|
+
|
|
230
|
+
1. **Tools atómicas** - Una tool hace una cosa bien
|
|
231
|
+
2. **Descripciones claras** - Claude decide basándose en la descripción
|
|
232
|
+
3. **Validación con Zod** - Siempre validar input
|
|
233
|
+
4. **Respuestas estructuradas** - JSON cuando hay datos complejos
|
|
234
|
+
5. **Errores informativos** - Ayudar a Claude a entender qué falló
|
|
235
|
+
6. **Logs en stderr** - No contaminar stdout (usado por MCP)
|
|
236
|
+
|
|
237
|
+
```typescript
|
|
238
|
+
// Usar stderr para logs
|
|
239
|
+
console.error('[DEBUG] Processing request...')
|
|
240
|
+
|
|
241
|
+
// stdout está reservado para MCP protocol
|
|
242
|
+
// NO usar console.log para debugging
|
|
243
|
+
```
|