@@ -78,6 +78,52 @@ mcp create <your project name here> --http --port 1337 --cors
78
78
mcp add tool price-fetcher
79
79
` ` `
80
80
81
+ # ## Building and Validation
82
+
83
+ The framework provides comprehensive validation to ensure your tools are properly documented and functional:
84
+
85
+ ` ` ` bash
86
+ # Build with automatic validation (recommended)
87
+ npm run build
88
+
89
+ # Build with custom validation settings
90
+ MCP_SKIP_TOOL_VALIDATION=false npm run build # Force validation (default)
91
+ MCP_SKIP_TOOL_VALIDATION=true npm run build # Skip validation (not recommended)
92
+ ` ` `
93
+
94
+ # ## Validating Tools
95
+
96
+ ` ` ` bash
97
+ # Validate all tools have proper descriptions (for Zod schemas)
98
+ mcp validate
99
+ ` ` `
100
+
101
+ This command checks that all tools using Zod schemas have descriptions for every field. The validation runs automatically during build, but you can also run it standalone:
102
+
103
+ - ✅ ** During build** : ` npm run build` automatically validates tools
104
+ - ✅ ** Standalone** : ` mcp validate` for manual validation
105
+ - ✅ ** Development** : Use ` defineSchema()` helper for immediate feedback
106
+ - ✅ ** Runtime** : Server validates tools on startup
107
+
108
+ ** Example validation error:**
109
+ ` ` ` bash
110
+ ❌ Tool validation failed:
111
+ ❌ PriceFetcher.js: Missing descriptions for fields in price_fetcher: symbol, currency.
112
+ All fields must have descriptions when using Zod object schemas.
113
+ Use .describe () on each field, e.g., z.string ().describe(" Field description" )
114
+ ` ` `
115
+
116
+ ** Integrating validation into CI/CD:**
117
+ ` ` ` json
118
+ {
119
+ " scripts" : {
120
+ " build" : " tsc && mcp-build" ,
121
+ " test" : " jest && mcp validate" ,
122
+ " prepack" : " npm run build && mcp validate"
123
+ }
124
+ }
125
+ ` ` `
126
+
81
127
# ## Adding a Prompt
82
128
83
129
` ` ` bash
@@ -94,38 +140,75 @@ mcp add resource market-data
94
140
95
141
# # Development Workflow
96
142
97
- 1. Create your project:
98
-
99
- ` ` ` bash
100
- mcp create my-mcp-server
101
- cd my-mcp-server
102
- ` ` `
103
-
104
- 2. Add tools as needed:
143
+ 1. ** Create your project:**
144
+ ` ` ` bash
145
+ mcp create my-mcp-server
146
+ cd my-mcp-server
147
+ ` ` `
105
148
149
+ 2. ** Add tools:**
106
150
` ` ` bash
107
151
mcp add tool data-fetcher
108
152
mcp add tool data-processor
109
153
mcp add tool report-generator
110
154
` ` `
111
155
112
- 3. Build:
156
+ 3. ** Define your tool schemas with automatic validation:**
157
+ ` ` ` typescript
158
+ // tools/DataFetcher.ts
159
+ import { MCPTool, McpInput } from " mcp-framework" ;
160
+ import { z } from " zod" ;
161
+
162
+ const DataFetcherSchema = z.object({
163
+ // all fields should have .describe ()
164
+ url: z.string().url ().describe(" URL to fetch data from" ),
165
+ timeout: z.number().positive ().default(5000).describe(" Request timeout in milliseconds" ).optional()
166
+ });
167
+
168
+ class DataFetcher extends MCPTool {
169
+ name = " data_fetcher" ;
170
+ description = " Fetch data from external APIs" ;
171
+ schema = DataFetcherSchema;
172
+
173
+ async execute(input: McpInput< this> ) {
174
+ // Fully typed input with autocomplete support
175
+ const { url, timeout = 5000 } = input;
176
+ // ... implementation
177
+ }
178
+ }
179
+ ` ` `
113
180
181
+ 4. ** Build with automatic validation:**
114
182
` ` ` bash
115
- npm run build
183
+ npm run build # Automatically validates schemas and compiles
184
+ ` ` `
116
185
186
+ 5. ** Optional: Run standalone validation:**
187
+ ` ` ` bash
188
+ mcp validate # Check all tools independently
117
189
` ` `
118
190
119
- 4. Add to MCP Client (Read below for Claude Desktop example)
191
+ 6. ** Test your server:**
192
+ ` ` ` bash
193
+ node dist/index.js # Server validates tools on startup
194
+ ` ` `
195
+
196
+ 7. ** Add to MCP Client** (see Claude Desktop example below)
197
+
198
+ ** Pro Tips:**
199
+ - Use ` defineSchema()` during development for immediate feedback
200
+ - Build process automatically catches missing descriptions
201
+ - Server startup validates all tools before accepting connections
202
+ - Use TypeScript' s autocomplete with `McpInput<this>` for better DX
120
203
121
204
## Using with Claude Desktop
122
205
123
206
### Local Development
124
207
125
208
Add this configuration to your Claude Desktop config file:
126
209
127
- ** MacOS** : \ ` ~/Library/Application Support/Claude/claude_desktop_config.json\ `
128
- ** Windows** : \ ` %APPDATA%/Claude/claude_desktop_config.json\ `
210
+ **MacOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
211
+ **Windows**: `%APPDATA%/Claude/claude_desktop_config.json`
129
212
130
213
```json
131
214
{
@@ -142,8 +225,8 @@ Add this configuration to your Claude Desktop config file:
142
225
143
226
Add this configuration to your Claude Desktop config file:
144
227
145
- ** MacOS** : \ ` ~/Library/Application Support/Claude/claude_desktop_config.json\ `
146
- ** Windows** : \ ` %APPDATA%/Claude/claude_desktop_config.json\ `
228
+ **MacOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
229
+ **Windows**: `%APPDATA%/Claude/claude_desktop_config.json`
147
230
148
231
```json
149
232
{
@@ -159,7 +242,7 @@ Add this configuration to your Claude Desktop config file:
159
242
## Building and Testing
160
243
161
244
1. Make changes to your tools
162
- 2. Run \ ` npm run build\ ` to compile
245
+ 2. Run `npm run build` to compile
163
246
3. The server will automatically load your tools on startup
164
247
165
248
## Environment Variables
@@ -179,39 +262,170 @@ Example usage:
179
262
MCP_ENABLE_FILE_LOGGING=true node dist/index.js
180
263
181
264
# Specify a custom log directory
182
- MCP_ENABLE_FILE_LOGGING=true MCP_LOG_DIRECTORY=my-logs
265
+ MCP_ENABLE_FILE_LOGGING=true MCP_LOG_DIRECTORY=my-logs node dist/index.js
266
+
183
267
# Enable debug messages in console
184
- MCP_DEBUG_CONSOLE=true` ` `
268
+ MCP_DEBUG_CONSOLE=true node dist/index.js
269
+ ```
185
270
186
271
## Quick Start
187
272
188
- # ## Creating a Tool
273
+ ### Defining Tools
274
+
275
+ MCP Framework uses Zod schemas for defining tool inputs, providing type safety, validation, and automatic documentation:
276
+
277
+ ```typescript
278
+ import { MCPTool, McpInput } from "mcp-framework";
279
+ import { z } from "zod";
280
+
281
+ const AddToolSchema = z.object({
282
+ a: z.number().describe("First number to add"),
283
+ b: z.number().describe("Second number to add"),
284
+ });
285
+
286
+ class AddTool extends MCPTool {
287
+ name = "add";
288
+ description = "Add tool description";
289
+ schema = AddToolSchema;
290
+
291
+ async execute(input: McpInput<this>) {
292
+ const result = input.a + input.b;
293
+ return `Result: ${result}`;
294
+ }
295
+ }
296
+
297
+ export default AddTool;
298
+ ```
299
+
300
+ **Key Benefits:**
301
+ - ✅ **Single source of truth** - Define types and validation in one place
302
+ - ✅ **Automatic type inference** - TypeScript types are inferred from your schema
303
+ - ✅ **Rich validation** - Leverage Zod' s powerful validation features
304
+ - ✅ ** Required descriptions** - Framework enforces documentation
305
+ - ✅ ** Better IDE support** - Full autocomplete and type checking
306
+ - ✅ ** Cleaner code** - No duplicate type definitions
307
+
308
+ # ## Advanced Zod Schema Features
309
+
310
+ The framework supports all Zod features:
189
311
190
312
` ` ` typescript
191
- import { MCPTool } from " mcp-framework" ;
313
+ import { MCPTool, McpInput } from " mcp-framework" ;
192
314
import { z } from " zod" ;
193
315
194
- interface ExampleInput {
195
- message: string;
316
+ const AdvancedSchema = z.object({
317
+ // String constraints and formats
318
+ email: z.string().email ().describe(" User email address" ),
319
+ name: z.string ().min(2).max(50).describe(" User name" ),
320
+ website: z.string().url().optional ().describe(" Optional website URL" ),
321
+
322
+ // Number constraints
323
+ age: z.number().int().positive ().max(120).describe(" User age" ),
324
+ rating: z.number ().min(1).max(5).describe(" Rating from 1 to 5" ),
325
+
326
+ // Arrays and objects
327
+ tags: z.array(z.string ()).describe(" List of tags" ),
328
+ metadata: z.object({
329
+ priority: z.enum([' low' , ' medium' , ' high' ]).describe(" Task priority" ),
330
+ dueDate: z.string().optional ().describe(" Due date in ISO format" )
331
+ }).describe(" Additional metadata" ),
332
+
333
+ // Default values
334
+ status: z.string ().default(' pending' ).describe(" Current status" ),
335
+
336
+ // Unions and enums
337
+ category: z.union([
338
+ z.literal(' personal' ),
339
+ z.literal(' work' ),
340
+ z.literal(' other' )
341
+ ]).describe(" Category type" )
342
+ });
343
+
344
+ class AdvancedTool extends MCPTool {
345
+ name = " advanced_tool" ;
346
+ description = " Tool demonstrating advanced Zod features" ;
347
+ schema = AdvancedSchema;
348
+
349
+ async execute(input: McpInput< this> ) {
350
+ // TypeScript automatically knows all the types!
351
+ const { email, name, website, age, rating, tags, metadata, status, category } = input;
352
+
353
+ console.log(input.name.toUpperCase ()); // ✅ TypeScript knows this is valid
354
+ console.log(input.age.toFixed(2)); // ✅ Number methods available
355
+ console.log(input.tags.length); // ✅ Array methods available
356
+ console.log(input.website? .includes(" https" )); // ✅ Optional handling
357
+
358
+ return ` Processed user: ${name} ` ;
359
+ }
196
360
}
361
+ ` ` `
197
362
198
- class ExampleTool extends MCPTool< ExampleInput> {
199
- name = " example_tool" ;
200
- description = " An example tool that processes messages" ;
363
+ # ## Automatic Type Inference
201
364
202
- schema = {
203
- message: {
204
- type: z.string (),
205
- description: " Message to process" ,
206
- },
207
- };
365
+ The ` McpInput< this> ` type automatically infers the correct input type from your schema, eliminating the need for manual type definitions:
208
366
209
- async execute(input: ExampleInput) {
210
- return ` Processed: ${input.message} ` ;
367
+ ` ` ` typescript
368
+ class MyTool extends MCPTool {
369
+ schema = z.object({
370
+ name: z.string ().describe(" User name" ),
371
+ age: z.number().optional ().describe(" User age" ),
372
+ tags: z.array(z.string ()).describe(" User tags" )
373
+ });
374
+
375
+ async execute(input: McpInput< this> ) {
376
+ // TypeScript automatically knows:
377
+ // input.name is string
378
+ // input.age is number | undefined
379
+ // input.tags is string[]
380
+
381
+ console.log(input.name.toUpperCase ()); // ✅ TypeScript knows this is valid
382
+ console.log(input.age? .toFixed(2)); // ✅ Handles optional correctly
383
+ console.log(input.tags.length); // ✅ Array methods available
211
384
}
212
385
}
386
+ ` ` `
387
+
388
+ No more duplicate interfaces or generic type parameters needed!
389
+
390
+ # ## Schema Validation & Descriptions
391
+
392
+ ** All schema fields must have descriptions** . This ensures your tools are well-documented and provides better user experience in MCP clients.
393
+
394
+ The framework validates descriptions at multiple levels:
395
+
396
+ # ### 1. Build-time Validation (Recommended)
397
+ ` ` ` bash
398
+ npm run build # Automatically validates during compilation
399
+ ` ` `
400
+
401
+ # ### 2. Development-time Validation
402
+ Use the ` defineSchema` helper for immediate feedback:
403
+
404
+ ` ` ` typescript
405
+ import { defineSchema } from " mcp-framework" ;
406
+
407
+ // This will throw an error immediately if descriptions are missing
408
+ const MySchema = defineSchema({
409
+ name: z.string (), // ❌ Error: Missing description
410
+ age: z.number ().describe(" User age" ) // ✅ Good
411
+ });
412
+ ` ` `
413
+
414
+ # ### 3. Standalone Validation
415
+ ` ` ` bash
416
+ mcp validate # Check all tools for proper descriptions
417
+ ` ` `
418
+
419
+ # ### 4. Runtime Validation
420
+ The server automatically validates tools on startup.
421
+
422
+ ** To skip validation** (not recommended):
423
+ ` ` ` bash
424
+ # Skip during build
425
+ MCP_SKIP_TOOL_VALIDATION=true npm run build
213
426
214
- export default ExampleTool;
427
+ # Skip during development
428
+ NODE_ENV=production npm run dev
215
429
` ` `
216
430
217
431
# ## Setting up the Server
0 commit comments