# How to Add New Tools to the MCP Everything Reference Server

> Learn to add new tools to the MCP Everything reference server. Our guide shows you how to register custom tools using TypeScript in your repository.

- Repository: [Model Context Protocol/servers](https://github.com/modelcontextprotocol/servers)
- Tags: how-to-guide
- Published: 2026-03-01

---

**To add new tools to the MCP Everything reference server, create a TypeScript file in `src/everything/tools/` that exports a registration function calling `server.registerTool()`, then import and invoke that function in [`src/everything/tools/index.ts`](https://github.com/modelcontextprotocol/servers/blob/main/src/everything/tools/index.ts) to wire it into the startup lifecycle.**

The Everything reference server in the `modelcontextprotocol/servers` repository demonstrates the canonical pattern for extending Model Context Protocol (MCP) servers with custom functionality. Adding new tools requires understanding the two-phase registration lifecycle that separates unconditional tool availability from capability-dependent conditional exposure.

## Understanding the Tool Registration Architecture

The Everything server builds on the official **MCP SDK**, where the `McpServer` instance maintains the tool registry. Tool registration follows a strict lifecycle defined in [`src/everything/tools/index.ts`](https://github.com/modelcontextprotocol/servers/blob/main/src/everything/tools/index.ts): unconditional tools register immediately during server creation, while conditional tools register only after the client reports its capabilities via the `notifications/initialized` event.

According to the source code, every tool must provide a **name**, **title**, **description**, **input schema** (Zod-based), and an async **handler** that returns a `CallToolResult`. The server factory in [`src/everything/server/index.ts`](https://github.com/modelcontextprotocol/servers/blob/main/src/everything/server/index.ts) orchestrates these registration phases during the `createServer` initialization sequence.

## Creating a New Tool Definition

### Step 1: Implement the Tool Handler

Create a new file in `src/everything/tools/` that defines your tool's schema and business logic. The file must export a `registerXTool(server)` function that invokes the SDK's registration API.

```typescript
// src/everything/tools/multiply.ts
import { z } from "zod";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";

const MultiplySchema = z.object({
  a: z.number().describe("First factor"),
  b: z.number().describe("Second factor"),
});

const name = "multiply";
const config = {
  title: "Multiply Numbers",
  description: "Returns the product of two numbers",
  inputSchema: MultiplySchema,
};

export const registerMultiplyTool = (server: McpServer) => {
  server.registerTool(name, config, async (args): Promise<CallToolResult> => {
    const { a, b } = MultiplySchema.parse(args);
    const product = a * b;
    return {
      content: [{ type: "text", text: `🧮 ${a} × ${b} = ${product}` }],
    };
  });
};

```

### Step 2: Export the Registration Function

The `registerMultiplyTool` function receives the `McpServer` instance and calls `server.registerTool(name, config, handler)`. This pattern isolates tool implementation from server configuration, allowing the aggregation layer in [`src/everything/tools/index.ts`](https://github.com/modelcontextprotocol/servers/blob/main/src/everything/tools/index.ts) to control when and how tools are exposed.

## Wiring Tools into the Server Lifecycle

### Unconditional Registration via `registerTools()`

Unconditional tools are always available regardless of client capabilities. The `registerTools(server)` function in [`src/everything/tools/index.ts`](https://github.com/modelcontextprotocol/servers/blob/main/src/everything/tools/index.ts) (lines 25-38) runs once during server startup, immediately after the `McpServer` instantiation.

```typescript
// src/everything/tools/index.ts
import { registerMultiplyTool } from "./multiply.js";

export const registerTools = (server: McpServer) => {
  // existing registrations …
  registerMultiplyTool(server);          // <-- new line
};

```

This aggregation pattern ensures that `createServer` in [`src/everything/server/index.ts`](https://github.com/modelcontextprotocol/servers/blob/main/src/everything/server/index.ts) can register all baseline tools with a single function call.

### Conditional Registration via `registerConditionalTools()`

Some tools require specific client capabilities (e.g., sampling support or advanced math features). These register later via `registerConditionalTools(server)`, which executes after the client sends its `notifications/initialized` event. As implemented in lines 44-53 of [`src/everything/tools/index.ts`](https://github.com/modelcontextprotocol/servers/blob/main/src/everything/tools/index.ts), this function checks `server.server.getClientCapabilities()` before exposing restricted functionality.

```typescript
export const registerConditionalTools = (server: McpServer) => {
  // existing conditional tools …
  const caps = server.server.getClientCapabilities() ?? {};
  if (caps.advancedMath) {
    registerMultiplyTool(server);
  }
};

```

## Server Startup Integration

The `createServer` function in [`src/everything/server/index.ts`](https://github.com/modelcontextprotocol/servers/blob/main/src/everything/server/index.ts) instantiates the `McpServer` and orchestrates the registration sequence. It immediately calls `registerTools(server)` after creation, then binds `registerConditionalTools(server)` to the server's `oninitialized` callback. This guarantees that tools appear at the correct moment in the MCP session lifecycle—unconditional tools at startup, conditional tools after capability negotiation.

The project documentation at [`src/everything/docs/extension.md`](https://github.com/modelcontextprotocol/servers/blob/main/src/everything/docs/extension.md) provides additional guidance on the "Adding Tools" workflow, pointing developers to the exact file locations and patterns described above.

## Summary

- Create tool files in `src/everything/tools/` exporting a `registerXTool(server)` function that calls `server.registerTool(name, config, handler)` with Zod-defined schemas
- Import and invoke registration functions in `registerTools()` at lines 25-38 of [`src/everything/tools/index.ts`](https://github.com/modelcontextprotocol/servers/blob/main/src/everything/tools/index.ts) for unconditional, always-available tools
- Use `registerConditionalTools()` at lines 44-53 of the same file for capability-dependent tools, checking `server.server.getClientCapabilities()` before registration
- The server factory in [`src/everything/server/index.ts`](https://github.com/modelcontextprotocol/servers/blob/main/src/everything/server/index.ts) orchestrates both phases during the `createServer` initialization sequence, ensuring tools appear at the correct lifecycle moment

## Frequently Asked Questions

### What is the difference between `registerTools()` and `registerConditionalTools()`?

`registerTools()` runs immediately during server startup and registers tools available to all clients regardless of capabilities. `registerConditionalTools()` executes only after the client sends the `notifications/initialized` event, allowing dynamic tool exposure based on reported client capabilities like sampling support or custom extensions.

### Where should I place my new tool implementation files?

Create a new TypeScript file in `src/everything/tools/` (e.g., [`src/everything/tools/multiply.ts`](https://github.com/modelcontextprotocol/servers/blob/main/src/everything/tools/multiply.ts)) following the `registerXTool(server)` export pattern established by existing reference implementations like [`get-sum.ts`](https://github.com/modelcontextprotocol/servers/blob/main/get-sum.ts). Each file should isolate one tool's schema, configuration, and handler logic.

### How does the server know when to register conditional tools?

The `createServer` function in [`src/everything/server/index.ts`](https://github.com/modelcontextprotocol/servers/blob/main/src/everything/server/index.ts) binds `registerConditionalTools(server)` to the `McpServer` instance's `oninitialized` callback. This ensures the function only executes after the MCP client completes capability negotiation, preventing exposure of tools the client cannot support.

### Can I use libraries like Zod for input validation?

Yes, the MCP SDK integrates natively with Zod for runtime input validation. Define your parameters using `z.object()` and pass the schema to the `inputSchema` property in the tool configuration. The SDK validates incoming arguments against this schema before invoking your handler, as demonstrated in the [`multiply.ts`](https://github.com/modelcontextprotocol/servers/blob/main/multiply.ts) example.