MCP (Model Context Protocol) Introduction
Model Context Protocol (MCP) is an open protocol that enables AI assistants like Claude to securely connect to external data sources and tools, extending their capabilities beyond their training data.
π― What is MCP?β
MCP allows AI models to:
- Access External Data - Connect to databases, APIs, file systems
- Use External Tools - Execute commands, run scripts, interact with services
- Maintain Context - Keep track of conversation context across tools
- Security - Controlled, permission-based access to resources
ποΈ MCP Architectureβ
Componentsβ
- MCP Client - Integrated into AI assistants (like Claude Desktop)
- MCP Server - Provides tools and resources to the client
- Transport Layer - Communication protocol (stdio, WebSocket, HTTP)
- Resources - External data sources (files, databases, APIs)
- Tools - Executable functions and capabilities
π Getting Startedβ
Prerequisitesβ
- Node.js 18+ or Python 3.8+
- Basic understanding of APIs and JSON
- Familiarity with command line tools
Installationβ
TypeScript/Node.jsβ
npm install @modelcontextprotocol/sdk
Pythonβ
pip install mcp
π¦ Your First MCP Serverβ
Simple Echo Server (TypeScript)β
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
const server = new Server({
name: 'echo-server',
version: '1.0.0'
}, {
capabilities: {
tools: {}
}
});
// Define a simple echo tool
server.setRequestHandler('tools/list', async () => {
return {
tools: [{
name: 'echo',
description: 'Echoes back the provided text',
inputSchema: {
type: 'object',
properties: {
message: {
type: 'string',
description: 'The message to echo back'
}
},
required: ['message']
}
}]
};
});
server.setRequestHandler('tools/call', async (request) => {
if (request.params.name === 'echo') {
const message = request.params.arguments?.message;
return {
content: [{
type: 'text',
text: `Echo: ${message}`
}]
};
}
throw new Error('Unknown tool');
});
// Start the server
const transport = new StdioServerTransport();
await server.connect(transport);
Simple File Server (Python)β
import asyncio
import json
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp.types import Tool, TextContent
app = Server("file-server")
@app.list_tools()
async def list_tools() -> list[Tool]:
return [
Tool(
name="read_file",
description="Read contents of a file",
inputSchema={
"type": "object",
"properties": {
"filepath": {
"type": "string",
"description": "Path to the file to read"
}
},
"required": ["filepath"]
}
)
]
@app.call_tool()
async def call_tool(name: str, arguments: dict) -> list[TextContent]:
if name == "read_file":
filepath = arguments["filepath"]
try:
with open(filepath, 'r') as file:
content = file.read()
return [TextContent(type="text", text=content)]
except Exception as e:
return [TextContent(type="text", text=f"Error: {str(e)}")]
raise ValueError(f"Unknown tool: {name}")
if __name__ == "__main__":
asyncio.run(stdio_server(app))
π§ MCP Server Configurationβ
Claude Desktop Integrationβ
Add to claude_desktop_config.json:
{
"mcpServers": {
"echo-server": {
"command": "node",
"args": ["path/to/your/echo-server.js"]
},
"file-server": {
"command": "python",
"args": ["path/to/your/file-server.py"]
}
}
}
Server Capabilitiesβ
const server = new Server({
name: 'my-server',
version: '1.0.0'
}, {
capabilities: {
tools: {}, // Provides executable tools
resources: {}, // Provides data resources
prompts: {}, // Provides prompt templates
logging: {} // Supports logging
}
});
π οΈ Advanced Featuresβ
Resource Providersβ
// List available resources
server.setRequestHandler('resources/list', async () => {
return {
resources: [{
uri: 'file://docs/readme.md',
name: 'Project README',
description: 'Main project documentation'
}]
};
});
// Read specific resource
server.setRequestHandler('resources/read', async (request) => {
const uri = request.params.uri;
// Implementation to read resource
return {
contents: [{
uri: uri,
mimeType: 'text/markdown',
text: 'Resource content...'
}]
};
});
Error Handlingβ
server.setRequestHandler('tools/call', async (request) => {
try {
// Tool implementation
return { content: [{ type: 'text', text: 'Success!' }] };
} catch (error) {
return {
content: [{
type: 'text',
text: `Error: ${error.message}`
}],
isError: true
};
}
});
π Testing Your MCP Serverβ
Manual Testing with MCP Inspectorβ
npx @modelcontextprotocol/inspector
Unit Testingβ
import { describe, it, expect } from 'vitest';
import { MockTransport } from '@modelcontextprotocol/sdk/testing';
describe('Echo Server', () => {
it('should echo messages correctly', async () => {
const transport = new MockTransport();
// Test implementation
});
});
π Best Practicesβ
- Security First - Validate all inputs, limit file access
- Error Handling - Provide clear error messages
- Documentation - Well-documented tool schemas
- Performance - Async operations, timeout handling
- Logging - Comprehensive logging for debugging
π Next Stepsβ
- Advanced MCP Tools (coming soon)
- MCP Security Best Practices (coming soon)
- Building AI Agents with MCP (coming soon)
Extend AI capabilities with MCP! π