MCP TypeScript Server Template
A template repository for building Model Context Protocol (MCP) servers with TypeScript, featuring full TypeScript support, testing setup, CI/CD pipelines, and modular architecture for easy extension.
README
MCP MCP Server
An MCP (Model Context Protocol) server implementation with TypeScript.
Features
- 🚀 Full TypeScript support with strict mode
- 🧪 Testing setup with Vitest and coverage reporting
- 📦 Automated releases with semantic-release
- 🔄 CI/CD pipelines with GitHub Actions
- 🏗️ Modular architecture for easy extension
- 📝 Comprehensive documentation and examples
- 🛠️ Development tools: Biome for linting/formatting, Husky for Git hooks
- 🎯 Pre-configured for MCP server development
- 🔐 Built-in validation using Zod schemas
- ⚡ ES modules with native Node.js support
- 📊 Code coverage reporting with c8
MCP Servers Built with This Template
Here are some MCP servers built using this template:
Wayback Machine MCP
Archive and retrieve web pages using the Internet Archive's Wayback Machine. No API keys required.
OpenAlex MCP
Access scholarly articles and research data from the OpenAlex database.
Building an MCP server? Use this template and add your server to this list!
Quick Start
Using GitHub Template
- Click "Use this template" button on GitHub
- Clone your new repository
- Install dependencies:
yarn install - Start development:
yarn dev
Manual Setup
# Clone the template
git clone https://github.com/Mearman/mcp-template.git my-mcp-server
cd my-mcp-server
# Install dependencies
yarn install
# Start development
yarn dev
Project Structure
src/
├── index.ts # MCP server entry point
├── tools/ # Tool implementations
│ ├── example.ts # Example tool
│ └── *.test.ts # Tool tests
├── utils/ # Shared utilities
│ ├── validation.ts # Input validation helpers
│ └── *.test.ts # Utility tests
└── types.ts # TypeScript type definitions
# Configuration files
├── .github/workflows/ # CI/CD pipelines
├── .husky/ # Git hooks
├── biome.json # Linter/formatter config
├── tsconfig.json # TypeScript config
├── vitest.config.ts # Test runner config
└── .releaserc.json # Semantic release config
Development
Available Commands
# Install dependencies
yarn install
# Development with hot reload
yarn dev
# Build TypeScript to JavaScript
yarn build
# Run production build
yarn start
# Run tests
yarn test
# Run tests in watch mode
yarn test:watch
# Run tests with coverage report
yarn test:ci
# Lint code
yarn lint
# Auto-fix linting issues
yarn lint:fix
# Format code
yarn format
Development Workflow
- Start development:
yarn dev- Runs the server with hot reload - Write tests: Add
.test.tsfiles alongside your code - Run tests:
yarn test:watch- Keep tests running while you code - Lint/format: Automatic on commit via Husky hooks
Creating Your MCP Server
1. Define Your Tools
Create tool implementations in src/tools/:
// src/tools/my-tool.ts
import { z } from 'zod';
const MyToolSchema = z.object({
input: z.string().describe('Tool input'),
});
export async function myTool(args: unknown) {
const { input } = MyToolSchema.parse(args);
// Tool implementation
return {
success: true,
result: `Processed: ${input}`,
};
}
2. Register Tools in Server
Update src/index.ts to register your tools:
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [
{
name: 'my_tool',
description: 'Description of what my tool does',
inputSchema: zodToJsonSchema(MyToolSchema),
},
],
}));
server.setRequestHandler(CallToolRequestSchema, async (request) => {
switch (request.params.name) {
case 'my_tool':
return await myTool(request.params.arguments);
default:
throw new Error(`Unknown tool: ${request.params.name}`);
}
});
3. Configure for Claude Desktop
Add to claude_desktop_config.json:
{
"mcpServers": {
"my-mcp-server": {
"command": "node",
"args": ["/path/to/my-mcp-server/dist/index.js"],
"env": {}
}
}
}
Testing
Write tests for your tools in src/tools/*.test.ts:
import { describe, it, expect } from 'vitest';
import { myTool } from './my-tool';
describe('myTool', () => {
it('should process input correctly', async () => {
const result = await myTool({ input: 'test' });
expect(result.success).toBe(true);
expect(result.result).toBe('Processed: test');
});
});
Publishing
NPM Package
-
Update
package.jsonwith your package details:name: Your package name (e.g.,mcp-your-server)description: Clear description of what your server doeskeywords: Add relevant keywords for discoverabilityauthor: Your name or organizationrepository: Your GitHub repository URL
-
Build the project:
yarn build -
Test the build locally:
yarn start -
Publish to npm:
npm publish
Automated Releases
This template includes semantic-release for automated versioning and publishing:
- Follow conventional commits
- Push to main branch
- CI/CD will automatically:
- Determine version bump
- Update CHANGELOG.md
- Create GitHub release
- Publish to npm (if NPM_TOKEN secret is configured)
Note: NPM publishing is optional. If you don't want to publish to npm, simply don't add the NPM_TOKEN secret to your repository. The release process will still create GitHub releases.
Best Practices
- Input Validation: Always validate tool inputs using Zod schemas
- Error Handling: Provide clear error messages for debugging
- Testing: Write comprehensive tests for all tools
- Documentation: Document each tool's purpose and usage
- Type Safety: Leverage TypeScript's type system fully
- Modular Design: Keep tools focused on single responsibilities
- Async/Await: Use modern async patterns for all I/O operations
- Environment Variables: Use
.envfiles for configuration (never commit secrets)
Adding CLI Support
To add CLI functionality to your MCP server (like the Wayback Machine example):
-
Install Commander.js:
yarn add commander chalk ora -
Create
src/cli.ts:import { Command } from 'commander'; import chalk from 'chalk'; export function createCLI() { const program = new Command(); program .name('your-tool') .description('Your MCP server as a CLI') .version('1.0.0'); // Add commands here return program; } -
Update
src/index.tsto detect CLI mode:async function main() { const isCliMode = process.stdin.isTTY || process.argv.length > 2; if (isCliMode && process.argv.length > 2) { const { createCLI } = await import('./cli.js'); const program = createCLI(); await program.parseAsync(process.argv); } else { // MCP server mode const transport = new StdioServerTransport(); await server.connect(transport); } } -
Add bin entry to
package.json:"bin": { "your-tool": "dist/index.js" }
License
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
Maintaining Your MCP Server
Template Updates
This template includes scripts to help you merge updates from the template into your derived MCP server:
-
Merge Updates: Use
scripts/merge-template-updates.shto selectively merge template improvements while preserving your customizations. -
Analyze Differences: Use
scripts/analyze-template-diff.shto understand what has changed between your server and the template.
See scripts/README.md for detailed documentation on using these maintenance scripts.
Installing Scripts in Existing Projects
If you created your MCP server before these scripts were added:
# From mcp-template directory
./scripts/install-scripts.sh ../path-to-your-mcp-server
Contributing
Contributions are welcome! Please read our contributing guidelines and submit pull requests to our repository.
Troubleshooting
Common Issues
- Build errors: Ensure all dependencies are installed with
yarn install - Type errors: Run
npx tsc --noEmitto check TypeScript types - Test failures: Check test files are named
*.test.ts - Claude Desktop connection: Verify the path in your config is absolute
Debug Mode
To see detailed logs when running as an MCP server:
DEBUG=* node dist/index.js
Resources
- Model Context Protocol Documentation
- MCP TypeScript SDK
- Creating MCP Servers Guide
- Awesome MCP Servers - Community-curated list
- MCP Discord - Get help and share your servers
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.