How the Request Schema is Defined and Validated Using Zod in the MCP Tool

The deepwiki-mcp repository uses Zod schemas in src/schemas/deepwiki.ts to declaratively define request shapes, then validates incoming tool calls at runtime using safeParse before processing them.

The Model Context Protocol (MCP) tools in the regenrek/deepwiki-mcp repository rely on Zod to enforce type safety and data integrity. By defining the request schema using Zod, the codebase ensures that every incoming tool request matches the expected structure before any business logic executes.

Defining the Zod Request Schema in deepwiki-mcp

All request schemas reside in src/schemas/deepwiki.ts, where they combine TypeScript type inference with runtime validation constraints.

Core FetchRequest Schema

The primary FetchRequest schema defines the contract for the deepwiki_fetch tool:

// src/schemas/deepwiki.ts
export const ModeEnum = z.enum(['aggregate', 'pages'])

export const FetchRequest = z.object({
  /** Deepwiki repo URL, eg https://deepwiki.com/user/repo */
  url: z.string()
    .describe('URL, owner/repo, two‑word form, or a keyword'),
  /** Crawl depth limit: 0 = only root page */
  maxDepth: z.number().int().min(0).max(1).default(1)
    .describe('maxDepth 0 → single site, 1 → all sites'),
  /** Conversion mode */
  mode: ModeEnum.default('aggregate'),
  /** Verbose logging flag */
  verbose: z.boolean().default(false),
})

Key constraints include:

  • maxDepth is restricted to integers between 0 and 1 with a default of 1
  • mode must be either 'aggregate' or 'pages'
  • All fields include .describe() metadata for MCP client documentation

Extending Schemas for Search Functionality

The search tool extends the base schema rather than duplicating it. In src/tools/deepwikiSearch.ts, the SearchRequest inherits from FetchRequest and adds search-specific fields:

// src/tools/deepwikiSearch.ts
const SearchRequest = FetchRequest.extend({
  /** Case‑insensitive literal search term */
  query: z.string().min(1, 'query cannot be empty'),
  /** Hard cap on snippets to return (default 10) */
  maxMatches: z.number().int().positive().max(100).default(10),
})

This pattern ensures that search requests inherit all validation rules from fetch requests (like maxDepth constraints) while adding their own specific requirements, such as query being a non-empty string.

Runtime Validation with Zod safeParse

Defining the schema is only half the implementation. The tools validate every incoming request at runtime using Zod's safeParse method.

Normalizing Input Before Validation

In src/tools/deepwiki.ts, the implementation first normalizes the raw input (for example, converting shorthand repository names like vercel/ai into full URLs) before passing it to the validator:

// src/tools/deepwiki.ts
const normalizedInput = normalizeUrl(input.url) // Custom normalization logic
const parse = FetchRequest.safeParse(normalizedInput)

Handling Validation Errors with ErrorEnvelope

If validation fails, the tool returns a structured error object rather than throwing an unhandled exception. The ErrorEnvelope schema (also defined in src/schemas/deepwiki.ts) standardizes error responses:

// src/tools/deepwiki.ts
if (!parse.success) {
  const err: z.infer<typeof ErrorEnvelope> = {
    status: 'error',
    code: 'VALIDATION',
    message: 'Request failed schema validation',
    details: parse.error.flatten(), // Structured Zod error details
  }
  return err
}

The parse.error.flatten() method produces a machine-readable error structure that MCP clients can display to users, showing exactly which fields failed validation and why.

Registering Validated Tools with the MCP Server

When registering tools with the MCP server, the implementation exposes the schema's shape (not the Zod object itself) so that the protocol can communicate the expected parameters to clients:

// src/tools/deepwiki.ts
mcp.tool(
  'deepwiki_fetch',
  'Fetch a deepwiki.com repo and return Markdown',
  FetchRequest.shape,  // Exposes the schema structure to MCP
  async (input) => {
    // Implementation uses safeParse as shown above
  }
)

The FetchRequest.shape property provides a JSON-serializable description of the schema that MCP clients use to render input forms or validate requests client-side before sending them to the server.

Summary

  • Schema Location: All Zod schemas are defined in src/schemas/deepwiki.ts, including FetchRequest, SearchRequest, and ModeEnum.
  • Extension Pattern: The search tool in src/tools/deepwikiSearch.ts uses FetchRequest.extend() to inherit base validation while adding query-specific fields.
  • Runtime Safety: Both tools use safeParse() to validate normalized input, returning structured ErrorEnvelope objects on validation failures rather than throwing exceptions.
  • MCP Integration: Tools register their schemas using FetchRequest.shape to expose parameter requirements to MCP clients, while .describe() calls provide human-readable documentation.

Frequently Asked Questions

How does the MCP tool handle invalid request parameters?

When a request fails validation, the tool uses Zod's safeParse method to catch errors gracefully. Instead of crashing, it returns a structured ErrorEnvelope object containing the error code VALIDATION, a descriptive message, and detailed field-level errors via parse.error.flatten(). This allows MCP clients to display precise feedback about which parameters are invalid and why.

What is the difference between FetchRequest and SearchRequest schemas?

FetchRequest is the base schema defined in src/schemas/deepwiki.ts that handles repository fetching with fields like url, maxDepth, and mode. SearchRequest extends this base schema in src/tools/deepwikiSearch.ts using Zod's .extend() method, adding query (a required non-empty string) and maxMatches (a positive integer capped at 100). This inheritance ensures search requests maintain all base validation rules while adding search-specific constraints.

Why does the tool use safeParse instead of parse?

The implementation chooses safeParse over parse to avoid throwing exceptions during request handling. Since MCP tools must return structured responses that clients can process programmatically, throwing would break the protocol contract. safeParse returns a discriminated union that allows the tool to check parse.success and, if false, construct a proper ErrorEnvelope response with validation details. This approach maintains stability and provides actionable error information to API consumers.

Where are the default values for request parameters defined?

Default values are declared directly in the Zod schema definitions within src/schemas/deepwiki.ts. For example, maxDepth uses .default(1) to default to crawling all sites, mode defaults to 'aggregate' via ModeEnum.default('aggregate'), and verbose defaults to false. These defaults are applied automatically by Zod during the safeParse call, ensuring that omitted fields receive sensible values before the tool logic executes.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →