@@ -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,75 @@ 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+ // 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+ ` ` `
113180
181+ 4. ** Build with automatic validation:**
114182 ` ` ` bash
115- npm run build
183+ npm run build # Automatically validates schemas and compiles
184+ ` ` `
116185
186+ 5. ** Optional: Run standalone validation:**
187+ ` ` ` bash
188+ mcp validate # Check all tools independently
117189 ` ` `
118190
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
120203
121204## Using with Claude Desktop
122205
123206### Local Development
124207
125208Add this configuration to your Claude Desktop config file:
126209
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`
129212
130213```json
131214{
@@ -142,8 +225,8 @@ Add this configuration to your Claude Desktop config file:
142225
143226Add this configuration to your Claude Desktop config file:
144227
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`
147230
148231```json
149232{
@@ -159,7 +242,7 @@ Add this configuration to your Claude Desktop config file:
159242## Building and Testing
160243
1612441. Make changes to your tools
162- 2. Run \ ` npm run build\ ` to compile
245+ 2. Run `npm run build` to compile
1632463. The server will automatically load your tools on startup
164247
165248## Environment Variables
@@ -179,39 +262,170 @@ Example usage:
179262MCP_ENABLE_FILE_LOGGING=true node dist/index.js
180263
181264# 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+
183267# Enable debug messages in console
184- MCP_DEBUG_CONSOLE=true` ` `
268+ MCP_DEBUG_CONSOLE=true node dist/index.js
269+ ```
185270
186271## Quick Start
187272
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:
189311
190312` ` ` typescript
191- import { MCPTool } from " mcp-framework" ;
313+ import { MCPTool, McpInput } from " mcp-framework" ;
192314import { z } from " zod" ;
193315
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+ }
196360}
361+ ` ` `
197362
198- class ExampleTool extends MCPTool< ExampleInput> {
199- name = " example_tool" ;
200- description = " An example tool that processes messages" ;
363+ # ## Automatic Type Inference
201364
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:
208366
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
211384 }
212385}
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
213426
214- export default ExampleTool;
427+ # Skip during development
428+ NODE_ENV=production npm run dev
215429` ` `
216430
217431# ## Setting up the Server
0 commit comments