cmp-standards 2.4.0 → 2.7.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 -611
- package/dist/cli/index.js +0 -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/turso-client.js +11 -11
- package/dist/eslint/rules/no-async-useeffect.js +6 -6
- package/dist/hooks/cloud-pre-tool-use.js +20 -20
- package/dist/hooks/cloud-session-start.d.ts +15 -3
- package/dist/hooks/cloud-session-start.d.ts.map +1 -1
- package/dist/hooks/cloud-session-start.js +135 -8
- package/dist/hooks/cloud-session-start.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 +99 -74
- package/dist/hooks/session-start.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.js +2 -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 +90 -90
- 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.js +76 -76
- package/dist/services/context-injector.d.ts +111 -0
- package/dist/services/context-injector.d.ts.map +1 -0
- package/dist/services/context-injector.js +397 -0
- package/dist/services/context-injector.js.map +1 -0
- 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-router.d.ts +122 -0
- package/dist/services/memory-router.d.ts.map +1 -0
- package/dist/services/memory-router.js +517 -0
- package/dist/services/memory-router.js.map +1 -0
- package/dist/services/pattern-tracker.d.ts +97 -0
- package/dist/services/pattern-tracker.d.ts.map +1 -0
- package/dist/services/pattern-tracker.js +425 -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/types/index.d.ts +329 -4
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +186 -9
- package/dist/types/index.js.map +1 -1
- package/package.json +104 -100
- package/standards/README.md +50 -50
- package/standards/experts/expert-routing.md +215 -215
- package/standards/general/code-quality.md +86 -86
- package/standards/general/memory-usage.md +205 -205
- package/standards/general/sync-workflow.md +235 -235
- package/standards/general/workflow.md +82 -82
- package/standards/hooks/mandatory-tracking.md +446 -446
- package/standards/infrastructure/cloud-database.md +287 -287
- package/standards/mcp/server-design.md +243 -243
- package/standards/mcp/tool-patterns.md +354 -354
- package/standards/skills/skill-structure.md +286 -286
- package/standards/skills/workflow-design.md +323 -323
- package/standards/tools/tool-design.md +297 -297
- 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 -72
- 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 -56
- package/templates/memory-config.schema.json +212 -212
- package/templates/settings.json +58 -58
- package/templates/skills/continue.md +205 -205
- 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
|
@@ -1,243 +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
|
-
```
|
|
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
|
+
```
|