๐ Complete MCP Server Guide - From Basics to Building Your Own
Welcome to the fascinating world of MCP Servers! If you've ever wondered how AI applications connect to external tools and services, or how to build your own AI-powered integrations, this guide will take you from complete beginner to MCP server developer.
๐ค What is MCP Server?
MCP (Model Context Protocol) Server is like a universal translator that helps AI models communicate with external tools, databases, and services. Think of it as a bridge between your AI assistant and the outside world.
Real-life analogy: Imagine you're at a fancy restaurant in a foreign country. The MCP server is like a multilingual waiter who:
- ๐ฃ๏ธ Understands what you want (AI model requests)
- ๐ง Knows how to get it from the kitchen (external tools/services)
- ๐ Brings back exactly what you ordered (structured responses)
๐ฏ Why MCP Servers Matter:
- ๐ Connectivity: Connect AI to databases, APIs, file systems
- ๐ก๏ธ Security: Controlled access to external resources
- ๐ Standardization: Universal protocol for AI integrations
- โก Efficiency: Optimized communication between AI and tools
Real-world example: Instead of manually copying data from your database to show an AI, an MCP server lets the AI directly query your database safely and efficiently.
๐๏ธ How MCP Servers Work
๐ญ The Three Main Characters:
- ๐ค AI Client (Claude, ChatGPT, etc.)
- ๐ MCP Server (The bridge we're building)
- ๐ง Tools/Resources (Databases, APIs, files)
๐ค AI Client โโ ๐ MCP Server โโ ๐ง External Tools
"Get user data" "I'll handle it" "Here's the data"
Real-life analogy: It's like ordering food delivery:
- AI Client = You (placing the order)
- MCP Server = Delivery service (handles the logistics)
- External Tools = Restaurant (provides the actual service)
๐ก Communication Flow:
// Simplified flow
1. AI sends request โ MCP Server
2. MCP Server processes โ External Tool
3. External Tool responds โ MCP Server
4. MCP Server formats โ AI Client
๐ ๏ธ Setting Up Your First MCP Server
๐ Prerequisites:
- Node.js (v16+) or Python (3.8+)
- Basic programming knowledge
- Text editor (VS Code recommended)
๐ Quick Start with Node.js:
# ๐ฆ Create new project
mkdir my-mcp-server
cd my-mcp-server
# ๐ง Initialize project
npm init -y
# ๐ฅ Install MCP SDK
npm install @modelcontextprotocol/sdk
๐ฏ Your First MCP Server:
// server.js
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
// ๐ช Create server instance
const server = new Server(
{
name: 'my-first-mcp-server',
version: '1.0.0',
},
{
capabilities: {
tools: {},
resources: {},
},
}
);
// ๐ง Add a simple tool
server.setRequestHandler('tools/list', async () => {
return {
tools: [
{
name: 'greet',
description: '๐ Say hello to someone',
inputSchema: {
type: 'object',
properties: {
name: {
type: 'string',
description: 'Name of the person to greet',
},
},
required: ['name'],
},
},
],
};
});
// ๐ฏ Handle tool calls
server.setRequestHandler('tools/call', async (request) => {
const { name, arguments: args } = request.params;
if (name === 'greet') {
const personName = args.name;
return {
content: [
{
type: 'text',
text: `๐ Hello, ${personName}! Welcome to MCP Server world!`,
},
],
};
}
throw new Error(`Unknown tool: ${name}`);
});
// ๐ Start the server
const transport = new StdioServerTransport();
server.connect(transport);
console.log('๐ MCP Server started! Ready to serve AI requests...');
Real-life analogy: This is like setting up a help desk that can answer one question: "How to greet people?" When someone asks, it provides a personalized greeting.
๐ฏ Understanding MCP Tools
๐ง What are Tools?
Tools are functions that your MCP server can execute on behalf of the AI. Think of them as special abilities you give to the AI.
๐ ๏ธ Building a Calculator Tool:
// calculator-server.js
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
const server = new Server(
{
name: 'calculator-mcp-server',
version: '1.0.0',
},
{
capabilities: {
tools: {},
},
}
);
// ๐ข List available calculator tools
server.setRequestHandler('tools/list', async () => {
return {
tools: [
{
name: 'add',
description: 'โ Add two numbers',
inputSchema: {
type: 'object',
properties: {
a: { type: 'number', description: 'First number' },
b: { type: 'number', description: 'Second number' },
},
required: ['a', 'b'],
},
},
{
name: 'multiply',
description: 'โ๏ธ Multiply two numbers',
inputSchema: {
type: 'object',
properties: {
a: { type: 'number', description: 'First number' },
b: { type: 'number', description: 'Second number' },
},
required: ['a', 'b'],
},
},
{
name: 'calculate_tip',
description: '๐ฐ Calculate tip for a bill',
inputSchema: {
type: 'object',
properties: {
billAmount: { type: 'number', description: 'Bill amount' },
tipPercent: { type: 'number', description: 'Tip percentage' },
},
required: ['billAmount', 'tipPercent'],
},
},
],
};
});
// ๐ฏ Handle calculator operations
server.setRequestHandler('tools/call', async (request) => {
const { name, arguments: args } = request.params;
switch (name) {
case 'add':
const sum = args.a + args.b;
return {
content: [
{
type: 'text',
text: `โ ${args.a} + ${args.b} = ${sum}`,
},
],
};
case 'multiply':
const product = args.a * args.b;
return {
content: [
{
type: 'text',
text: `โ๏ธ ${args.a} ร ${args.b} = ${product}`,
},
],
};
case 'calculate_tip':
const tip = args.billAmount * (args.tipPercent / 100);
const total = args.billAmount + tip;
return {
content: [
{
type: 'text',
text: `๐ฐ Bill: $${args.billAmount.toFixed(2)}\n๐ต Tip (${args.tipPercent}%): $${tip.toFixed(2)}\n๐ณ Total: $${total.toFixed(2)}`,
},
],
};
default:
throw new Error(`Unknown tool: ${name}`);
}
});
// ๐ Start server
const transport = new StdioServerTransport();
server.connect(transport);
console.log('๐ข Calculator MCP Server ready!');
Real-life analogy: This is like having a smart calculator that not only does math but also explains what it's doing and can handle real-world scenarios like tip calculations.
๐ Working with Resources
๐ What are Resources?
Resources are data sources that your MCP server can read from. Think of them as information libraries that the AI can access.
๐ File System Resource Example:
// file-server.js
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import fs from 'fs/promises';
import path from 'path';
const server = new Server(
{
name: 'file-mcp-server',
version: '1.0.0',
},
{
capabilities: {
resources: {},
},
}
);
// ๐ List available files
server.setRequestHandler('resources/list', async () => {
try {
const files = await fs.readdir('./documents');
return {
resources: files.map(file => ({
uri: `file://${file}`,
name: file,
description: `๐ Document: ${file}`,
mimeType: 'text/plain',
})),
};
} catch (error) {
return { resources: [] };
}
});
// ๐ Read file content
server.setRequestHandler('resources/read', async (request) => {
const { uri } = request.params;
const fileName = uri.replace('file://', '');
const filePath = path.join('./documents', fileName);
try {
const content = await fs.readFile(filePath, 'utf8');
return {
contents: [
{
uri,
mimeType: 'text/plain',
text: content,
},
],
};
} catch (error) {
throw new Error(`Could not read file: ${fileName}`);
}
});
// ๐ง Add a tool to create files
server.setRequestHandler('tools/list', async () => {
return {
tools: [
{
name: 'create_file',
description: '๐ Create a new text file',
inputSchema: {
type: 'object',
properties: {
filename: { type: 'string', description: 'Name of the file' },
content: { type: 'string', description: 'File content' },
},
required: ['filename', 'content'],
},
},
],
};
});
server.setRequestHandler('tools/call', async (request) => {
const { name, arguments: args } = request.params;
if (name === 'create_file') {
const filePath = path.join('./documents', args.filename);
await fs.writeFile(filePath, args.content, 'utf8');
return {
content: [
{
type: 'text',
text: `โ
File '${args.filename}' created successfully!`,
},
],
};
}
throw new Error(`Unknown tool: ${name}`);
});
// ๐ Start server
const transport = new StdioServerTransport();
server.connect(transport);
console.log('๐ File MCP Server ready!');
Real-life analogy: This is like having a librarian who can both find books for you to read and help you write new books to add to the library.
๐ Database Integration MCP Server
๐๏ธ SQLite Database Example:
// database-server.js
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import sqlite3 from 'sqlite3';
import { open } from 'sqlite';
// ๐๏ธ Database setup
let db;
async function initDatabase() {
db = await open({
filename: './users.db',
driver: sqlite3.Database,
});
// ๐ Create users table
await db.exec(`
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT UNIQUE NOT NULL,
age INTEGER,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
)
`);
// ๐ Insert sample data
await db.run(`
INSERT OR IGNORE INTO users (name, email, age) VALUES
('Alice Johnson', 'alice@example.com', 28),
('Bob Smith', 'bob@example.com', 35),
('Charlie Brown', 'charlie@example.com', 22)
`);
}
const server = new Server(
{
name: 'database-mcp-server',
version: '1.0.0',
},
{
capabilities: {
tools: {},
resources: {},
},
}
);
// ๐ง Database tools
server.setRequestHandler('tools/list', async () => {
return {
tools: [
{
name: 'get_users',
description: '๐ฅ Get all users from database',
inputSchema: {
type: 'object',
properties: {},
},
},
{
name: 'add_user',
description: 'โ Add a new user',
inputSchema: {
type: 'object',
properties: {
name: { type: 'string', description: 'User name' },
email: { type: 'string', description: 'User email' },
age: { type: 'number', description: 'User age' },
},
required: ['name', 'email', 'age'],
},
},
{
name: 'search_users',
description: '๐ Search users by name',
inputSchema: {
type: 'object',
properties: {
name: { type: 'string', description: 'Name to search for' },
},
required: ['name'],
},
},
],
};
});
// ๐ฏ Handle database operations
server.setRequestHandler('tools/call', async (request) => {
const { name, arguments: args } = request.params;
try {
switch (name) {
case 'get_users':
const users = await db.all('SELECT * FROM users ORDER BY created_at DESC');
return {
content: [
{
type: 'text',
text: `๐ฅ Found ${users.length} users:\n\n` +
users.map(user =>
`๐ ${user.name} (${user.age} years old)\n` +
` ๐ง ${user.email}\n` +
` ๐ Joined: ${user.created_at}`
).join('\n\n'),
},
],
};
case 'add_user':
const result = await db.run(
'INSERT INTO users (name, email, age) VALUES (?, ?, ?)',
[args.name, args.email, args.age]
);
return {
content: [
{
type: 'text',
text: `โ
User '${args.name}' added successfully! (ID: ${result.lastID})`,
},
],
};
case 'search_users':
const searchResults = await db.all(
'SELECT * FROM users WHERE name LIKE ? ORDER BY name',
[`%${args.name}%`]
);
if (searchResults.length === 0) {
return {
content: [
{
type: 'text',
text: `โ No users found matching '${args.name}'`,
},
],
};
}
return {
content: [
{
type: 'text',
text: `๐ Found ${searchResults.length} users matching '${args.name}':\n\n` +
searchResults.map(user =>
`๐ ${user.name} (${user.age} years old) - ${user.email}`
).join('\n'),
},
],
};
default:
throw new Error(`Unknown tool: ${name}`);
}
} catch (error) {
return {
content: [
{
type: 'text',
text: `โ Database error: ${error.message}`,
},
],
};
}
});
// ๐ Initialize and start server
async function startServer() {
await initDatabase();
const transport = new StdioServerTransport();
server.connect(transport);
console.log('๐๏ธ Database MCP Server ready!');
}
startServer();
Real-life analogy: This is like having a smart receptionist who can look up customer information, add new customers, and search through records - all while speaking the AI's language.
๐ค๏ธ Weather API MCP Server
๐ก๏ธ External API Integration:
// weather-server.js
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import fetch from 'node-fetch';
const server = new Server(
{
name: 'weather-mcp-server',
version: '1.0.0',
},
{
capabilities: {
tools: {},
},
}
);
// ๐ค๏ธ Weather tools
server.setRequestHandler('tools/list', async () => {
return {
tools: [
{
name: 'get_weather',
description: '๐ค๏ธ Get current weather for a city',
inputSchema: {
type: 'object',
properties: {
city: { type: 'string', description: 'City name' },
country: { type: 'string', description: 'Country code (optional)' },
},
required: ['city'],
},
},
{
name: 'get_weather_forecast',
description: '๐ Get 5-day weather forecast',
inputSchema: {
type: 'object',
properties: {
city: { type: 'string', description: 'City name' },
country: { type: 'string', description: 'Country code (optional)' },
},
required: ['city'],
},
},
],
};
});
// ๐ฏ Handle weather requests
server.setRequestHandler('tools/call', async (request) => {
const { name, arguments: args } = request.params;
// Note: You'll need to get a free API key from openweathermap.org
const API_KEY = 'YOUR_API_KEY_HERE';
const BASE_URL = 'https://api.openweathermap.org/data/2.5';
try {
switch (name) {
case 'get_weather':
const location = args.country ? `${args.city},${args.country}` : args.city;
const weatherResponse = await fetch(
`${BASE_URL}/weather?q=${location}&appid=${API_KEY}&units=metric`
);
if (!weatherResponse.ok) {
throw new Error(`Weather API error: ${weatherResponse.status}`);
}
const weatherData = await weatherResponse.json();
const temp = Math.round(weatherData.main.temp);
const feelsLike = Math.round(weatherData.main.feels_like);
const humidity = weatherData.main.humidity;
const description = weatherData.weather[0].description;
// ๐ก๏ธ Get weather emoji
const getWeatherEmoji = (main) => {
const emojis = {
'Clear': 'โ๏ธ',
'Clouds': 'โ๏ธ',
'Rain': '๐ง๏ธ',
'Snow': 'โ๏ธ',
'Thunderstorm': 'โ๏ธ',
'Drizzle': '๐ฆ๏ธ',
'Mist': '๐ซ๏ธ',
'Fog': '๐ซ๏ธ',
};
return emojis[main] || '๐ค๏ธ';
};
const emoji = getWeatherEmoji(weatherData.weather[0].main);
return {
content: [
{
type: 'text',
text: `${emoji} Weather in ${weatherData.name}, ${weatherData.sys.country}\n\n` +
`๐ก๏ธ Temperature: ${temp}ยฐC (feels like ${feelsLike}ยฐC)\n` +
`โ๏ธ Condition: ${description}\n` +
`๐ง Humidity: ${humidity}%\n` +
`๐ช๏ธ Wind: ${weatherData.wind.speed} m/s\n` +
`๐๏ธ Visibility: ${(weatherData.visibility / 1000).toFixed(1)} km`,
},
],
};
case 'get_weather_forecast':
const forecastLocation = args.country ? `${args.city},${args.country}` : args.city;
const forecastResponse = await fetch(
`${BASE_URL}/forecast?q=${forecastLocation}&appid=${API_KEY}&units=metric`
);
if (!forecastResponse.ok) {
throw new Error(`Forecast API error: ${forecastResponse.status}`);
}
const forecastData = await forecastResponse.json();
const dailyForecasts = {};
// ๐ Group by day
forecastData.list.forEach(item => {
const date = new Date(item.dt * 1000).toDateString();
if (!dailyForecasts[date]) {
dailyForecasts[date] = {
temps: [],
conditions: [],
humidity: [],
};
}
dailyForecasts[date].temps.push(item.main.temp);
dailyForecasts[date].conditions.push(item.weather[0].main);
dailyForecasts[date].humidity.push(item.main.humidity);
});
// ๐ Create forecast summary
const forecastSummary = Object.entries(dailyForecasts)
.slice(0, 5)
.map(([date, data]) => {
const avgTemp = Math.round(data.temps.reduce((a, b) => a + b) / data.temps.length);
const maxTemp = Math.round(Math.max(...data.temps));
const minTemp = Math.round(Math.min(...data.temps));
const mostCommonCondition = data.conditions.sort((a, b) =>
data.conditions.filter(v => v === a).length - data.conditions.filter(v => v === b).length
).pop();
const emoji = getWeatherEmoji(mostCommonCondition);
const dayName = new Date(date).toLocaleDateString('en-US', { weekday: 'long' });
return `${emoji} ${dayName}: ${minTemp}ยฐC - ${maxTemp}ยฐC (${mostCommonCondition})`;
})
.join('\n');
return {
content: [
{
type: 'text',
text: `๐ 5-Day Weather Forecast for ${forecastData.city.name}\n\n${forecastSummary}`,
},
],
};
default:
throw new Error(`Unknown tool: ${name}`);
}
} catch (error) {
return {
content: [
{
type: 'text',
text: `โ Weather service error: ${error.message}`,
},
],
};
}
});
// ๐ Start server
const transport = new StdioServerTransport();
server.connect(transport);
console.log('๐ค๏ธ Weather MCP Server ready!');
Real-life analogy: This is like having a personal meteorologist who can check the weather anywhere in the world and give you detailed forecasts in a format that's easy to understand.
๐ Security Best Practices
๐ก๏ธ Essential Security Measures:
// secure-server.js
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import crypto from 'crypto';
// ๐ Configuration with security settings
const CONFIG = {
MAX_REQUEST_SIZE: 1024 * 1024, // 1MB limit
RATE_LIMIT: 100, // requests per minute
ALLOWED_OPERATIONS: ['read', 'search'], // No write operations
ENCRYPTION_KEY: process.env.ENCRYPTION_KEY || 'your-secret-key',
};
class SecureMCPServer {
constructor() {
this.requestCounts = new Map();
this.server = new Server(
{
name: 'secure-mcp-server',
version: '1.0.0',
},
{
capabilities: {
tools: {},
},
}
);
this.setupHandlers();
}
// ๐ Rate limiting
checkRateLimit(clientId) {
const now = Date.now();
const windowStart = now - 60000; // 1 minute window
if (!this.requestCounts.has(clientId)) {
this.requestCounts.set(clientId, []);
}
const requests = this.requestCounts.get(clientId);
const recentRequests = requests.filter(time => time > windowStart);
if (recentRequests.length >= CONFIG.RATE_LIMIT) {
throw new Error('๐ซ Rate limit exceeded. Try again later.');
}
recentRequests.push(now);
this.requestCounts.set(clientId, recentRequests);
}
// ๐งน Input sanitization
sanitizeInput(input) {
if (typeof input !== 'string') return input;
// Remove potential harmful characters
return input
.replace(/[<>\"']/g, '')
.replace(/javascript:/gi, '')
.replace(/on\w+=/gi, '')
.trim();
}
// ๐ Encrypt sensitive data
encryptData(data) {
const cipher = crypto.createCipher('aes-256-cbc', CONFIG.ENCRYPTION_KEY);
let encrypted = cipher.update(data, 'utf8', 'hex');
encrypted += cipher.final('hex');
return encrypted;
}
// ๐ Decrypt sensitive data
decryptData(encryptedData) {
const decipher = crypto.createDecipher('aes-256-cbc', CONFIG.ENCRYPTION_KEY);
let decrypted = decipher.update(encryptedData, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
// ๐ง Setup secure handlers
setupHandlers() {
this.server.setRequestHandler('tools/list', async () => {
return {
tools: [
{
name: 'secure_search',
description: '๐ Search data securely',
inputSchema: {
type: 'object',
properties: {
query: {
type: 'string',
description: 'Search query',
maxLength: 100,
},
},
required: ['query'],
},
},
],
};
});
this.server.setRequestHandler('tools/call', async (request) => {
const clientId = request.meta?.clientId || 'unknown';
try {
// ๐ฆ Check rate limit
this.checkRateLimit(clientId);
const { name, arguments: args } = request.params;
if (name === 'secure_search') {
// ๐งน Sanitize input
const sanitizedQuery = this.sanitizeInput(args.query);
// ๐ Validate query length
if (sanitizedQuery.length > 100) {
throw new Error('๐ซ Query too long. Maximum 100 characters.');
}
// ๐ Perform secure search (example)
const results = this.performSecureSearch(sanitizedQuery);
return {
content: [
{
type: 'text',
text: `๐ Secure search results for "${sanitizedQuery}":\n\n${results}`,
},
],
};
}
throw new Error(`Unknown tool: ${name}`);
} catch (error) {
// ๐ Log security events
console.error(`Security event - Client: ${clientId}, Error: ${error.message}`);
return {
content: [
{
type: 'text',
text: `โ Security Error: ${error.message}`,
},
],
};
}
});
}
// ๐ Secure search implementation
performSecureSearch(query) {
// ๐ฏ Example: Only allow specific search patterns
const allowedPatterns = /^[a-zA-Z0-9\s\-_]+$/;
if (!allowedPatterns.test(query)) {
throw new Error('๐ซ Invalid search pattern');
}
// ๐ Mock search results
const mockResults = [
'๐ Document 1: Safe content',
'๐ Report 2: Authorized data',
'๐ Analysis 3: Public information',
];
return mockResults
.filter(result => result.toLowerCase().includes(query.toLowerCase()))
.join('\n') || 'โ No results found';
}
// ๐ Start secure server
start() {
const transport = new StdioServerTransport();
this.server.connect(transport);
console.log('๐ Secure MCP Server ready!');
}
}
// ๐ Initialize secure server
const secureServer = new SecureMCPServer();
secureServer.start();
Real-life analogy: This is like having a bank vault with multiple security layers - you need proper identification, there are limits on transactions, and everything is monitored and encrypted.
๐งช Testing Your MCP Server
๐ฌ Unit Testing Example:
// test-server.js
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { describe, it, expect, beforeEach } from 'vitest';
describe('MCP Server Tests', () => {
let server;
beforeEach(() => {
server = new Server(
{ name: 'test-server', version: '1.0.0' },
{ capabilities: { tools: {} } }
);
// ๐ง Setup test tools
server.setRequestHandler('tools/list', async () => {
return {
tools: [
{
name: 'test_tool',
description: 'Test tool',
inputSchema: {
type: 'object',
properties: {
input: { type: 'string' },
},
required: ['input'],
},
},
],
};
});
server.setRequestHandler('tools/call', async (request) => {
const { name, arguments: args } = request.params;
if (name === 'test_tool') {
return {
content: [
{
type: 'text',
text: `Echo: ${args.input}`,
},
],
};
}
throw new Error(`Unknown tool: ${name}`);
});
});
// โ
Test tool listing
it('should list available tools', async () => {
const response = await server.request({
method: 'tools/list',
params: {},
});
expect(response.tools).toHaveLength(1);
expect(response.tools[0].name).toBe('test_tool');
});
// โ
Test tool execution
it('should execute tools correctly', async () => {
const response = await server.request({
method: 'tools/call',
params: {
name: 'test_tool',
arguments: { input: 'Hello, Test!' },
},
});
expect(response.content[0].text).toBe('Echo: Hello, Test!');
});
// โ Test error handling
it('should handle unknown tools', async () => {
try {
await server.request({
method: 'tools/call',
params: {
name: 'unknown_tool',
arguments: {},
},
});
} catch (error) {
expect(error.message).toContain('Unknown tool');
}
});
});
๐ฏ Manual Testing Script:
// manual-test.js
import { spawn } from 'child_process';
import { writeFileSync, readFileSync } from 'fs';
class MCPTester {
constructor(serverPath) {
this.serverPath = serverPath;
this.testResults = [];
}
// ๐งช Run test cases
async runTests() {
console.log('๐งช Starting MCP Server Tests...\n');
const testCases = [
{
name: 'List Tools',
request: { method: 'tools/list', params: {} },
},
{
name: 'Call Tool',
request: {
method: 'tools/call',
params: {
name: 'greet',
arguments: { name: 'Test User' },
},
},
},
{
name: 'Invalid Tool',
request: {
method: 'tools/call',
params: {
name: 'nonexistent',
arguments: {},
},
},
expectError: true,
},
];
for (const testCase of testCases) {
await this.runTestCase(testCase);
}
this.generateReport();
}
// ๐ฏ Run individual test case
async runTestCase(testCase) {
console.log(`๐ Testing: ${testCase.name}`);
try {
const response = await this.sendRequest(testCase.request);
if (testCase.expectError) {
this.testResults.push({
name: testCase.name,
status: 'FAIL',
message: 'Expected error but got success',
});
console.log('โ FAIL - Expected error but got success\n');
} else {
this.testResults.push({
name: testCase.name,
status: 'PASS',
response: response,
});
console.log('โ
PASS\n');
}
} catch (error) {
if (testCase.expectError) {
this.testResults.push({
name: testCase.name,
status: 'PASS',
message: 'Expected error occurred',
});
console.log('โ
PASS - Expected error occurred\n');
} else {
this.testResults.push({
name: testCase.name,
status: 'FAIL',
error: error.message,
});
console.log(`โ FAIL - ${error.message}\n`);
}
}
}
// ๐ก Send request to server
async sendRequest(request) {
return new Promise((resolve, reject) => {
const serverProcess = spawn('node', [this.serverPath]);
let responseData = '';
serverProcess.stdout.on('data', (data) => {
responseData += data.toString();
});
serverProcess.stderr.on('data', (data) => {
reject(new Error(data.toString()));
});
serverProcess.on('close', (code) => {
try {
const response = JSON.parse(responseData);
resolve(response);
} catch (error) {
reject(new Error('Invalid JSON response'));
}
});
// Send request
serverProcess.stdin.write(JSON.stringify(request) + '\n');
serverProcess.stdin.end();
});
}
// ๐ Generate test report
generateReport() {
const passed = this.testResults.filter(r => r.status === 'PASS').length;
const failed = this.testResults.filter(r => r.status === 'FAIL').length;
console.log('๐ Test Results Summary:');
console.log(`โ
Passed: ${passed}`);
console.log(`โ Failed: ${failed}`);
console.log(`๐ Total: ${this.testResults.length}\n`);
if (failed > 0) {
console.log('โ Failed Tests:');
this.testResults
.filter(r => r.status === 'FAIL')
.forEach(result => {
console.log(`- ${result.name}: ${result.error || result.message}`);
});
}
// ๐พ Save detailed report
const report = {
timestamp: new Date().toISOString(),
summary: { passed, failed, total: this.testResults.length },
details: this.testResults,
};
writeFileSync('test-report.json', JSON.stringify(report, null, 2));
console.log('๐พ Detailed report saved to test-report.json');
}
}
// ๐ Run tests
const tester = new MCPTester('./server.js');
tester.runTests();
๐ Deployment and Production
๐ Docker Deployment:
# Dockerfile
FROM node:18-alpine
# ๐ Set working directory
WORKDIR /app
# ๐ฆ Copy package files
COPY package*.json ./
# ๐ง Install dependencies
RUN npm ci --only=production
# ๐ Copy application code
COPY . .
# ๐ค Create non-root user
RUN addgroup -g 1001 -S nodejs
RUN adduser -S mcp -u 1001
# ๐ Set permissions
RUN chown -R mcp:nodejs /app
USER mcp
# ๐ Expose port (if using HTTP transport)
EXPOSE 3000
# ๐โโ๏ธ Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD node healthcheck.js
# ๐ Start server
CMD ["node", "server.js"]
๐ณ Docker Compose Setup:
# docker-compose.yml
version: '3.8'
services:
mcp-server:
build: .
container_name: mcp-server
restart: unless-stopped
environment:
- NODE_ENV=production
- API_KEY=${API_KEY}
- DATABASE_URL=${DATABASE_URL}
volumes:
- ./data:/app/data
- ./logs:/app/logs
networks:
- mcp-network
healthcheck:
test: ["CMD", "node", "healthcheck.js"]
interval: 30s
timeout: 10s
retries: 3
# ๐๏ธ Database (if needed)
database:
image: postgres:15-alpine
container_name: mcp-database
restart: unless-stopped
environment:
- POSTGRES_DB=mcpserver
- POSTGRES_USER=${DB_USER}
- POSTGRES_PASSWORD=${DB_PASSWORD}
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- mcp-network
# ๐ Monitoring (optional)
prometheus:
image: prom/prometheus:latest
container_name: mcp-prometheus
restart: unless-stopped
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
networks:
- mcp-network
volumes:
postgres_data:
networks:
mcp-network:
driver: bridge
๐ Monitoring and Logging:
// monitoring.js
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import winston from 'winston';
import promClient from 'prom-client';
// ๐ Metrics setup
const register = new promClient.Registry();
const requestCounter = new promClient.Counter({
name: 'mcp_requests_total',
help: 'Total number of MCP requests',
labelNames: ['method', 'status'],
});
const requestDuration = new promClient.Histogram({
name: 'mcp_request_duration_seconds',
help: 'Duration of MCP requests in seconds',
labelNames: ['method'],
});
register.registerMetric(requestCounter);
register.registerMetric(requestDuration);
// ๐ Logger setup
const logger = winston.createLogger({
level: 'info',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.errors({ stack: true }),
winston.format.json()
),
defaultMeta: { service: 'mcp-server' },
transports: [
new winston.transports.File({ filename: 'logs/error.log', level: 'error' }),
new winston.transports.File({ filename: 'logs/combined.log' }),
new winston.transports.Console({
format: winston.format.simple()
}),
],
});
class MonitoredMCPServer {
constructor() {
this.server = new Server(
{
name: 'monitored-mcp-server',
version: '1.0.0',
},
{
capabilities: {
tools: {},
},
}
);
this.setupHandlers();
}
// ๐ง Setup monitored handlers
setupHandlers() {
// ๐ง Tools list with monitoring
this.server.setRequestHandler('tools/list', async (request) => {
const timer = requestDuration.startTimer({ method: 'tools/list' });
try {
logger.info('Tools list requested');
const response = {
tools: [
{
name: 'monitored_tool',
description: '๐ A tool with monitoring',
inputSchema: {
type: 'object',
properties: {
input: { type: 'string' },
},
required: ['input'],
},
},
],
};
requestCounter.inc({ method: 'tools/list', status: 'success' });
logger.info('Tools list served successfully');
return response;
} catch (error) {
requestCounter.inc({ method: 'tools/list', status: 'error' });
logger.error('Error serving tools list', { error: error.message });
throw error;
} finally {
timer();
}
});
// ๐ฏ Tool call with monitoring
this.server.setRequestHandler('tools/call', async (request) => {
const timer = requestDuration.startTimer({ method: 'tools/call' });
const { name, arguments: args } = request.params;
try {
logger.info('Tool call requested', { toolName: name, args });
if (name === 'monitored_tool') {
const response = {
content: [
{
type: 'text',
text: `๐ Monitored response: ${args.input}`,
},
],
};
requestCounter.inc({ method: 'tools/call', status: 'success' });
logger.info('Tool call completed successfully', { toolName: name });
return response;
}
throw new Error(`Unknown tool: ${name}`);
} catch (error) {
requestCounter.inc({ method: 'tools/call', status: 'error' });
logger.error('Tool call failed', {
toolName: name,
error: error.message,
args
});
throw error;
} finally {
timer();
}
});
}
// ๐ Metrics endpoint
async getMetrics() {
return register.metrics();
}
// ๐ Start monitored server
start() {
const transport = new StdioServerTransport();
this.server.connect(transport);
logger.info('Monitored MCP Server started');
console.log('๐ Monitored MCP Server ready!');
}
}
// ๐ Initialize monitored server
const monitoredServer = new MonitoredMCPServer();
monitoredServer.start();
๐ฏ Advanced MCP Patterns
๐ Multi-Service Orchestration:
// orchestrator-server.js
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
class ServiceOrchestrator {
constructor() {
this.services = {
database: new DatabaseService(),
weather: new WeatherService(),
email: new EmailService(),
};
this.server = new Server(
{
name: 'orchestrator-mcp-server',
version: '1.0.0',
},
{
capabilities: {
tools: {},
},
}
);
this.setupHandlers();
}
// ๐ง Setup orchestration tools
setupHandlers() {
this.server.setRequestHandler('tools/list', async () => {
return {
tools: [
{
name: 'daily_report',
description: '๐ Generate daily report combining multiple services',
inputSchema: {
type: 'object',
properties: {
userId: { type: 'string', description: 'User ID' },
includeWeather: { type: 'boolean', description: 'Include weather data' },
},
required: ['userId'],
},
},
{
name: 'smart_notification',
description: '๐ Send smart notification based on conditions',
inputSchema: {
type: 'object',
properties: {
userId: { type: 'string', description: 'User ID' },
message: { type: 'string', description: 'Message to send' },
},
required: ['userId', 'message'],
},
},
],
};
});
this.server.setRequestHandler('tools/call', async (request) => {
const { name, arguments: args } = request.params;
switch (name) {
case 'daily_report':
return await this.generateDailyReport(args);
case 'smart_notification':
return await this.sendSmartNotification(args);
default:
throw new Error(`Unknown tool: ${name}`);
}
});
}
// ๐ Generate comprehensive daily report
async generateDailyReport(args) {
try {
// ๐ค Get user data
const userData = await this.services.database.getUser(args.userId);
// ๐ Get user activity
const activity = await this.services.database.getUserActivity(args.userId);
let weatherData = '';
if (args.includeWeather) {
// ๐ค๏ธ Get weather for user's location
weatherData = await this.services.weather.getWeather(userData.location);
}
// ๐ Compile report
const report = {
user: userData.name,
date: new Date().toDateString(),
activity: {
tasksCompleted: activity.tasksCompleted,
timeSpent: activity.timeSpent,
productivity: this.calculateProductivity(activity),
},
weather: weatherData,
recommendations: this.generateRecommendations(activity, weatherData),
};
return {
content: [
{
type: 'text',
text: this.formatReport(report),
},
],
};
} catch (error) {
return {
content: [
{
type: 'text',
text: `โ Error generating report: ${error.message}`,
},
],
};
}
}
// ๐ Send intelligent notification
async sendSmartNotification(args) {
try {
// ๐ค Get user preferences
const userData = await this.services.database.getUser(args.userId);
// ๐ค๏ธ Check weather conditions
const weather = await this.services.weather.getWeather(userData.location);
// ๐ฏ Customize message based on context
let customizedMessage = args.message;
if (weather.temperature < 10) {
customizedMessage += '\n๐งฅ Don\'t forget your jacket - it\'s cold outside!';
} else if (weather.condition === 'Rain') {
customizedMessage += '\nโ๏ธ Take an umbrella - it\'s raining!';
}
// ๐ง Send email notification
await this.services.email.send({
to: userData.email,
subject: 'Smart Notification',
message: customizedMessage,
});
return {
content: [
{
type: 'text',
text: `โ
Smart notification sent to ${userData.name} (${userData.email})`,
},
],
};
} catch (error) {
return {
content: [
{
type: 'text',
text: `โ Error sending notification: ${error.message}`,
},
],
};
}
}
// ๐ Calculate productivity score
calculateProductivity(activity) {
const baseScore = (activity.tasksCompleted * 10) + (activity.timeSpent * 0.1);
return Math.min(100, Math.round(baseScore));
}
// ๐ก Generate personalized recommendations
generateRecommendations(activity, weather) {
const recommendations = [];
if (activity.productivity < 50) {
recommendations.push('๐ฏ Try the Pomodoro technique to boost productivity');
}
if (activity.timeSpent > 8) {
recommendations.push('๐ด Take more breaks to avoid burnout');
}
if (weather && weather.condition === 'Clear') {
recommendations.push('๐ Great weather for a outdoor break!');
}
return recommendations;
}
// ๐ Format report nicely
formatReport(report) {
return `๐ Daily Report for ${report.user}
๐
Date: ${report.date}
๐ฏ Activity Summary:
โ
Tasks Completed: ${report.activity.tasksCompleted}
โฑ๏ธ Time Spent: ${report.activity.timeSpent} hours
๐ Productivity Score: ${report.activity.productivity}/100
${report.weather ? `๐ค๏ธ Weather: ${report.weather}` : ''}
๐ก Recommendations:
${report.recommendations.map(r => `โข ${r}`).join('\n')}
๐ Keep up the great work!`;
}
// ๐ Start orchestrator
start() {
const transport = new StdioServerTransport();
this.server.connect(transport);
console.log('๐ญ Orchestrator MCP Server ready!');
}
}
// ๐ Mock service classes
class DatabaseService {
async getUser(userId) {
return {
id: userId,
name: 'John Doe',
email: 'john@example.com',
location: 'New York',
};
}
async getUserActivity(userId) {
return {
tasksCompleted: 8,
timeSpent: 6.5,
projects: ['Website', 'Mobile App'],
};
}
}
class WeatherService {
async getWeather(location) {
return {
location,
temperature: 22,
condition: 'Clear',
humidity: 65,
};
}
}
class EmailService {
async send(emailData) {
console.log(`๐ง Email sent to ${emailData.to}: ${emailData.subject}`);
return { success: true, messageId: 'msg-123' };
}
}
// ๐ Initialize orchestrator
const orchestrator = new ServiceOrchestrator();
orchestrator.start();
Real-life analogy: This is like having a smart personal assistant who can coordinate between your calendar, weather app, email, and task manager to give you intelligent insights and take actions on your behalf.
๐ Best Practices and Tips
๐ฏ Development Best Practices:
// best-practices-example.js
// โ
DO: Use clear, descriptive tool names
const goodToolName = 'calculate_monthly_budget';
const badToolName = 'calc'; // โ Too vague
// โ
DO: Provide comprehensive input schemas
const goodSchema = {
type: 'object',
properties: {
income: {
type: 'number',
description: 'Monthly income in USD',
minimum: 0,
},
expenses: {
type: 'array',
items: {
type: 'object',
properties: {
category: { type: 'string' },
amount: { type: 'number', minimum: 0 },
},
required: ['category', 'amount'],
},
},
},
required: ['income', 'expenses'],
};
// โ
DO: Handle errors gracefully
async function safeToolCall(toolFunction, params) {
try {
return await toolFunction(params);
} catch (error) {
return {
content: [
{
type: 'text',
text: `โ Error: ${error.message}. Please try again or contact support.`,
},
],
};
}
}
// โ
DO: Validate inputs thoroughly
function validateBudgetInputs(params) {
if (!params.income || params.income <= 0) {
throw new Error('Income must be a positive number');
}
if (!Array.isArray(params.expenses)) {
throw new Error('Expenses must be an array');
}
for (const expense of params.expenses) {
if (!expense.category || expense.amount < 0) {
throw new Error('Each expense must have a category and non-negative amount');
}
}
}
// โ
DO: Use consistent response formats
function createSuccessResponse(data, message) {
return {
content: [
{
type: 'text',
text: `โ
${message}\n\n${data}`,
},
],
};
}
// โ
DO: Log important operations
import winston from 'winston';
const logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
transports: [
new winston.transports.File({ filename: 'mcp-server.log' }),
],
});
function logToolUsage(toolName, params, result) {
logger.info('Tool executed', {
tool: toolName,
params: params,
success: !!result,
timestamp: new Date().toISOString(),
});
}
๐ Security Checklist:
๐ MCP Server Security Checklist:
โ
Input Validation:
- Validate all input parameters
- Sanitize string inputs
- Check data types and ranges
- Prevent SQL injection
โ
Rate Limiting:
- Implement request rate limits
- Monitor unusual usage patterns
- Block suspicious clients
โ
Access Control:
- Authenticate clients when possible
- Implement role-based permissions
- Log all access attempts
โ
Data Protection:
- Encrypt sensitive data
- Use secure communication channels
- Don't log sensitive information
โ
Error Handling:
- Don't expose internal errors
- Provide helpful but safe error messages
- Log errors for debugging
โ
Resource Management:
- Limit resource usage per request
- Implement timeouts
- Clean up resources properly
๐ Performance Optimization:
// performance-optimizations.js
// โ
Connection pooling for databases
import { Pool } from 'pg';
const dbPool = new Pool({
host: 'localhost',
database: 'mydb',
max: 20, // Maximum 20 connections
idleTimeoutMillis: 30000,
connectionTimeoutMillis: 2000,
});
// โ
Caching for frequently accessed data
class CacheManager {
constructor() {
this.cache = new Map();
this.maxSize = 1000;
this.ttl = 5 * 60 * 1000; // 5 minutes
}
set(key, value) {
if (this.cache.size >= this.maxSize) {
// Remove oldest entries
const firstKey = this.cache.keys().next().value;
this.cache.delete(firstKey);
}
this.cache.set(key, {
value,
timestamp: Date.now(),
});
}
get(key) {
const item = this.cache.get(key);
if (!item) return null;
// Check if expired
if (Date.now() - item.timestamp > this.ttl) {
this.cache.delete(key);
return null;
}
return item.value;
}
}
// โ
Batch operations
class BatchProcessor {
constructor(batchSize = 10) {
this.batchSize = batchSize;
this.queue = [];
this.processing = false;
}
async addRequest(request) {
this.queue.push(request);
if (this.queue.length >= this.batchSize && !this.processing) {
await this.processBatch();
}
}
async processBatch() {
this.processing = true;
const batch = this.queue.splice(0, this.batchSize);
try {
// Process all requests in parallel
await Promise.all(batch.map(request => this.processRequest(request)));
} catch (error) {
console.error('Batch processing error:', error);
} finally {
this.processing = false;
}
}
async processRequest(request) {
// Individual request processing logic
return request();
}
}
๐ฏ Real-World Use Cases
๐ข Enterprise Integration Example:
// enterprise-mcp-server.js
class EnterpriseMCPServer {
constructor() {
this.integrations = {
salesforce: new SalesforceIntegration(),
slack: new SlackIntegration(),
jira: new JiraIntegration(),
confluence: new ConfluenceIntegration(),
};
}
// ๐ฏ Sales intelligence tool
async getSalesInsights(params) {
const { accountId, timeframe } = params;
// ๐ Get data from multiple sources
const [salesData, interactions, tickets, documents] = await Promise.all([
this.integrations.salesforce.getAccountData(accountId),
this.integrations.slack.getAccountInteractions(accountId),
this.integrations.jira.getAccountTickets(accountId),
this.integrations.confluence.getAccountDocuments(accountId),
]);
// ๐ง Analyze and combine insights
const insights = this.analyzeSalesData({
sales: salesData,
interactions: interactions,
support: tickets,
knowledge: documents,
});
return {
content: [
{
type: 'text',
text: `๐ Sales Insights for Account ${accountId}:\n\n${insights}`,
},
],
};
}
// ๐ Analyze combined data
analyzeSalesData(data) {
const { sales, interactions, support, knowledge } = data;
return `๐ผ Account Health: ${this.calculateAccountHealth(data)}
๐ Revenue Trend: ${sales.trend}
๐ฌ Recent Interactions: ${interactions.count} (${interactions.sentiment})
๐ซ Open Tickets: ${support.open} | Resolved: ${support.resolved}
๐ Knowledge Engagement: ${knowledge.views} views
๐ฏ Recommendations:
${this.generateSalesRecommendations(data).join('\n')}`;
}
calculateAccountHealth(data) {
// Complex scoring algorithm
return 'Healthy ๐';
}
generateSalesRecommendations(data) {
return [
'โข Schedule follow-up call',
'โข Share case studies',
'โข Address open support tickets',
];
}
}
๐ฅ Healthcare Integration Example:
// healthcare-mcp-server.js
class HealthcareMCPServer {
constructor() {
this.server = new Server(
{
name: 'healthcare-mcp-server',
version: '1.0.0',
},
{
capabilities: {
tools: {},
},
}
);
this.setupHealthcareTools();
}
setupHealthcareTools() {
this.server.setRequestHandler('tools/list', async () => {
return {
tools: [
{
name: 'patient_summary',
description: '๐จโโ๏ธ Generate comprehensive patient summary',
inputSchema: {
type: 'object',
properties: {
patientId: { type: 'string', description: 'Patient ID' },
includeHistory: { type: 'boolean', description: 'Include medical history' },
},
required: ['patientId'],
},
},
{
name: 'medication_interaction_check',
description: '๐ Check for drug interactions',
inputSchema: {
type: 'object',
properties: {
medications: {
type: 'array',
items: { type: 'string' },
description: 'List of medications',
},
},
required: ['medications'],
},
},
{
name: 'appointment_scheduler',
description: '๐
Schedule patient appointments intelligently',
inputSchema: {
type: 'object',
properties: {
patientId: { type: 'string', description: 'Patient ID' },
appointmentType: { type: 'string', description: 'Type of appointment' },
urgency: { type: 'string', enum: ['low', 'medium', 'high'] },
},
required: ['patientId', 'appointmentType'],
},
},
],
};
});
this.server.setRequestHandler('tools/call', async (request) => {
const { name, arguments: args } = request.params;
switch (name) {
case 'patient_summary':
return await this.generatePatientSummary(args);
case 'medication_interaction_check':
return await this.checkMedicationInteractions(args);
case 'appointment_scheduler':
return await this.scheduleAppointment(args);
default:
throw new Error(`Unknown tool: ${name}`);
}
});
}
// ๐จโโ๏ธ Generate comprehensive patient summary
async generatePatientSummary(args) {
try {
// ๐ Get patient data (mock implementation)
const patientData = await this.getPatientData(args.patientId);
const vitals = await this.getLatestVitals(args.patientId);
const medications = await this.getCurrentMedications(args.patientId);
const allergies = await this.getAllergies(args.patientId);
let history = '';
if (args.includeHistory) {
history = await this.getMedicalHistory(args.patientId);
}
const summary = `๐ค Patient Summary: ${patientData.name}
๐ ID: ${patientData.id} | Age: ${patientData.age} | Gender: ${patientData.gender}
๐ฉบ Latest Vitals:
โข Blood Pressure: ${vitals.bloodPressure}
โข Heart Rate: ${vitals.heartRate} bpm
โข Temperature: ${vitals.temperature}ยฐF
โข Weight: ${vitals.weight} lbs
๐ Current Medications:
${medications.map(med => `โข ${med.name} - ${med.dosage}`).join('\n')}
โ ๏ธ Allergies:
${allergies.length > 0 ? allergies.map(allergy => `โข ${allergy}`).join('\n') : 'None on record'}
${history ? `๐ Medical History:\n${history}` : ''}
๐จ Alerts:
${this.generateHealthAlerts(patientData, vitals, medications).join('\n')}`;
return {
content: [
{
type: 'text',
text: summary,
},
],
};
} catch (error) {
return {
content: [
{
type: 'text',
text: `โ Error generating patient summary: ${error.message}`,
},
],
};
}
}
// ๐ Check medication interactions
async checkMedicationInteractions(args) {
try {
const interactions = await this.analyzeInteractions(args.medications);
if (interactions.length === 0) {
return {
content: [
{
type: 'text',
text: 'โ
No medication interactions detected.',
},
],
};
}
const interactionReport = `โ ๏ธ Medication Interaction Analysis:
${interactions.map(interaction =>
`๐ด ${interaction.severity.toUpperCase()}: ${interaction.drug1} + ${interaction.drug2}
๐ Effect: ${interaction.effect}
๐ก Recommendation: ${interaction.recommendation}`
).join('\n\n')}
๐ Please consult with pharmacist or physician for review.`;
return {
content: [
{
type: 'text',
text: interactionReport,
},
],
};
} catch (error) {
return {
content: [
{
type: 'text',
text: `โ Error checking interactions: ${error.message}`,
},
],
};
}
}
// ๐
Intelligent appointment scheduling
async scheduleAppointment(args) {
try {
const patientData = await this.getPatientData(args.patientId);
const availableSlots = await this.getAvailableSlots(args.appointmentType);
const optimalSlot = this.findOptimalSlot(availableSlots, args.urgency, patientData);
const appointment = await this.bookAppointment({
patientId: args.patientId,
slot: optimalSlot,
type: args.appointmentType,
});
return {
content: [
{
type: 'text',
text: `โ
Appointment Scheduled Successfully!
๐ค Patient: ${patientData.name}
๐
Date: ${optimalSlot.date}
๐ Time: ${optimalSlot.time}
๐ฅ Type: ${args.appointmentType}
๐จโโ๏ธ Provider: ${optimalSlot.provider}
๐ Location: ${optimalSlot.location}
๐ Appointment ID: ${appointment.id}
๐ฒ Confirmation sent to: ${patientData.phone}
๐ง Reminder email sent to: ${patientData.email}`,
},
],
};
} catch (error) {
return {
content: [
{
type: 'text',
text: `โ Error scheduling appointment: ${error.message}`,
},
],
};
}
}
// ๐ Mock data methods (replace with real integrations)
async getPatientData(patientId) {
return {
id: patientId,
name: 'John Smith',
age: 45,
gender: 'Male',
phone: '(555) 123-4567',
email: 'john.smith@email.com',
};
}
async getLatestVitals(patientId) {
return {
bloodPressure: '120/80',
heartRate: 72,
temperature: 98.6,
weight: 180,
};
}
async getCurrentMedications(patientId) {
return [
{ name: 'Lisinopril', dosage: '10mg daily' },
{ name: 'Metformin', dosage: '500mg twice daily' },
];
}
async getAllergies(patientId) {
return ['Penicillin', 'Shellfish'];
}
generateHealthAlerts(patient, vitals, medications) {
const alerts = [];
if (vitals.heartRate > 100) {
alerts.push('๐ด Elevated heart rate detected');
}
if (medications.length > 5) {
alerts.push('โ ๏ธ Multiple medications - consider interaction review');
}
return alerts.length > 0 ? alerts : ['โ
No current alerts'];
}
}
๐ซ Education Platform Example:
// education-mcp-server.js
class EducationMCPServer {
constructor() {
this.server = new Server(
{
name: 'education-mcp-server',
version: '1.0.0',
},
{
capabilities: {
tools: {},
resources: {},
},
}
);
this.setupEducationTools();
}
setupEducationTools() {
this.server.setRequestHandler('tools/list', async () => {
return {
tools: [
{
name: 'student_progress_report',
description: '๐ Generate comprehensive student progress report',
inputSchema: {
type: 'object',
properties: {
studentId: { type: 'string', description: 'Student ID' },
subject: { type: 'string', description: 'Subject (optional)' },
timeframe: { type: 'string', description: 'Time period (week/month/semester)' },
},
required: ['studentId'],
},
},
{
name: 'personalized_study_plan',
description: '๐ฏ Create personalized study plan',
inputSchema: {
type: 'object',
properties: {
studentId: { type: 'string', description: 'Student ID' },
goal: { type: 'string', description: 'Learning goal' },
timeAvailable: { type: 'number', description: 'Hours per week' },
},
required: ['studentId', 'goal', 'timeAvailable'],
},
},
{
name: 'assignment_feedback',
description: '๐ Generate detailed assignment feedback',
inputSchema: {
type: 'object',
properties: {
assignmentId: { type: 'string', description: 'Assignment ID' },
studentId: { type: 'string', description: 'Student ID' },
includeImprovement: { type: 'boolean', description: 'Include improvement suggestions' },
},
required: ['assignmentId', 'studentId'],
},
},
],
};
});
this.server.setRequestHandler('tools/call', async (request) => {
const { name, arguments: args } = request.params;
switch (name) {
case 'student_progress_report':
return await this.generateProgressReport(args);
case 'personalized_study_plan':
return await this.createStudyPlan(args);
case 'assignment_feedback':
return await this.generateAssignmentFeedback(args);
default:
throw new Error(`Unknown tool: ${name}`);
}
});
}
// ๐ Generate student progress report
async generateProgressReport(args) {
try {
const student = await this.getStudentData(args.studentId);
const grades = await this.getGrades(args.studentId, args.subject, args.timeframe);
const attendance = await this.getAttendance(args.studentId, args.timeframe);
const assignments = await this.getAssignments(args.studentId, args.timeframe);
const report = `๐ Progress Report: ${student.name}
๐ Student ID: ${student.id} | Grade: ${student.grade} | Class: ${student.class}
๐ Academic Performance:
${this.formatGrades(grades)}
๐
Attendance: ${attendance.present}/${attendance.total} days (${attendance.percentage}%)
๐ Assignment Status:
โข Completed: ${assignments.completed}
โข Pending: ${assignments.pending}
โข Overdue: ${assignments.overdue}
โข Average Score: ${assignments.averageScore}%
๐ฏ Performance Analysis:
${this.analyzePerformance(grades, attendance, assignments).join('\n')}
๐ Trends:
${this.identifyTrends(grades).join('\n')}
๐ก Recommendations:
${this.generateRecommendations(student, grades, attendance, assignments).join('\n')}`;
return {
content: [
{
type: 'text',
text: report,
},
],
};
} catch (error) {
return {
content: [
{
type: 'text',
text: `โ Error generating progress report: ${error.message}`,
},
],
};
}
}
// ๐ฏ Create personalized study plan
async createStudyPlan(args) {
try {
const student = await this.getStudentData(args.studentId);
const weakAreas = await this.identifyWeakAreas(args.studentId);
const learningStyle = await this.getLearningStyle(args.studentId);
const studyPlan = this.generateStudyPlan({
student,
goal: args.goal,
timeAvailable: args.timeAvailable,
weakAreas,
learningStyle,
});
return {
content: [
{
type: 'text',
text: studyPlan,
},
],
};
} catch (error) {
return {
content: [
{
type: 'text',
text: `โ Error creating study plan: ${error.message}`,
},
],
};
}
}
generateStudyPlan(data) {
const { student, goal, timeAvailable, weakAreas, learningStyle } = data;
return `๐ฏ Personalized Study Plan for ${student.name}
๐ฏ Goal: ${goal}
โฐ Time Available: ${timeAvailable} hours/week
๐ง Learning Style: ${learningStyle.primary}
๐ Weekly Schedule:
${this.createWeeklySchedule(timeAvailable, weakAreas)}
๐ Focus Areas:
${weakAreas.map(area => `โข ${area.subject}: ${area.topics.join(', ')}`).join('\n')}
๐ Recommended Resources:
${this.getRecommendedResources(weakAreas, learningStyle)}
๐ฏ Milestones:
${this.createMilestones(goal).join('\n')}
๐ Progress Tracking:
โข Weekly self-assessment quizzes
โข Bi-weekly review sessions
โข Monthly progress evaluation`;
}
createWeeklySchedule(hoursAvailable, weakAreas) {
const schedule = [];
const daysOfWeek = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
const hoursPerDay = Math.ceil(hoursAvailable / 7);
daysOfWeek.forEach((day, index) => {
if (index < hoursAvailable) {
const area = weakAreas[index % weakAreas.length];
schedule.push(`${day}: ${hoursPerDay}h - ${area.subject} (${area.priority})`);
}
});
return schedule.join('\n');
}
// ๐ Generate assignment feedback
async generateAssignmentFeedback(args) {
try {
const assignment = await this.getAssignment(args.assignmentId);
const submission = await this.getSubmission(args.assignmentId, args.studentId);
const rubric = await this.getRubric(args.assignmentId);
const feedback = this.analyzeFeedback(assignment, submission, rubric);
let report = `๐ Assignment Feedback
๐ Assignment: ${assignment.title}
๐ค Student: ${submission.studentName}
๐
Submitted: ${submission.submittedAt}
โญ Score: ${submission.score}/${assignment.maxScore} (${submission.percentage}%)
๐ฏ Strengths:
${feedback.strengths.join('\n')}
๐ Areas for Improvement:
${feedback.improvements.join('\n')}
๐ Rubric Breakdown:
${this.formatRubricScores(submission.rubricScores)}`;
if (args.includeImprovement) {
report += `\n\n๐ก Specific Improvement Suggestions:
${feedback.suggestions.join('\n')}
๐ Recommended Resources:
${feedback.resources.join('\n')}`;
}
return {
content: [
{
type: 'text',
text: report,
},
],
};
} catch (error) {
return {
content: [
{
type: 'text',
text: `โ Error generating feedback: ${error.message}`,
},
],
};
}
}
// ๐ Mock data methods
async getStudentData(studentId) {
return {
id: studentId,
name: 'Emma Johnson',
grade: '10th Grade',
class: '10-A',
};
}
async getGrades(studentId, subject, timeframe) {
return {
math: 85,
science: 92,
english: 78,
history: 88,
};
}
async identifyWeakAreas(studentId) {
return [
{
subject: 'Mathematics',
topics: ['Algebra', 'Geometry'],
priority: 'High',
},
{
subject: 'English',
topics: ['Essay Writing', 'Grammar'],
priority: 'Medium',
},
];
}
}
๐ Conclusion and Next Steps
Congratulations! ๐ You've just completed a comprehensive journey through the world of MCP Servers. Let's recap what you've mastered:
๐ฏ What You've Learned:
๐๏ธ Core Concepts:
- ๐ก MCP Protocol - The bridge between AI and external services
- ๐ง Tools - Functions that AI can execute
- ๐ Resources - Data sources AI can access
- ๐ Server Architecture - How everything connects together
๐ป Technical Skills:
- โก Basic Server Setup - Your first "Hello World" MCP server
- ๐๏ธ Database Integration - Connecting to SQLite and other databases
- ๐ API Integration - Weather services and external APIs
- ๐ Security Implementation - Rate limiting, validation, encryption
- ๐งช Testing Strategies - Unit tests and manual testing
- ๐ Deployment - Docker, monitoring, and production setup
๐ช Advanced Patterns:
- ๐ญ Service Orchestration - Combining multiple services intelligently
- ๐ข Enterprise Integration - Real-world business applications
- ๐ฅ Domain-Specific Solutions - Healthcare, education, and more
- ๐ Performance Optimization - Caching, batching, connection pooling
๐ Your MCP Journey Roadmap:
๐ฑ Beginner Level (You are here!):
- โ Understand MCP concepts
- โ Build basic tools and resources
- โ Handle simple integrations
- โ Implement basic security
๐ฟ Intermediate Level (Next steps):
- ๐ฏ Build Complex Integrations - Multi-service orchestration
- ๐ Implement Workflows - Chain multiple tools together
- ๐ Add Analytics - Track usage and performance
- ๐จ Create Domain-Specific Servers - For your industry
- ๐ง Optimize Performance - Caching and scaling
๐ณ Advanced Level (Future goals):
- ๐๏ธ Microservices Architecture - Distributed MCP systems
- ๐ค AI-Powered Tools - Tools that use AI internally
- ๐ Protocol Extensions - Custom MCP capabilities
- ๐ข Enterprise Solutions - Large-scale deployments
- ๐ Contribute to MCP - Help improve the protocol
๐ก Project Ideas to Practice:
๐ Personal Projects:
- ๐ Personal Assistant Server - Calendar, email, tasks, weather
- ๐ฐ Finance Manager - Budget tracking, expense analysis
- ๐โโ๏ธ Fitness Tracker - Workout plans, nutrition, progress
- ๐ Learning Companion - Study schedules, progress tracking
- ๐ก Smart Home Controller - IoT device integration
๐ข Business Projects:
- ๐ CRM Integration - Sales data, customer insights
- ๐ Analytics Dashboard - Business metrics, reporting
- ๐ซ Support Ticket System - Customer service automation
- ๐ฆ Inventory Manager - Stock tracking, reorder alerts
- ๐ฅ HR Assistant - Employee data, scheduling, reviews
๐ Community Projects:
- ๐ฑ Environmental Monitor - Air quality, weather data
- ๐ Transit Information - Bus schedules, route planning
- ๐ฐ News Aggregator - Local news, event information
- ๐ญ Event Organizer - Community events, RSVPs
- ๐ Library System - Book recommendations, availability
๐ Additional Resources:
๐ Learn More:
- MCP Official Documentation - Latest specifications and examples
- AI Integration Patterns - Best practices for AI-tool communication
- API Design Principles - Creating robust, scalable interfaces
- Security in AI Systems - Protecting AI-enabled applications
๐ ๏ธ Tools and Libraries:
- MCP SDK - Official development kit
- Testing Frameworks - Vitest, Jest, or your preferred framework
- Monitoring Tools - Prometheus, Grafana for production monitoring
- Deployment Platforms - Docker, Kubernetes, cloud services
๐ค Community:
- GitHub Repositories - Explore open-source MCP servers
- Developer Forums - Ask questions, share experiences
- AI Developer Communities - Connect with other AI builders
- Local Meetups - Find AI and development groups near you
๐ฏ Remember:
"The best way to learn MCP is by building MCP servers!"
Start with simple projects and gradually increase complexity. Every expert was once a beginner, and every professional was once an amateur. The key is to:
- ๐ Practice Regularly - Build something new each week
- ๐งช Experiment Fearlessly - Try new integrations and patterns
- ๐ค Share Your Work - Get feedback from the community
- ๐ Keep Learning - Stay updated with MCP developments
- ๐ฏ Solve Real Problems - Build tools that genuinely help people
๐ Final Thoughts:
MCP Servers represent the future of AI integration - a standardized way for AI systems to interact with the digital world. By mastering MCP, you're not just learning a technology; you're preparing for a future where AI assistants can seamlessly work with any service or system.
Whether you're building personal productivity tools, enterprise integrations, or the next generation of AI-powered applications, the skills you've learned here will serve as your foundation.
Go forth and build amazing things! ๐
The world needs more AI integrations, and now you have the knowledge to create them. Start small, think big, and remember - every great MCP server started with a simple console.log('MCP Server ready!')
.
Happy Building! ๐ ๏ธ๐จโ๐ป๐ฉโ๐ป
Found this guide helpful? Share it with other developers who want to build the future of AI integration! ๐ค
๐ Quick Reference:
// ๐ Quick MCP Server Template
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
const server = new Server({
name: 'my-awesome-server',
version: '1.0.0',
}, {
capabilities: { tools: {}, resources: {} }
});
// Add your tools here
server.setRequestHandler('tools/list', async () => ({ tools: [] }));
server.setRequestHandler('tools/call', async (request) => { /* handle */ });
// Start server
const transport = new StdioServerTransport();
server.connect(transport);
console.log('๐ MCP Server ready!');
Save this template and start building your next MCP server today! โญ