chris-quintin/mcp-server-template
If you are the rightful owner of mcp-server-template and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to dayong@mcphub.com.
This document provides a structured overview of a Model Context Protocol (MCP) server template designed for building robust MCP servers using TypeScript and Node.js.
MCP Server Template
A comprehensive template for building Model Context Protocol (MCP) servers using TypeScript and Node.js.
Features
- 🛠️ Complete MCP Implementation: Tools, Resources, and Prompts
- 🔄 Dual Transport Support: STDIO (local) + HTTP (web/cloud) modes
- 📦 TypeScript: Full type safety and modern JavaScript features
- 🔧 Example Tools: Sample implementations to get you started
- 📚 Resource Management: File-like data exposure
- 💬 Prompt Templates: Reusable AI interaction templates
- 🚀 Development Ready: Hot reload, linting, and build scripts
- ☁️ Cloud Ready: Railway, Docker, and multi-platform deployment
- 📖 Well Documented: Comprehensive examples and comments
Prerequisites
- Node.js v18.0.0 or higher
- npm or yarn package manager
Quick Start
-
Clone and Setup
git clone <your-repo-url> my-mcp-server cd my-mcp-server npm install -
Configure Environment
cp .env.example .env # Edit .env with your configuration -
Development Mode
npm run dev -
Build for Production
npm run build npm start # STDIO mode npm start:http # HTTP mode
🔄 Transport Modes
This template supports two transport modes with identical MCP functionality:
📱 STDIO Mode (Local MCP Clients)
Perfect for local MCP clients like Claude Desktop, Cursor, or other desktop applications.
# Development
npm run dev
# Production
npm run build
npm start
Use STDIO when:
- ✅ Integrating with Claude Desktop
- ✅ Running locally for development
- ✅ Building desktop MCP integrations
- ✅ Working with process-based MCP clients
Client Configuration Example (Claude Desktop):
{
"mcp-server-template": {
"command": "node",
"args": ["/path/to/your/dist/index.js"]
}
}
🌐 HTTP Mode (Web/Cloud Deployment)
Ideal for web applications, cloud deployment, and remote MCP access.
# Development
npm run dev:http
# Production
npm run build
npm start:http
Use HTTP when:
- ✅ Deploying to Railway, Render, or other cloud platforms
- ✅ Building web-based MCP integrations
- ✅ Need HTTP endpoints for health checks
- ✅ Require remote access to your MCP server
Endpoints:
- Health Check:
GET /health - SSE Connection:
GET /sse - MCP Messages:
POST /message
📊 Mode Comparison
| Feature | STDIO Mode | HTTP Mode |
|---|---|---|
| Transport | stdin/stdout | SSE over HTTP |
| Use Case | Local clients | Web/Cloud deployment |
| Health Checks | ❌ | ✅ /health endpoint |
| Remote Access | ❌ | ✅ HTTPS support |
| Cloud Deploy | ❌ | ✅ Railway, Render, etc. |
| Desktop Clients | ✅ Claude Desktop | ❌ |
| Same MCP Features | ✅ | ✅ |
Both modes implement the exact same MCP functionality - tools, resources, and prompts are identical. Choose based on your deployment needs!
Project Structure
mcp-server-template/
├── src/
│ └── index.ts # Main server implementation
├── dist/ # Compiled JavaScript (generated)
├── package.json # Dependencies and scripts
├── tsconfig.json # TypeScript configuration
├── .eslintrc.json # ESLint configuration
├── .env.example # Environment variables template
├── .gitignore # Git ignore rules
└── README.md # This file
Core Concepts
Tools
Tools are functions that can be called by MCP clients. They accept structured input and return structured output.
// Example tool registration
{
name: 'search_data',
description: 'Search for data using a query string',
inputSchema: {
type: 'object',
properties: {
query: { type: 'string', description: 'The search query' }
},
required: ['query']
}
}
Resources
Resources expose data in a file-like manner. They have URIs and can be read by clients.
// Example resource
{
uri: 'config://server',
mimeType: 'application/json',
name: 'Server Configuration',
description: 'Current server configuration and settings'
}
Prompts
Prompts are reusable templates for AI interactions with parameterization support.
// Example prompt
{
name: 'analyze_data',
description: 'Analyze data and provide insights',
arguments: [
{ name: 'data', description: 'The data to analyze', required: true }
]
}
Customization
Adding New Tools
-
Define the tool schema in the
ListToolsRequestSchemahandler:tools.push({ name: 'my_tool', description: 'Description of what the tool does', inputSchema: { type: 'object', properties: { param1: { type: 'string', description: 'First parameter' } }, required: ['param1'] } }); -
Implement the tool logic in the
CallToolRequestSchemahandler:case 'my_tool': { const { param1 } = args as { param1: string }; const result = await myService.doSomething(param1); return { content: [{ type: 'text', text: result }] }; }
Adding New Resources
- Register the resource in the
ListResourcesRequestSchemahandler - Implement the read logic in the
ReadResourceRequestSchemahandler
Adding New Prompts
- Register the prompt in the
ListPromptsRequestSchemahandler - Implement the prompt logic in the
GetPromptRequestSchemahandler
Development Scripts
npm run dev- Start development server with hot reloadnpm run build- Build for productionnpm start- Start production servernpm run watch- Watch mode for developmentnpm run lint- Run ESLintnpm run lint:fix- Fix ESLint issues automaticallynpm run clean- Clean build directory
Environment Variables
Copy .env.example to .env and configure:
NODE_ENV- Environment (development/production)API_KEY- Your API key (if using external services)DATABASE_URL- Database connection string (if needed)LOG_LEVEL- Logging level (debug/info/warn/error)
Error Handling
The template includes comprehensive error handling:
- Tool Errors: Caught and returned as error responses
- Resource Errors: Proper error messages for missing resources
- Server Errors: Logged to stderr (never stdout)
- Graceful Shutdown: Handles SIGINT for clean shutdown
Best Practices
- Never write to stdout - Use stderr for logging
- Validate inputs - Use Zod schemas for input validation
- Handle errors gracefully - Return meaningful error messages
- Use TypeScript - Leverage type safety throughout
- Document your tools - Provide clear descriptions and examples
- Test thoroughly - Test all tools, resources, and prompts
Deployment
Local Development
STDIO Mode (for local MCP clients):
npm run dev
HTTP Mode (for web/remote access):
npm run dev:http
Production Build
npm run build
npm start # STDIO mode
npm start:http # HTTP mode
Railway Deployment
Railway is a great platform for deploying MCP servers with automatic HTTPS and scaling.
1. One-Click Deploy
2. Manual Deployment
-
Install Railway CLI:
npm install -g @railway/cli -
Login and Initialize:
railway login railway init -
Configure Environment Variables:
railway variables set NODE_ENV=production railway variables set API_KEY=your-api-key railway variables set PORT=3000 -
Deploy:
railway up
3. GitHub Integration
- Push your code to GitHub
- Visit Railway
- Click "New Project" → "Deploy from GitHub repo"
- Select your repository
- Railway will automatically detect the configuration and deploy
Railway Configuration Files:
railway.json- Railway deployment settingsnixpacks.toml- Build configuration- Environment variables set via Railway dashboard
Railway Features:
- ✅ Automatic HTTPS with custom domains
- ✅ Zero-downtime deployments
- ✅ Auto-scaling based on traffic
- ✅ Built-in monitoring and logs
- ✅ Environment variable management
- ✅ GitHub/GitLab integration
4. Accessing Your Deployed Server
After deployment, Railway provides:
- Public URL:
https://your-app.railway.app - Health check:
https://your-app.railway.app/health - MCP endpoint:
https://your-app.railway.app/message
Docker Deployment
Create a Dockerfile:
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY dist ./dist
EXPOSE 3000
CMD ["npm", "run", "start:http"]
Build and run:
docker build -t mcp-server .
docker run -p 3000:3000 mcp-server
Other Cloud Platforms
Render
- Connect GitHub repository
- Set build command:
npm run build - Set start command:
npm run start:http - Add environment variables
Fly.io
fly launch
fly deploy
Google Cloud Run
gcloud run deploy --source .
Vercel (Serverless)
Add vercel.json:
{
"builds": [{ "src": "dist/http-server.js", "use": "@vercel/node" }],
"routes": [{ "src": "/(.*)", "dest": "/dist/http-server.js" }]
}
Troubleshooting
Common Issues
-
Module not found errors
- Ensure all dependencies are installed:
npm install - Check TypeScript compilation:
npm run build
- Ensure all dependencies are installed:
-
Server not responding
- Check that the server is running on stdio transport
- Verify no stdout pollution (use stderr for logging)
-
Type errors
- Run TypeScript compiler:
npx tsc --noEmit - Check tsconfig.json configuration
- Run TypeScript compiler:
Debug Mode
Enable debug logging by setting environment variable:
LOG_LEVEL=debug npm run dev
Contributing
- Fork the repository
- Create a feature branch:
git checkout -b feature-name - Make your changes
- Run tests and linting:
npm run lint - Build the project:
npm run build - Commit your changes:
git commit -am 'Add feature' - Push to the branch:
git push origin feature-name - Create a Pull Request
License
MIT License - see LICENSE file for details.
Resources
Support
If you encounter issues or need help:
- Check the MCP Documentation
- Review the example implementations in
src/index.ts - Open an issue in this repository
- Join the MCP community discussions