
MCP Learning Project
A comprehensive tutorial project that teaches Model Context Protocol (MCP) development from beginner to advanced levels, covering both server-side and client-side development.
README
MCP Learning Project - Complete Guide
This is a comprehensive tutorial project that teaches Model Context Protocol (MCP) development from beginner to advanced levels. You'll learn both server-side (backend) and client-side (frontend) development.
🎯 What You'll Learn
Beginner Level:
- ✅ Basic MCP server structure and concepts
- ✅ Simple tool creation and registration
- ✅ Parameter handling and validation
- ✅ Basic client connection and tool calling
Intermediate Level:
- ✅ State management between tool calls
- ✅ Resource management (serving data to AI)
- ✅ Data processing and complex operations
- ✅ Client-server communication patterns
Advanced Level:
- ✅ CRUD operations with persistent state
- ✅ Comprehensive error handling
- ✅ Prompt templates for AI interactions
- ✅ Best practices and production considerations
📁 Project Structure
mcp-learning-project/
├── src/
│ ├── server.ts # MCP Learning Server (backend)
│ └── client.ts # MCP Learning Client (frontend)
├── dist/ # Compiled JavaScript
├── package.json # Dependencies and scripts
├── tsconfig.json # TypeScript configuration
└── README.md # This file
🚀 Quick Start
1. Setup Project
# Create project directory
mkdir mcp-learning-project
cd mcp-learning-project
# Initialize npm project
npm init -y
# Install dependencies
npm install @modelcontextprotocol/sdk
# Install dev dependencies
npm install --save-dev typescript @types/node tsx
2. Create Package.json
{
"name": "mcp-learning-project",
"version": "1.0.0",
"description": "Learn MCP development from beginner to advanced",
"main": "dist/server.js",
"type": "module",
"scripts": {
"build": "tsc",
"start:server": "node dist/server.js",
"start:client": "node dist/client.js dist/server.js",
"dev:server": "tsx src/server.ts",
"dev:client": "tsx src/client.ts dist/server.js",
"demo": "npm run build && npm run start:client"
},
"dependencies": {
"@modelcontextprotocol/sdk": "^0.4.0"
},
"devDependencies": {
"@types/node": "^20.0.0",
"tsx": "^4.0.0",
"typescript": "^5.0.0"
}
}
3. Create TypeScript Config
Create tsconfig.json
:
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "node",
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"outDir": "./dist",
"rootDir": "./src",
"declaration": true,
"skipLibCheck": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
4. Save the Code Files
- Save the MCP Learning Server code as
src/server.ts
- Save the MCP Learning Client code as
src/client.ts
5. Build and Run
# Build the project
npm run build
# Run the interactive client (this will also start the server)
npm run demo
🎓 Learning Path
Phase 1: Understanding the Basics
-
Start the interactive client:
npm run demo
-
Try basic commands:
mcp-learning> help mcp-learning> tools mcp-learning> call hello_world {"name": "Alice"}
-
Learn about resources:
mcp-learning> resources mcp-learning> read mcp-concepts
Phase 2: Hands-on Practice
-
Run the beginner demo:
mcp-learning> demo beginner
-
Practice tool calls:
mcp-learning> call calculator {"operation": "add", "a": 5, "b": 3} mcp-learning> call calculator {"operation": "divide", "a": 10, "b": 0}
-
Understand state management:
mcp-learning> call counter {"action": "get"} mcp-learning> call counter {"action": "increment", "amount": 5} mcp-learning> call counter {"action": "get"}
Phase 3: Advanced Concepts
-
Run intermediate demo:
mcp-learning> demo intermediate
-
Work with complex data:
mcp-learning> call data_processor {"data": [5, 2, 8, 1, 9], "operation": "sort"} mcp-learning> call data_processor {"data": [5, 2, 8, 1, 9], "operation": "average"}
-
CRUD operations:
mcp-learning> call task_manager {"action": "create", "task": {"title": "Learn MCP", "priority": "high"}} mcp-learning> call task_manager {"action": "list"}
Phase 4: Production Ready
-
Run advanced demo:
mcp-learning> demo advanced
-
Learn error handling:
mcp-learning> call error_demo {"error_type": "none"} mcp-learning> call error_demo {"error_type": "validation"}
-
Study best practices:
mcp-learning> read best-practices
🔧 Key Concepts Explained
1. MCP Server (Backend)
The server provides capabilities to AI models:
// Server setup
const server = new Server({
name: 'my-server',
version: '1.0.0'
}, {
capabilities: {
tools: {}, // Functions AI can call
resources: {}, // Data AI can read
prompts: {} // Templates AI can use
}
});
// Tool registration
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [
{
name: 'my_tool',
description: 'What this tool does',
inputSchema: { /* JSON Schema */ }
}
]
}));
// Tool implementation
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
// Process the tool call and return results
return {
content: [{
type: 'text',
text: 'Tool response'
}]
};
});
2. MCP Client (Frontend)
The client connects to servers and uses their capabilities:
// Client setup
const client = new Client({
name: 'my-client',
version: '1.0.0'
}, {
capabilities: { /* client capabilities */ }
});
// Connect to server
const transport = new StdioClientTransport(/* server process */);
await client.connect(transport);
// Discover server capabilities
const tools = await client.listTools();
const resources = await client.listResources();
// Use server tools
const result = await client.callTool({
name: 'tool_name',
arguments: { /* tool parameters */ }
});
3. Communication Flow
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ AI Model │ ───▶ │ MCP Client │ ───▶ │ MCP Server │
│ │ │ (Frontend) │ │ (Backend) │
│ │ ◀─── │ │ ◀─── │ │
└─────────────┘ └─────────────┘ └─────────────┘
▲ │ │
│ │ │
└──────────────────────┴──────────────────────┘
Uses server capabilities
🧪 Experimentation Ideas
Create Your Own Tools:
-
Weather Tool:
{ name: 'weather', description: 'Get weather information', inputSchema: { type: 'object', properties: { city: { type: 'string', description: 'City name' }, units: { type: 'string', enum: ['celsius', 'fahrenheit'], default: 'celsius' } }, required: ['city'] } }
-
File System Tool:
{ name: 'file_operations', description: 'Basic file system operations', inputSchema: { type: 'object', properties: { action: { type: 'string', enum: ['list', 'read', 'write'] }, path: { type: 'string', description: 'File or directory path' }, content: { type: 'string', description: 'Content to write' } }, required: ['action', 'path'] } }
-
Database Tool:
{ name: 'database', description: 'Simple in-memory database operations', inputSchema: { type: 'object', properties: { action: { type: 'string', enum: ['create', 'read', 'update', 'delete'] }, table: { type: 'string', description: 'Table name' }, data: { type: 'object', description: 'Data to store/update' }, id: { type: 'string', description: 'Record ID' } }, required: ['action', 'table'] } }
Create Custom Resources:
-
Configuration Resource:
{ uri: 'config://app-settings', name: 'Application Settings', description: 'Current application configuration', mimeType: 'application/json' }
-
Documentation Resource:
{ uri: 'docs://api-reference', name: 'API Reference', description: 'Complete API documentation', mimeType: 'text/markdown' }
Create Interactive Prompts:
- Code Review Prompt:
{ name: 'code-review', description: 'Start a code review session', arguments: [ { name: 'language', description: 'Programming language', required: true }, { name: 'focus', description: 'Review focus (security, performance, style)', required: false } ] }
🐛 Debugging and Troubleshooting
Common Issues:
-
Server Won't Start:
# Check if TypeScript compiled correctly npm run build # Look for compilation errors npx tsc --noEmit # Check for missing dependencies npm install
-
Client Can't Connect:
# Make sure server path is correct node dist/client.js dist/server.js # Check if server process starts node dist/server.js
-
Tool Calls Fail:
// Add debugging to your server console.error(`[DEBUG] Tool called: ${name}`, JSON.stringify(args)); // Validate input parameters carefully if (typeof args.requiredParam === 'undefined') { throw new McpError(ErrorCode.InvalidParams, 'Missing required parameter'); }
Debug Mode:
Enable verbose logging in both server and client:
// In server
console.error('[SERVER]', 'Detailed log message');
// In client
console.log('[CLIENT]', 'Connection status:', connected);
🚀 Next Steps: Building Production Servers
1. Add Real Functionality:
Replace demo tools with actual useful functionality:
// Example: Real file system access
private async handleFileOperations(args: any) {
const { action, path, content } = args;
switch (action) {
case 'read':
return {
content: [{
type: 'text',
text: await fs.readFile(path, 'utf-8')
}]
};
case 'write':
await fs.writeFile(path, content);
return {
content: [{
type: 'text',
text: `File written: ${path}`
}]
};
}
}
2. Add External Integrations:
// Example: HTTP API integration
private async handleApiCall(args: any) {
const { url, method, data } = args;
const response = await fetch(url, {
method,
headers: { 'Content-Type': 'application/json' },
body: data ? JSON.stringify(data) : undefined
});
return {
content: [{
type: 'text',
text: JSON.stringify({
status: response.status,
data: await response.json()
}, null, 2)
}]
};
}
3. Add Persistence:
import * as fs from 'fs/promises';
class PersistentMCPServer {
private dataFile = './mcp-data.json';
async loadState(): Promise<Map<string, any>> {
try {
const data = await fs.readFile(this.dataFile, 'utf-8');
return new Map(Object.entries(JSON.parse(data)));
} catch {
return new Map();
}
}
async saveState(state: Map<string, any>): Promise<void> {
const data = Object.fromEntries(state);
await fs.writeFile(this.dataFile, JSON.stringify(data, null, 2));
}
}
4. Add Authentication:
private validateAuth(headers: any): boolean {
const token = headers['authorization'];
return token === 'Bearer your-secret-token';
}
private async handleSecureTool(args: any, headers: any) {
if (!this.validateAuth(headers)) {
throw new McpError(ErrorCode.InvalidParams, 'Authentication required');
}
// Continue with tool logic...
}
📚 Additional Resources
Official Documentation:
Community Examples:
Advanced Topics:
- HTTP transport for web services
- WebSocket transport for real-time communication
- Custom transport implementations
- Performance optimization techniques
- Security best practices
🎯 Learning Exercises
Exercise 1: Extend the Calculator
Add more operations: power
, sqrt
, factorial
, sin
, cos
Exercise 2: Build a Note-Taking System
Create tools for creating, editing, searching, and organizing notes with tags.
Exercise 3: Add External API Integration
Integrate with a real API (weather, news, stock prices) and create corresponding tools.
Exercise 4: Build a Project Manager
Create a comprehensive project management system with tasks, deadlines, priorities, and progress tracking.
Exercise 5: Add Real-Time Features
Implement tools that can send notifications or updates back to the client.
🏆 Mastery Checklist
Beginner Level ✅
- [ ] Understand MCP architecture (client, server, transport)
- [ ] Create basic tools with input validation
- [ ] Handle simple tool calls and responses
- [ ] Read and understand error messages
Intermediate Level ✅
- [ ] Implement stateful tools with persistence
- [ ] Create and serve resources to AI
- [ ] Handle complex data processing
- [ ] Implement proper error handling patterns
Advanced Level ✅
- [ ] Build CRUD operations with complex state
- [ ] Create interactive prompt templates
- [ ] Implement production-ready error handling
- [ ] Understand security and authentication concepts
- [ ] Optimize performance for production use
Expert Level 🚀
- [ ] Build custom transport layers
- [ ] Create MCP server frameworks
- [ ] Implement advanced security measures
- [ ] Build distributed MCP architectures
- [ ] Contribute to the MCP ecosystem
🎉 Congratulations!
You now have a complete understanding of MCP development from both frontend and backend perspectives. You can:
- Build MCP servers that provide tools, resources, and prompts
- Create MCP clients that interact with servers effectively
- Handle errors gracefully and implement proper validation
- Manage state between tool calls and across sessions
- Follow best practices for production-ready implementations
The interactive learning environment in this project gives you hands-on experience with all MCP concepts. Use this as a foundation to build your own specialized MCP servers for any domain or use case!
Happy coding! 🚀
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.