Model Context Protocol (MCP)¶
MCP is an open standard for connecting AI assistants to external data sources and tools.
What is MCP?¶
MCP provides a standardized way for LLMs to:
- Access data from files, databases, APIs
- Use tools to perform actions
- Maintain context across interactions
┌─────────────────────────────────────────────────────────────┐
│ MCP Architecture │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ AI Host │ │ MCP Server │ │
│ │ (Claude, etc)│◄──── Protocol ────►│ (Your App) │ │
│ └──────────────┘ └──────────────┘ │
│ │ │ │
│ v v │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ Tools │ │ Resources │ │
│ │ - search │ │ - files │ │
│ │ - execute │ │ - database │ │
│ │ - query │ │ - API data │ │
│ └──────────────┘ └──────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
In This Section¶
| Document | Description |
|---|---|
| Servers | Building MCP servers |
| Clients | Connecting to MCP servers |
| Examples | Practical MCP implementations |
Quick Start¶
Install MCP SDK¶
Simple MCP Server (Python)¶
#!/usr/bin/env python3
from mcp.server import Server
from mcp.types import Tool, TextContent
import asyncio
server = Server("example-server")
@server.list_tools()
async def list_tools():
return [
Tool(
name="greet",
description="Generate a greeting",
inputSchema={
"type": "object",
"properties": {
"name": {"type": "string", "description": "Name to greet"}
},
"required": ["name"]
}
)
]
@server.call_tool()
async def call_tool(name: str, arguments: dict):
if name == "greet":
return [TextContent(
type="text",
text=f"Hello, {arguments['name']}!"
)]
async def main():
from mcp.server.stdio import stdio_server
async with stdio_server() as (read, write):
await server.run(read, write)
if __name__ == "__main__":
asyncio.run(main())
Use with Claude Desktop¶
Add to ~/Library/Application Support/Claude/claude_desktop_config.json:
MCP Features¶
Tools¶
Functions the AI can call:
@server.list_tools()
async def list_tools():
return [
Tool(
name="search",
description="Search for information",
inputSchema={
"type": "object",
"properties": {
"query": {"type": "string"}
},
"required": ["query"]
}
)
]
@server.call_tool()
async def call_tool(name: str, arguments: dict):
if name == "search":
results = perform_search(arguments["query"])
return [TextContent(type="text", text=results)]
Resources¶
Data the AI can read:
@server.list_resources()
async def list_resources():
return [
Resource(
uri="file:///data/config.json",
name="Configuration",
mimeType="application/json"
)
]
@server.read_resource()
async def read_resource(uri: str):
if uri == "file:///data/config.json":
with open("/data/config.json") as f:
return f.read()
Prompts¶
Reusable prompt templates:
@server.list_prompts()
async def list_prompts():
return [
Prompt(
name="analyze",
description="Analyze data",
arguments=[
PromptArgument(name="data", description="Data to analyze")
]
)
]
@server.get_prompt()
async def get_prompt(name: str, arguments: dict):
if name == "analyze":
return GetPromptResult(
messages=[
PromptMessage(
role="user",
content=TextContent(
type="text",
text=f"Analyze this data: {arguments['data']}"
)
)
]
)
Available MCP Servers¶
Official Servers¶
| Server | Description |
|---|---|
| filesystem | Read/write local files |
| git | Git repository operations |
| github | GitHub API access |
| postgres | PostgreSQL database |
| sqlite | SQLite database |
| slack | Slack workspace |
| google-drive | Google Drive access |
Community Servers¶
| Server | Description |
|---|---|
| browserbase | Web browser automation |
| puppeteer | Headless browser control |
| docker | Container management |
| kubernetes | K8s cluster operations |
Install Official Servers¶
# Using uvx (recommended)
uvx mcp-server-filesystem
# Using npx
npx -y @modelcontextprotocol/server-github
Configuration¶
Claude Desktop¶
{
"mcpServers": {
"filesystem": {
"command": "uvx",
"args": ["mcp-server-filesystem", "/path/to/allowed/directory"]
},
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_TOKEN": "ghp_xxxx"
}
}
}
}
Claude Code¶
// ~/.claude/settings.json
{
"mcpServers": {
"myserver": {
"command": "python",
"args": ["/path/to/server.py"]
}
}
}
Transport Options¶
Stdio (Default)¶
Server communicates via stdin/stdout:
async def main():
from mcp.server.stdio import stdio_server
async with stdio_server() as (read, write):
await server.run(read, write)
HTTP/SSE¶
Server over HTTP with Server-Sent Events:
from mcp.server.sse import SseServerTransport
from starlette.applications import Starlette
from starlette.routing import Route
sse = SseServerTransport("/messages")
async def handle_sse(request):
async with sse.connect_sse(
request.scope, request.receive, request._send
) as streams:
await server.run(streams[0], streams[1])
app = Starlette(routes=[
Route("/sse", endpoint=handle_sse),
sse.handle_post_message,
])
Best Practices¶
Tool Design¶
- Clear descriptions - Help the AI understand when to use tools
- Validate inputs - Check arguments before processing
- Handle errors gracefully - Return informative error messages
- Limit scope - Each tool should do one thing well
Security¶
- Validate all inputs - Never trust AI-provided arguments
- Limit file access - Restrict to specific directories
- Use environment variables - Don't hardcode credentials
- Log operations - Track what the AI does
Performance¶
- Async operations - Use async/await for I/O
- Cache when possible - Avoid repeated expensive operations
- Timeout long operations - Don't let calls hang indefinitely