Build a Production-Ready MCP Server in TypeScript
TL;DR
This tutorial guides you through building a production-ready MCP server in TypeScript using the MCP Starter Kit. It covers setup, authentication, database integration, and deployment for AI assistants like Cursor.
Key Takeaways
- •The MCP Starter Kit simplifies building MCP servers with preconfigured authentication, database setup, and billing systems.
- •You can create applications with templates for blog, ecommerce, CRM, or todo, including CRUD operations and AI integration.
- •Deployment options include Vercel, Railway, or Docker, with best practices for security, performance, and troubleshooting.
Tags
What is the Model Context Protocol (MCP)?
The Model Context Protocol (MCP) is a framework that allows AI assistants like Cursor or Claude to interact with external tools, APIs, and databases. Think of it as a bridge that lets your AI assistant actually do things in the real world: fetch data, update records, process payments, or manage authentication.
With MCP servers, you can:
- Handle user authentication and sessions
- Work with databases (queries, migrations, CRUD)
- Manage billing flows (free tiers, upgrades, subscriptions)
- Connect to external APIs (emails, third-party data, integrations)
- Bundle multiple tools into a single AI-accessible server
Why Use the MCP Starter Kit?
Building an MCP server from scratch means setting up all of the above — authentication, database connections, billing, APIs, error handling, and deployment pipelines. That’s a lot of moving parts.
The MCP Starter Kit simplifies the process by giving you:
Instant Setup
- One command bootstraps an MCP server
- Preconfigured authentication with Kinde
- Database setup via Neon PostgreSQL
- Built-in billing system
- Multiple ready-to-go templates (blog, ecommerce, CRM, todo)
Production-Ready Features
- Secure auth flows
- Database migrations & schema management
- Error handling and logging
Rate limiting & security headers
Testing setup out of the box
Developer Experience
- TypeScript support
- Hot reloading for dev
- Cursor AI integration
- Deployment-ready config
What You'll Build
By the end of this tutorial, you'll create a complete MCP application with:
- Authentication System → User login, registration, and session management
- Database Integration → PostgreSQL with automatic schema setup
- CRUD Operations → Create, read, update, and delete functionality
- Billing System → Freemium model with upgrade flows
- AI Integration → Seamless Cursor AI integration
- Production Deployment → Ready-to-deploy application
Prerequisites
Before starting, ensure you have:
- Node.js 18+ (download)
- npm or yarn
- Cursor IDE (download)
- Git
- Basic TypeScript knowledge (helpful but optional)
Setting Up Your Development Environment
Step 1: Install Node.js and npm
node --version
npm --version
If missing, download and install from nodejs.org.
Step 2: Install Cursor IDE
- Visit cursor.sh
- Download and install Cursor
- Sign up for a free account
Step 3: Create Development Accounts
You'll need accounts for:
Neon Database (Free Tier)
- Visit neon.tech
- Sign up for a free account
- Create a new database
- Copy your connection string
Kinde.com (Free Tier)
- Visit kinde.com
- Sign up for a free account
- Create a new application
- Note your client credentials
Creating Your First MCP Application
Step 1: Generate Your Application
npx mcp-starter-kit
You'll see an interactive prompt:
🚀 MCP Starter Kit
Create MCP applications with authentication, database, and billing
📝 What would you like to name your application? my-awesome-app
📋 Choose your template:
1. blog - Blog management system (posts, comments)
2. ecommerce - E-commerce system (products, orders)
3. crm - Customer relationship management (contacts, deals, tasks)
4. todo - Simple todo management system
🎯 Enter your choice (1-4): 1
🚀 Creating my-awesome-app with blog template...
✅ Application created successfully!
Step 2: Install Dependencies
npm install
Step3: Understand the Project Structure
Your generated project will have this structure:
my-awesome-app/
├── package.json # Dependencies and scripts
├── tsconfig.json # TypeScript configuration
├── .env.example # Environment template
├── README.md # Project documentation
└── src/
├── app-config.ts # Application configuration
├── universal-server.ts # Main MCP server
├── setup-db.ts # Database setup script
├── kinde-auth-server.ts # Authentication server
└── core/ # Core MCP modules
├── auth/ # Authentication manager
├── database/ # Database manager
├── server/ # MCP server core
└── tools/ # Tool factory
A brief explanation of key files:
-
universal-server.ts
→ your main MCP server that handles all AI interactions -
kinde-auth-server.ts
→ authentication server for user login/logout -
setup-db.ts
→ database schema creation and migration script -
app-config.ts
→ configuration for your specific application template -
core/
→ MCP modules
Configuring Authentication with Kinde
Step 1: Set Up Kinde Application
- Log into your Kinde dashboard
- Create a new application (if you haven’t)
- Configure the following settings:
- Application Name: Your MCP App
- Redirect URLs:
http://localhost:3000/callback
- Logout URLs:
http://localhost:3000
Step 2: Configure Environment Variables
cp .env.example .env
Edit your .env file:
# Kinde Authentication
KINDE_ISSUER_URL=https://your-domain.kinde.com
KINDE_CLIENT_ID=your_client_id
KINDE_CLIENT_SECRET=your_client_secret
JWT_SECRET=super_secret
Setting Up Your Database with Neon
Step 1: Update your .env file
Grab the with the connection string you copied from your Neon console and paste it in your .env
file:
# Database Configuration
DATABASE_URL=postgresql://username:password@host:port/database
Your complete .env
file should look like this:
# Database Configuration
DATABASE_URL=postgresql://username:password@host:port/database
# Kinde Authentication
KINDE_ISSUER_URL=https://your-domain.kinde.com
KINDE_CLIENT_ID=your_client_id
KINDE_CLIENT_SECRET=your_client_secret
# JWT Configuration
JWT_SECRET=your_super_secret_jwt_key_here
# Server Configuration
NODE_ENV=development
PORT=3000
Step 2: Initialize Database Schema
npm run setup-db
This command will:
- Connect to your Neon database
- Create all necessary tables
- Set up indexes and relationships
Building Your MCP Server
Step 1: Start the server:
npm run dev
Step 2: Start the authentication server:
npm run auth-server
Visit http://localhost:3000
to test the login flow.
Step 3: Understand the MCP Tools
Your MCP server provides these tools:
Authentication Tools:
-
login
→ Get authentication URL -
save_token
→ Save authentication token -
logout
→ Log out current user -
refresh_billing_status
→ Check billing status
CRUD Tools (Blog Template):
-
create_post
→ Create new blog post -
list_posts
→ List all blog posts -
get_post
→ Get specific blog post -
update_post
→ Update existing post -
delete_post
→ Delete blog post -
create_comment
→ Add comment to post -
list_comments
→ List post comments
Step 4: Integrating with Cursor AI
Create or edit ~/.cursor/mcp.json
:
{
"mcpServers": {
"my-awesome-app": {
"command": "node",
"args": ["dist/universal-server.js"],
"cwd": "/path/to/your/my-awesome-app",
"env": {
"DATABASE_URL": "your_database_url",
"KINDE_ISSUER_URL": "your_kinde_issuer_url",
"KINDE_CLIENT_ID": "your_kinde_client_id",
"KINDE_CLIENT_SECRET": "your_kinde_client_secret",
"JWT_SECRET": "your_jwt_secret"
}
}
}
}
After configuring MCP settings, restart Cursor to load the new configuration.
Step 5: Test AI Integration
In Cursor, you can now use natural language to interact with your MCP application:
"Create a new blog post titled 'Getting Started with MCP' with content about building AI applications"
"List all my blog posts"
"Update the post with ID 1 to change the title to 'Advanced MCP Techniques'"
Understanding the Billing System
The MCP Starter Kit includes a comprehensive billing system:
Free Tier Limits
Each template has configurable free tier limits:
Blog Template:
- 10 posts (free tier)
- 50 comments (free tier)
- Unlimited reads
E-commerce Template:
- 5 products (free tier)
- 10 orders (free tier)
- Unlimited customers
Upgrade Flow
- Usage Tracking → Automatic tracking of free tier usage
- Limit Warnings → Notifications when approaching limits
- Upgrade Prompts → Seamless redirect to billing portal
- Plan Management → Check current plan and usage
Billing Integration
// Check billing status
const billingStatus = await checkBillingStatus(userId);
// Redirect to upgrade
if (billingStatus.needsUpgrade) {
return redirectToBillingPortal(userId);
}
Available Templates Deep Dive
Blog Template
Perfect for content creators and writers:
Entities:
- Posts - Title, content, author, published date
- Comments - Text, author, post relationship
Features:
- Rich text content support
- Comment moderation
- Author management
- Publication scheduling
Use Cases:
- Personal blogs
- Company blogs
- Documentation sites
- News websites
E-commerce Template
Ideal for online stores and marketplaces:
Entities:
- Products - Name, description, price, inventory
- Orders - Customer, items, total, status
- Order Items - Product, quantity, price
Features:
- Inventory management
- Order tracking
- Customer management
- Payment integration
Use Cases:
- Online stores
- Digital marketplaces
- Subscription services
- Product catalogs
CRM Template
Perfect for sales teams and businesses:
Entities:
- Contacts - Name, email, company, status
- Deals - Title, value, stage, contact
- Tasks - Description, due date, contact
Features:
- Lead management
- Sales pipeline
- Task automation
- Contact segmentation
Use Cases:
- Sales teams
- Customer support
- Lead generation
- Business development
Todo Template
Great for personal productivity and task management:
Entities:
- Todos - Title, description, completed, due date
Features:
- Task prioritization
- Due date management
- Completion tracking
- Category organization
Use Cases:
- Personal productivity
- Project management
- Team coordination
- Goal tracking
Advanced Features and Customization
Custom Entity Creation
You can extend any template with custom entities:
// Add a new entity to your template
const customEntity = {
name: 'custom_entity',
fields: {
title: 'string',
description: 'text',
created_at: 'timestamp'
},
relationships: {
user_id: 'users.id'
}
};
Custom MCP Tools
Create custom tools for your specific needs:
// Custom tool example
const customTool = {
name: 'send_email',
description: 'Send email to user',
parameters: {
to: 'string',
subject: 'string',
body: 'string'
},
handler: async (params) => {
// Your custom logic here
return { success: true };
}
};
API Rate Limiting
Configure rate limiting for your MCP server:
// Rate limiting configuration
const rateLimitConfig = {
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // limit each IP to 100 requests per windowMs
message: 'Too many requests from this IP'
};
Deployment and Production Considerations
Once your MCP server is running locally, the next step is to think about deploying it in a secure and production-ready way. Here are the key areas to cover:
Environment Configuration
Keep separate environment files for development and production.
Development (.env.local
):
NODE_ENV=development
DATABASE_URL=your_dev_database_url
KINDE_ISSUER_URL=your_dev_kinde_url
Production (.env
):
NODE_ENV=production
DATABASE_URL=your_prod_database_url
KINDE_ISSUER_URL=your_prod_kinde_url
Security Considerations
When moving to production, follow these best practices:
- Environment Variables → Never commit secrets or .env files to version control.
- HTTPS → Always serve your app over HTTPS in production.
- CORS → Configure CORS to only allow requests from your domain.
- Rate Limiting → Protect your endpoints from abuse with rate limiting.
- Input Validation → Validate all incoming requests to prevent injection attacks.
Deployment Options
There are several ways to host your MCP server. Here are three common approaches:
1. Vercel (Recommended)
Vercel makes deployment easy with automatic builds and scaling.
# Install Vercel CLI
npm i -g vercel
# Deploy your application
vercel --prod
2. Railway
Railway provides a simple GitHub integration:
# Connect your GitHub repository
# Railway will automatically build and deploy your app
3. Docker
For more control, you can containerize your app with Docker:
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
EXPOSE 3000
CMD ["npm", "start"]
Which One Should You Choose?
Option | Pros | Cons |
---|---|---|
Vercel | Zero-config, fast deploys, free tier, great for TypeScript apps | Less control over server environment |
Railway | Easy GitHub integration, supports background jobs | Free tier more limited than Vercel |
Docker | Full control, portable across any cloud provider | More setup and maintenance required |
For most developers, Vercel is the fastest way to go live. If you want more flexibility or need background jobs, Railway is a good choice. For enterprise-grade control, Docker is the way forward.
Troubleshooting Common Issues
MCP Server Not Detected in Cursor
Symptoms:
- Cursor doesn't recognize your MCP server
- Tools don't appear in Cursor interface
Solutions:
- Check
~/.cursor/mcp.json
syntax - Verify environment variables are set
- Restart Cursor completely
- Ensure MCP server is running
- Check Cursor logs for errors
Authentication Issues
Symptoms:
- Login redirects fail
- Tokens not being saved
- Authentication errors
Solutions:
- Verify Kinde credentials in .env
- Check redirect URLs in Kinde dashboard
- Ensure auth server is running on port 3000
- Clear browser cookies and try again
- Check JWT secret is set correctly
Database Connection Issues
Symptoms:
- Database connection errors
- Schema creation fails
- Query timeouts
Solutions:
- Verify Neon database URL
- Check database permissions
- Run
npm run setup-db
to create schema - Test connection with
npm run test-db
- Check network connectivity
Performance Issues
Symptoms:
- Slow response times
- High memory usage
- Timeout errors
Solutions:
- Optimize database queries
- Add database indexes
- Implement caching
- Use connection pooling
- Monitor resource usage
Best Practices and Tips
Development Workflow
- Use Version Control → Always use Git for your projects
- Environment Management → Use different environments for dev/staging/prod
- Testing → Write tests for your MCP tools
- Documentation → Document your custom tools and configurations
- Monitoring → Set up logging and monitoring
Security Best Practices
- Secrets Management → Use environment variables for all secrets
- Input Validation → Validate all inputs from AI and users
- Rate Limiting → Implement rate limiting to prevent abuse
- Authentication → Always verify user authentication
- HTTPS → Use HTTPS in production
Performance Optimization
- Database Indexing → Add indexes for frequently queried fields
- Connection Pooling → Use connection pooling for database connections
- Caching → Implement caching for frequently accessed data
- Lazy Loading → Load data only when needed
- Monitoring → Monitor performance metrics
AI Integration Tips
- Clear Descriptions → Write clear descriptions for your MCP tools
- Error Handling → Provide meaningful error messages
- Context → Include relevant context in responses
- Validation → Validate AI inputs before processing
- Logging → Log all AI interactions for debugging
Conclusion and Next Steps
You’ve just built a production-ready AI-Native MCP server in TypeScript using a Starter Kit. Along the way, you added authentication, database integration, billing, and even connected it to Cursor AI.
With this foundation, you can now extend your server with custom tools, new entities, and additional integrations to fit your use case.
Ready to build your own MCP application? Run:
npx mcp-starter-kit