A boilerplate template for creating Model Context Protocol (MCP) servers with TypeScript. This template provides a modular architecture for building custom tools that can be used with MCP-compatible LLM clients such as Claude, Roo, or Cursor. The server communicates over standard input/output (stdio).
Follow these steps to set up your MCP server:
- Clone this template
git clone <your-repo-url>
cd template-mcp- Install dependencies
yarn install- Build the project
yarn buildThis compiles the TypeScript source files and prepares the build to be accessed from MCP clients.
- Customize your tools
- Rename the
your-modulefolder to match your domain (e.g.,weather,database,api-client) - Edit
src/your-module/service.tsto implement your business logic - Update
src/your-module/tools.tsto define your tool schemas and handlers - Register your tools in
src/index.ts
The template includes a sample tool that generates random names. You can test it immediately:
# Build and run the server
yarn build
node ./build/index.jsThen configure your MCP client to use this server.
You can use this project as an MCP server backend for clients like Claude, Roo, or Cursor.
node ./build/index.jsThe server communicates over stdio by default.
Configure your MCP-compatible client to connect via stdio to this server executable. For example, in Claude Desktop, Roo, or Cursor, add this configuration:
{
"mcpServers": {
"my-custom-server": {
"command": "node",
"args": [
"/path/to/your/template-mcp/build/index.js"
],
"alwaysAllow": [
"get_random_name"
],
"disabled": false
}
}Replace /path/to/your/template-mcp/build/index.js with the actual path to your built server, and update the alwaysAllow array with your custom tool names.
This will enable the client to discover and use the tools provided by your server.
This template follows a modular architecture that makes it easy to add new tools:
Create a new folder under src/ for your feature domain:
src/
└── weather/ # Your new module
├── service.ts # Business logic
└── tools.ts # Tool definitions
// src/weather/service.ts
export const getCurrentWeather = async (location: string): Promise<string> => {
// Your business logic here
const response = await fetch(`https://api.weather.com/v1/current?location=${location}`);
const data = await response.json();
return `Weather in ${location}: ${data.temperature}°F`;
};// src/weather/tools.ts
import { z } from "zod";
import { ToolRegistrationOptions } from "../utils/registerTool.js";
import { getCurrentWeather } from "./service.js";
const weatherHandler = async ({ location }: { location: string }) => {
const weather = await getCurrentWeather(location);
return {
content: [
{
type: "text",
text: weather,
},
],
};
};
export const toolWeather: ToolRegistrationOptions = {
toolName: "get_current_weather",
toolDescription: "Get current weather for a specified location.",
inputSchema: {
location: z.string().describe("The location to get weather for"),
},
toolHandler: weatherHandler
};Add your tool to src/index.ts:
import { toolWeather } from "./weather/tools.js";
// Register All Tools
[
toolRandomName, // existing example tool
toolWeather // your new tool
].forEach((tool) => registerTool(server, tool));template-mcp/
├── package.json # Project dependencies and scripts
├── tsconfig.json # TypeScript configuration
├── build/ # Compiled JavaScript output
├── script/ # Development/test scripts
└── src/
├── index.ts # Entry point: creates MCP server, registers tools
├── utils/
│ └── registerTool.ts # Generic tool registration utility
└── your-module/ # Example module (rename for your domain)
├── service.ts # Business logic implementation
└── tools.ts # Tool schema and handler definitions
- Modular Design: Each feature is organized in its own folder with separate service logic and tool definitions
- Type Safety: Full TypeScript support with Zod schemas for input validation
- Easy Registration: Simple tool registration system using the
ToolRegistrationOptionsinterface - Extensible: Add new tools by creating new modules and registering them
src/index.tsinitializes the MCP server and imports tool modules.- Each feature module (e.g.,
cohort,info,etc) exports atools.tsfile containing one or more tool definitions conforming to theToolRegistrationOptionsinterface. - The
registerToolfunction insrc/utils/registerTool.tsis a generic utility that registers a tool with the MCP server. - Tools are registered by calling:
registerTool(server, toolModule);where toolModule contains:
{
toolName: string,
toolDescription: string,
inputSchema: JSON schema or zod schema,
toolHandler: async function(args)
}This design allows easy addition of new tools by creating a new module and registering it in src/index.ts.
yarn build- Compile TypeScript to JavaScriptyarn test:service- Test service layer functionalityyarn test:tools- Test tool definitions and schemasyarn test:integration- Run integration testsyarn test:all- Run all tests
The template includes test scripts to help validate your tools:
- Service Tests: Test your business logic independently
- Tool Tests: Validate tool schemas and handlers
- Integration Tests: Test the complete MCP server functionality
- Update
package.jsonwith your project details - Build the project:
yarn build - Publish:
npm publish
- Build the project:
yarn build - Use the compiled
build/index.jsdirectly in your MCP client configuration
- Fork this repository
- Create your feature branch:
git checkout -b feature/amazing-tool - Commit your changes:
git commit -m 'Add amazing tool' - Push to the branch:
git push origin feature/amazing-tool - Open a Pull Request
This project is licensed under the ISC License.
For questions or support, contact me at ans4175@gmail.com.