# How to Add a New Tool to the Revit MCP Server Using Dynamic Registration

> Easily add new tools to your revit-mcp server with dynamic registration. Learn how to create a TypeScript file and register tools using server.tool() for seamless integration.

- Repository: [MCP servers for Revit/revit-mcp](https://github.com/mcp-servers-for-revit/revit-mcp)
- Tags: how-to-guide
- Published: 2026-02-16

---

**You can add a new tool to the revit-mcp server by creating a TypeScript file in `src/tools/` that exports a function named `register[ToolName]Tool`, which receives an `McpServer` instance and calls `server.tool()` with your tool's ID, Zod schema, and async handler.**

The revit-mcp repository implements a **dynamic registration** system that eliminates manual registry updates when extending server capabilities. This architecture allows you to add a new tool to the MCP server using dynamic registration simply by dropping a properly structured file into the tools directory, where it is automatically discovered and loaded at runtime.

## How Dynamic Registration Works in revit-mcp

The dynamic registration pipeline operates through a convention-based discovery mechanism implemented in [`src/tools/register.ts`](https://github.com/mcp-servers-for-revit/revit-mcp/blob/main/src/tools/register.ts). When the server initializes in [`src/index.ts`](https://github.com/mcp-servers-for-revit/revit-mcp/blob/main/src/index.ts), it invokes `registerTools(server)`, which performs the following steps:

1. **Directory Scanning**: Reads the contents of the `src/tools/` directory, excluding its own file and any non-TypeScript/JavaScript files.
2. **Dynamic Import**: Uses `import()` to load each tool module asynchronously.
3. **Function Detection**: Searches for an exported function whose name starts with `register` (e.g., `registerEchoTool`).
4. **Registration Invocation**: Calls the discovered function, passing the `McpServer` instance, which then executes `server.tool()` to make the tool available to MCP clients.

This approach ensures that adding a new tool requires zero changes to central configuration files.

## Step-by-Step Guide to Adding a New Tool

Follow these steps to implement and register a new tool using the dynamic registration system.

### 1. Create the Tool File in `src/tools/`

Create a new TypeScript file in the `src/tools/` directory. Use a descriptive filename that reflects the tool's purpose, such as [`my_new_tool.ts`](https://github.com/mcp-servers-for-revit/revit-mcp/blob/main/my_new_tool.ts) or [`echo.ts`](https://github.com/mcp-servers-for-revit/revit-mcp/blob/main/echo.ts).

### 2. Export a Registration Function Following the Naming Convention

Your file must export a single function whose name follows the pattern `register[ToolName]Tool`. The registration system specifically looks for functions starting with `register`. The function signature must accept an `McpServer` instance:

```typescript
export function registerMyNewToolTool(server: McpServer) {
  // Registration logic here
}

```

### 3. Define the Tool Schema and Handler

Inside your registration function, call `server.tool()` with four arguments:

- **Tool ID**: A unique string identifier (e.g., `"my_new_tool"`)
- **Description**: A human-readable explanation of what the tool does
- **Zod Schema**: An object defining and validating the tool's arguments using **Zod**
- **Async Handler**: An async function implementing the tool's logic, usually utilizing `withRevitConnection` or other utilities from [`src/utils/ConnectionManager.ts`](https://github.com/mcp-servers-for-revit/revit-mcp/blob/main/src/utils/ConnectionManager.ts) to communicate with Revit

### 4. Save and Restart the Server

Save your file. No additional imports or registry updates are required. When the server restarts, [`src/tools/register.ts`](https://github.com/mcp-servers-for-revit/revit-mcp/blob/main/src/tools/register.ts) automatically discovers your file, imports the module, detects your `register*` function, and invokes it to register the tool.

## Complete Example: Creating an Echo Tool

Here is a complete, runnable example demonstrating how to implement a simple "echo" tool that returns the input text unchanged.

Create [`src/tools/echo.ts`](https://github.com/mcp-servers-for-revit/revit-mcp/blob/main/src/tools/echo.ts):

```typescript
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";

/**
 * Registers the `echo` tool.
 * The tool simply returns the received message.
 */
export function registerEchoTool(server: McpServer) {
  server.tool(
    "echo",                                   // ← tool ID
    "Returns the supplied text unchanged.",   // ← description
    {
      // ← argument validation with Zod
      message: z.string().describe("Text to echo back"),
    },
    // ← async handler
    async (args) => ({
      content: [
        { type: "text", text: `🗣️ ${args.message}` },
      ],
    })
  );
}

```

When the server initializes, [`src/tools/register.ts`](https://github.com/mcp-servers-for-revit/revit-mcp/blob/main/src/tools/register.ts) performs the following sequence:

1. Reads the `src/tools` directory and identifies [`echo.ts`](https://github.com/mcp-servers-for-revit/revit-mcp/blob/main/echo.ts).
2. Dynamically imports [`./echo.js`](https://github.com/mcp-servers-for-revit/revit-mcp/blob/main/./echo.js) (the compiled output).
3. Detects the exported `registerEchoTool` function (matching the `register*` pattern).
4. Invokes `registerEchoTool(server)`, making the `echo` tool available to MCP clients.

## Key Files in the Dynamic Registration Pipeline

Understanding these core files helps you debug and extend the registration system:

- **[`src/tools/register.ts`](https://github.com/mcp-servers-for-revit/revit-mcp/blob/main/src/tools/register.ts)**: Implements the discovery logic. It scans the tools directory, filters for TypeScript/JavaScript files, dynamically imports each module, searches for exported functions starting with `register`, and invokes them with the `McpServer` instance.

- **[`src/index.ts`](https://github.com/mcp-servers-for-revit/revit-mcp/blob/main/src/index.ts)**: The server entry point. It instantiates the `McpServer`, calls `registerTools(server)` to trigger the dynamic registration process, and connects the server to the stdio transport.

- **[`src/tools/tag_all_walls.ts`](https://github.com/mcp-servers-for-revit/revit-mcp/blob/main/src/tools/tag_all_walls.ts)**: A production-ready example demonstrating complex tool implementation, including Zod schema definitions, Revit connection handling via `withRevitConnection`, error handling, and structured response formatting.

- **[`src/utils/ConnectionManager.ts`](https://github.com/mcp-servers-for-revit/revit-mcp/blob/main/src/utils/ConnectionManager.ts)**: Provides the `withRevitConnection` utility used by most tools to establish and manage communication with the Revit application.

## Summary

- **Dynamic registration** in revit-mcp eliminates manual registry updates by automatically discovering tools in `src/tools/` at runtime.
- To add a tool, create a file in `src/tools/` and export a function named `register[ToolName]Tool` that calls `server.tool()` with a Zod schema and async handler.
- The registration system in [`src/tools/register.ts`](https://github.com/mcp-servers-for-revit/revit-mcp/blob/main/src/tools/register.ts) scans the directory, dynamically imports modules, and invokes any function starting with `register`, passing the `McpServer` instance.
- No changes to [`src/index.ts`](https://github.com/mcp-servers-for-revit/revit-mcp/blob/main/src/index.ts) or central configuration files are required when adding, removing, or modifying tools.

## Frequently Asked Questions

### What naming convention must the registration function follow?

The function must start with the prefix `register` and end with `Tool`, following the pattern `register[ToolName]Tool` (e.g., `registerEchoTool` or `registerTagAllWallsTool`). The dynamic registration system in [`src/tools/register.ts`](https://github.com/mcp-servers-for-revit/revit-mcp/blob/main/src/tools/register.ts) specifically searches for exported functions matching this prefix and invokes them automatically.

### Do I need to modify any central registry files when adding a new tool?

No. The dynamic registration architecture requires zero changes to central files like [`src/index.ts`](https://github.com/mcp-servers-for-revit/revit-mcp/blob/main/src/index.ts) or [`src/tools/register.ts`](https://github.com/mcp-servers-for-revit/revit-mcp/blob/main/src/tools/register.ts). Simply create your tool file in `src/tools/`, export the registration function, and restart the server. The discovery mechanism automatically imports your module and registers the tool with the `McpServer` instance.

### How does the server validate tool arguments?

The server uses **Zod** schemas for runtime type validation and type safety. When calling `server.tool()` inside your registration function, you pass a Zod object defining the expected arguments (e.g., `{ message: z.string() }`). The MCP SDK automatically validates incoming requests against this schema before invoking your async handler, ensuring type-safe communication between clients and the Revit server.

### Can I organize tools into subdirectories within `src/tools/`?

The current implementation in [`src/tools/register.ts`](https://github.com/mcp-servers-for-revit/revit-mcp/blob/main/src/tools/register.ts) scans only the immediate `src/tools/` directory, skipping non-TypeScript/JavaScript files and its own file. It does not recursively traverse subdirectories. To ensure your tool is discovered, place it directly in `src/tools/` rather than in nested folders, or modify the discovery logic in [`src/tools/register.ts`](https://github.com/mcp-servers-for-revit/revit-mcp/blob/main/src/tools/register.ts) to support recursive scanning.