MCP Server Template
A production-ready template for building Model Context Protocol servers using TypeScript and Bun runtime, including schema validation, structured logging, and retry utilities.
README
MCP Server Template
Production-ready MCP server template for building Model Context Protocol servers with TypeScript and Bun runtime.
What is this?
This is a template project for creating MCP servers. It includes:
- TypeScript with strict type checking
- Bun runtime for fast execution
- Zod schema validation
- Structured logging (stderr only)
- Retry utilities with exponential backoff
- Unit and integration test setup
- Production-ready error handling
Installation
bun install
Quick Start
# Start the MCP server
bun run start
# Development with hot reload
bun run dev
MCP Configuration
Add to your MCP client configuration:
{
"mcpServers": {
"mcp-server-template": {
"command": "bun",
"args": ["run", "/path/to/mcp-server-template/src/server.ts"]
}
}
}
Or use the built version:
{
"mcpServers": {
"mcp-server-template": {
"command": "node",
"args": ["/path/to/mcp-server-template/dist/server.js"]
}
}
}
Adding Tools
1. Define Schema
In src/types/index.ts:
import { z } from "zod";
export const MyToolInputSchema = z.object({
param1: z.string().min(1).describe("Parameter description"),
param2: z.number().optional().describe("Optional parameter"),
});
export type MyToolInput = z.infer<typeof MyToolInputSchema>;
2. Add Tool Definition
In src/tools/index.ts:
export const toolDefinitions = [
{
name: "my_tool",
description: "Description of what the tool does",
inputSchema: {
type: "object" as const,
properties: {
param1: { type: "string", description: "Parameter description" },
param2: { type: "number", description: "Optional parameter" },
},
required: ["param1"],
},
},
];
3. Implement Handler
export async function handleMyTool(input: unknown): Promise<CallToolResult> {
try {
const validated = MyToolInputSchema.parse(input);
log.info('Executing tool', { tool: 'my_tool', params: validated });
// Your logic here
const result = { data: "..." };
log.info('Tool completed', { tool: 'my_tool', success: true });
return createSuccessResult(result);
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
return createErrorResult(message, "my_tool");
}
}
4. Add to Router
export async function handleToolCall(name: string, args: unknown): Promise<CallToolResult> {
switch (name) {
case "my_tool":
return handleMyTool(args);
default:
return createErrorResult(`Unknown tool: ${name}`, name);
}
}
5. Write Tests
Create tests/unit/my_tool.test.ts:
import { describe, test, expect } from "bun:test";
import { handleMyTool } from "../../src/tools/index.js";
describe("My Tool", () => {
test("should work correctly", async () => {
const result = await handleMyTool({ param1: "test" });
expect(result.isError).toBe(false);
});
});
6. Document Tool
Create docs/tools/my_tool.md:
# my_tool
Description of what the tool does.
## Parameters
| Name | Type | Required | Description |
|------|------|----------|-------------|
| param1 | string | Yes | Description |
## Examples
**Input:**
\`\`\`json
{ "param1": "value" }
\`\`\`
**Output:**
\`\`\`json
{ "data": "result" }
\`\`\`
Available Scripts
| Script | Description |
|---|---|
bun run dev |
Start development server with hot reload |
bun run build |
Build for production |
bun run start |
Run production build |
bun test |
Run unit tests |
bun run test:coverage |
Run tests with coverage |
bun run test:runtime |
Run runtime testcases |
bun run lint |
Run Biome linter |
bun run lint:fix |
Auto-fix lint issues |
bun run format |
Format code with Biome |
bun run typecheck |
Type check without emit |
Configuration
Environment Variables
DEBUG=true- Enable debug logging
Troubleshooting
Server won't start
- Ensure Bun is installed:
bun --version - Check TypeScript errors:
bun run typecheck
Tool execution fails
- Check input schema matches the tool definition
- Enable debug mode:
DEBUG=true bun run start
Development
See DEVELOPMENT.md for development setup.
License
MIT License - see LICENSE for details.
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.