@@ -78,6 +78,52 @@ mcp create <your project name here> --http --port 1337 --cors
7878mcp add tool price-fetcher
7979` ` `
8080
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+
81127# ## Adding a Prompt
82128
83129` ` ` bash
@@ -94,38 +140,74 @@ mcp add resource market-data
94140
95141# # Development Workflow
96142
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+ ` ` `
105148
149+ 2. ** Add tools:**
106150 ` ` ` bash
107151 mcp add tool data-fetcher
108152 mcp add tool data-processor
109153 mcp add tool report-generator
110154 ` ` `
111155
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+ url: z.string().url ().describe(" URL to fetch data from" ),
164+ timeout: z.number().positive ().default(5000).describe(" Request timeout in milliseconds" ).optional()
165+ });
166+
167+ class DataFetcher extends MCPTool {
168+ name = " data_fetcher" ;
169+ description = " Fetch data from external APIs" ;
170+ schema = DataFetcherSchema;
171+
172+ async execute(input: McpInput< this> ) {
173+ // Fully typed input with autocomplete support
174+ const { url, timeout = 5000 } = input;
175+ // ... implementation
176+ }
177+ }
178+ ` ` `
113179
180+ 4. ** Build with automatic validation:**
114181 ` ` ` bash
115- npm run build
182+ npm run build # Automatically validates schemas and compiles
183+ ` ` `
116184
185+ 5. ** Optional: Run standalone validation:**
186+ ` ` ` bash
187+ mcp validate # Check all tools independently
117188 ` ` `
118189
119- 4. Add to MCP Client (Read below for Claude Desktop example)
190+ 6. ** Test your server:**
191+ ` ` ` bash
192+ node dist/index.js # Server validates tools on startup
193+ ` ` `
194+
195+ 7. ** Add to MCP Client** (see Claude Desktop example below)
196+
197+ ** Pro Tips:**
198+ - Use ` defineSchema()` during development for immediate feedback
199+ - Build process automatically catches missing descriptions
200+ - Server startup validates all tools before accepting connections
201+ - Use TypeScript' s autocomplete with `McpInput<this>` for better DX
120202
121203## Using with Claude Desktop
122204
123205### Local Development
124206
125207Add this configuration to your Claude Desktop config file:
126208
127- ** MacOS** : \ ` ~/Library/Application Support/Claude/claude_desktop_config.json\ `
128- ** Windows** : \ ` %APPDATA%/Claude/claude_desktop_config.json\ `
209+ **MacOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
210+ **Windows**: `%APPDATA%/Claude/claude_desktop_config.json`
129211
130212```json
131213{
@@ -142,8 +224,8 @@ Add this configuration to your Claude Desktop config file:
142224
143225Add this configuration to your Claude Desktop config file:
144226
145- ** MacOS** : \ ` ~/Library/Application Support/Claude/claude_desktop_config.json\ `
146- ** Windows** : \ ` %APPDATA%/Claude/claude_desktop_config.json\ `
227+ **MacOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
228+ **Windows**: `%APPDATA%/Claude/claude_desktop_config.json`
147229
148230```json
149231{
@@ -159,7 +241,7 @@ Add this configuration to your Claude Desktop config file:
159241## Building and Testing
160242
1612431. Make changes to your tools
162- 2. Run \ ` npm run build\ ` to compile
244+ 2. Run `npm run build` to compile
1632453. The server will automatically load your tools on startup
164246
165247## Environment Variables
@@ -179,39 +261,170 @@ Example usage:
179261MCP_ENABLE_FILE_LOGGING=true node dist/index.js
180262
181263# Specify a custom log directory
182- MCP_ENABLE_FILE_LOGGING=true MCP_LOG_DIRECTORY=my-logs
264+ MCP_ENABLE_FILE_LOGGING=true MCP_LOG_DIRECTORY=my-logs node dist/index.js
265+
183266# Enable debug messages in console
184- MCP_DEBUG_CONSOLE=true` ` `
267+ MCP_DEBUG_CONSOLE=true node dist/index.js
268+ ```
185269
186270## Quick Start
187271
188- # ## Creating a Tool
272+ ### Defining Tools
273+
274+ MCP Framework uses Zod schemas for defining tool inputs, providing type safety, validation, and automatic documentation:
275+
276+ ```typescript
277+ import { MCPTool, McpInput } from "mcp-framework";
278+ import { z } from "zod";
279+
280+ const AddToolSchema = z.object({
281+ a: z.number().describe("First number to add"),
282+ b: z.number().describe("Second number to add"),
283+ });
284+
285+ class AddTool extends MCPTool {
286+ name = "add";
287+ description = "Add tool description";
288+ schema = AddToolSchema;
289+
290+ async execute(input: McpInput<this>) {
291+ const result = input.a + input.b;
292+ return `Result: ${result}`;
293+ }
294+ }
295+
296+ export default AddTool;
297+ ```
298+
299+ **Key Benefits:**
300+ - ✅ **Single source of truth** - Define types and validation in one place
301+ - ✅ **Automatic type inference** - TypeScript types are inferred from your schema
302+ - ✅ **Rich validation** - Leverage Zod' s powerful validation features
303+ - ✅ ** Required descriptions** - Framework enforces documentation
304+ - ✅ ** Better IDE support** - Full autocomplete and type checking
305+ - ✅ ** Cleaner code** - No duplicate type definitions
306+
307+ # ## Advanced Zod Schema Features
308+
309+ The framework supports all Zod features:
189310
190311` ` ` typescript
191- import { MCPTool } from " mcp-framework" ;
312+ import { MCPTool, McpInput } from " mcp-framework" ;
192313import { z } from " zod" ;
193314
194- interface ExampleInput {
195- message: string;
315+ const AdvancedSchema = z.object({
316+ // String constraints and formats
317+ email: z.string().email ().describe(" User email address" ),
318+ name: z.string ().min(2).max(50).describe(" User name" ),
319+ website: z.string().url().optional ().describe(" Optional website URL" ),
320+
321+ // Number constraints
322+ age: z.number().int().positive ().max(120).describe(" User age" ),
323+ rating: z.number ().min(1).max(5).describe(" Rating from 1 to 5" ),
324+
325+ // Arrays and objects
326+ tags: z.array(z.string ()).describe(" List of tags" ),
327+ metadata: z.object({
328+ priority: z.enum([' low' , ' medium' , ' high' ]).describe(" Task priority" ),
329+ dueDate: z.string().optional ().describe(" Due date in ISO format" )
330+ }).describe(" Additional metadata" ),
331+
332+ // Default values
333+ status: z.string ().default(' pending' ).describe(" Current status" ),
334+
335+ // Unions and enums
336+ category: z.union([
337+ z.literal(' personal' ),
338+ z.literal(' work' ),
339+ z.literal(' other' )
340+ ]).describe(" Category type" )
341+ });
342+
343+ class AdvancedTool extends MCPTool {
344+ name = " advanced_tool" ;
345+ description = " Tool demonstrating advanced Zod features" ;
346+ schema = AdvancedSchema;
347+
348+ async execute(input: McpInput< this> ) {
349+ // TypeScript automatically knows all the types!
350+ const { email, name, website, age, rating, tags, metadata, status, category } = input;
351+
352+ console.log(input.name.toUpperCase ()); // ✅ TypeScript knows this is valid
353+ console.log(input.age.toFixed(2)); // ✅ Number methods available
354+ console.log(input.tags.length); // ✅ Array methods available
355+ console.log(input.website? .includes(" https" )); // ✅ Optional handling
356+
357+ return ` Processed user: ${name} ` ;
358+ }
196359}
360+ ` ` `
197361
198- class ExampleTool extends MCPTool< ExampleInput> {
199- name = " example_tool" ;
200- description = " An example tool that processes messages" ;
362+ # ## Automatic Type Inference
201363
202- schema = {
203- message: {
204- type: z.string (),
205- description: " Message to process" ,
206- },
207- };
364+ The ` McpInput< this> ` type automatically infers the correct input type from your schema, eliminating the need for manual type definitions:
208365
209- async execute(input: ExampleInput) {
210- return ` Processed: ${input.message} ` ;
366+ ` ` ` typescript
367+ class MyTool extends MCPTool {
368+ schema = z.object({
369+ name: z.string ().describe(" User name" ),
370+ age: z.number().optional ().describe(" User age" ),
371+ tags: z.array(z.string ()).describe(" User tags" )
372+ });
373+
374+ async execute(input: McpInput< this> ) {
375+ // TypeScript automatically knows:
376+ // input.name is string
377+ // input.age is number | undefined
378+ // input.tags is string[]
379+
380+ console.log(input.name.toUpperCase ()); // ✅ TypeScript knows this is valid
381+ console.log(input.age? .toFixed(2)); // ✅ Handles optional correctly
382+ console.log(input.tags.length); // ✅ Array methods available
211383 }
212384}
385+ ` ` `
386+
387+ No more duplicate interfaces or generic type parameters needed!
388+
389+ # ## Schema Validation & Descriptions
390+
391+ ** All schema fields must have descriptions** . This ensures your tools are well-documented and provides better user experience in MCP clients.
392+
393+ The framework validates descriptions at multiple levels:
394+
395+ # ### 1. Build-time Validation (Recommended)
396+ ` ` ` bash
397+ npm run build # Automatically validates during compilation
398+ ` ` `
399+
400+ # ### 2. Development-time Validation
401+ Use the ` defineSchema` helper for immediate feedback:
402+
403+ ` ` ` typescript
404+ import { defineSchema } from " mcp-framework" ;
405+
406+ // This will throw an error immediately if descriptions are missing
407+ const MySchema = defineSchema({
408+ name: z.string (), // ❌ Error: Missing description
409+ age: z.number ().describe(" User age" ) // ✅ Good
410+ });
411+ ` ` `
412+
413+ # ### 3. Standalone Validation
414+ ` ` ` bash
415+ mcp validate # Check all tools for proper descriptions
416+ ` ` `
417+
418+ # ### 4. Runtime Validation
419+ The server automatically validates tools on startup.
420+
421+ ** To skip validation** (not recommended):
422+ ` ` ` bash
423+ # Skip during build
424+ MCP_SKIP_TOOL_VALIDATION=true npm run build
213425
214- export default ExampleTool;
426+ # Skip during development
427+ NODE_ENV=production npm run dev
215428` ` `
216429
217430# ## Setting up the Server
0 commit comments