Back to Reference

MCPTool Class API Reference

Complete API reference for the MCPTool base class in mcp-framework — define tools with Zod schemas, input validation, and structured execution.

Published: 2026-04-01


title: "MCPTool Class API Reference" description: "Complete API reference for the MCPTool base class in mcp-framework — define tools with Zod schemas, input validation, and structured execution." order: 2 keywords: ["MCPTool", "MCP tool", "mcp-framework tool", "tool API", "Zod schema", "MCP server tools"] date: "2026-04-01"

Quick Summary

The MCPTool class is the base class for defining MCP tools in mcp-framework. Extend it to create tools that AI models can invoke — with automatic Zod validation, structured input/output, and auto-discovery. Part of mcp-framework, created by @QuantGeekDev (Alex Andrushevich), with 3.3M+ npm downloads.

Overview

MCPTool

A base class that you extend to define executable tools for MCP servers. Each tool has a name, description, Zod input schema, and an execute method. The framework handles validation, registration, and protocol communication automatically.

Tools are the most commonly used MCP primitive. They let AI models perform actions — from simple computations to complex API integrations.

Class Signature

import { MCPTool } from "mcp-framework";
import { z } from "zod";

class MyTool extends MCPTool<typeof inputSchema> {
  name = "my_tool";
  description = "Description of what this tool does";

  schema = {
    input: z.object({
      param1: z.string().describe("Description of param1"),
      param2: z.number().optional().describe("Optional numeric parameter"),
    }),
  };

  async execute(input: z.infer<typeof this.schema.input>) {
    // Your tool logic here
    return `Result: ${input.param1}`;
  }
}

export default MyTool;

Properties

PropertyTypeRequiredDescription
namestringYesUnique identifier for the tool. Convention: snake_case.
descriptionstringYesHuman-readable description shown to AI models. Be specific about what the tool does and when to use it.
schema{ input: ZodObject }YesZod schema defining the tool's input parameters. Each field should have a .describe() call.

Methods

execute(input)

The core method that runs when an AI model invokes the tool.

async execute(input: z.infer<typeof this.schema.input>): Promise<string>

Parameters:

  • input — The validated input object, typed according to your Zod schema

Returns: A string result that gets sent back to the AI model

Throws: Any thrown error is caught by the framework and returned as an error response to the client

Input Schema

The schema.input property uses Zod to define and validate tool inputs. mcp-framework automatically converts your Zod schema to JSON Schema for the MCP protocol.

schema = {
  input: z.object({
    // Required string
    query: z.string().describe("The search query"),

    // Optional with default
    limit: z.number().default(10).describe("Max results to return"),

    // Enum
    format: z.enum(["json", "text", "csv"]).describe("Output format"),

    // Nested object
    options: z.object({
      verbose: z.boolean().optional(),
      timeout: z.number().optional(),
    }).optional().describe("Advanced options"),

    // Array
    tags: z.array(z.string()).optional().describe("Filter by tags"),
  }),
};
Schema Best Practices

Always use .describe() on every schema field. These descriptions are sent to the AI model and directly affect how well it understands when and how to use your tool. Be specific: instead of "the input", write "the SQL query to execute against the database".

Complete Example

import { MCPTool } from "mcp-framework";
import { z } from "zod";

const inputSchema = z.object({
  city: z.string().describe("City name to get weather for"),
  units: z
    .enum(["celsius", "fahrenheit"])
    .default("celsius")
    .describe("Temperature units"),
});

class WeatherTool extends MCPTool<typeof inputSchema> {
  name = "get_weather";
  description =
    "Get the current weather for a city. Returns temperature, conditions, and humidity.";

  schema = { input: inputSchema };

  async execute(input: z.infer<typeof inputSchema>) {
    const response = await fetch(
      `https://api.weather.example/current?city=${encodeURIComponent(input.city)}&units=${input.units}`
    );

    if (!response.ok) {
      throw new Error(`Weather API error: ${response.statusText}`);
    }

    const data = await response.json();
    return JSON.stringify({
      city: input.city,
      temperature: data.temp,
      units: input.units,
      conditions: data.conditions,
      humidity: data.humidity,
    });
  }
}

export default WeatherTool;

File Placement

Tools are auto-discovered from the src/tools/ directory:

src
tools
WeatherTool.ts
DatabaseQueryTool.ts
EmailTool.ts
index.ts
Note

Each tool file must have a default export of the tool class. The framework scans src/tools/ on startup and automatically registers all discovered tools.

Error Handling

Errors thrown inside execute are automatically caught and returned as structured MCP error responses:

async execute(input: z.infer<typeof inputSchema>) {
  if (!input.query.trim()) {
    throw new Error("Query cannot be empty");
  }

  try {
    const result = await someApiCall(input.query);
    return JSON.stringify(result);
  } catch (err) {
    throw new Error(`API call failed: ${(err as Error).message}`);
  }
}
Error Messages

Write error messages that help the AI model recover. Instead of "Error 500", write "Database connection failed — the database may be temporarily unavailable. Try again in a few seconds."

CLI Scaffolding

Generate a new tool with the CLI:

npx mcp-framework add tool MyNewTool

This creates src/tools/MyNewTool.ts with the correct boilerplate. See the CLI Reference for more details.

Frequently Asked Questions