Model Context Protocol (MCP) represents a new standard for connecting AI agents with external systems and data. This protocol enables secure and efficient communication between language models and various information sources, from databases to cloud services.
What is Model Context Protocol (MCP)¶
Model Context Protocol (MCP) is a new standardized protocol developed by Anthropic that enables large language models (LLM) to safely and efficiently interact with external systems and tools. The protocol solves a long-term problem in the AI agents field – how to provide models access to real-time data and functionalities without compromising security or system control.
MCP functions as a bridge between AI models and external data sources, databases, APIs, or local tools. Unlike traditional approaches where each tool requires its own integration, MCP provides a unified interface for all types of resources and tools.
MCP Architecture and Components¶
MCP builds on client-server architecture with clearly defined roles:
- MCP Client – usually an AI application or agent that needs access to external resources
- MCP Server – provides specific functionalities or data access
- Transport Layer – handles communication between client and server (JSON-RPC, WebSockets)
Each MCP server can expose three main types of capabilities:
- Resources – static or semi-static data (files, documents, configuration data)
- Tools – executable functions that the model can call
- Prompts – pre-prepared prompt templates for specific tasks
Implementing MCP Server in Python¶
Creating your own MCP server is surprisingly simple. Anthropic provides an official SDK that significantly simplifies the process:
from mcp import McpServer, Tool
from mcp.types import TextContent
import asyncio
import json
app = McpServer("file-manager")
@app.tool("read_file")
async def read_file(path: str) -> TextContent:
"""Reads file content from specified path"""
try:
with open(path, 'r', encoding='utf-8') as file:
content = file.read()
return TextContent(
type="text",
text=f"File content {path}:\n{content}"
)
except Exception as e:
return TextContent(
type="text",
text=f"Error reading file: {str(e)}"
)
@app.tool("list_directory")
async def list_directory(path: str = ".") -> TextContent:
"""List files in directory"""
import os
try:
files = os.listdir(path)
file_list = "\n".join(files)
return TextContent(
type="text",
text=f"Files in {path}:\n{file_list}"
)
except Exception as e:
return TextContent(
type="text",
text=f"Error listing: {str(e)}"
)
if __name__ == "__main__":
asyncio.run(app.run())
Server Configuration and Registration¶
MCP servers are configured through a JSON configuration file. For Claude Desktop, the configuration is stored in:
{
"mcpServers": {
"file-manager": {
"command": "python",
"args": ["path/to/file_server.py"],
"env": {
"PYTHONPATH": "/path/to/mcp/sdk"
}
},
"database-connector": {
"command": "node",
"args": ["db-server.js"],
"env": {
"DB_CONNECTION": "postgresql://user:pass@localhost:5432/mydb"
}
}
}
}
This configuration allows Claude to automatically start and connect MCP servers on application startup.
Resources vs Tools: Practical Usage¶
The distinction between Resources and Tools is key to proper MCP server design:
Resources – for reading data¶
@app.resource("config://database")
async def get_database_config() -> dict:
"""Returns database configuration"""
return {
"host": "localhost",
"port": 5432,
"database": "production",
"tables": ["users", "orders", "products"]
}
@app.resource("logs://application/{date}")
async def get_application_logs(date: str) -> TextContent:
"""Loads application logs for specific date"""
log_path = f"/var/log/app/{date}.log"
# log reading implementation
return TextContent(type="text", text=log_content)
Tools – for actions and changes¶
@app.tool("deploy_application")
async def deploy_application(
environment: str,
version: str
) -> TextContent:
"""Deploys application to specified environment"""
if environment not in ["staging", "production"]:
return TextContent(
type="text",
text="Error: Unsupported environment"
)
# Deployment logic
result = await deploy_to_environment(environment, version)
return TextContent(
type="text",
text=f"Application version {version} successfully deployed to {environment}"
)
Security Aspects¶
MCP places great emphasis on security. Each server runs in an isolated process and communication occurs through a standardized interface. Important security principles include:
- Principle of Least Privilege – each server has access only to necessary resources
- Input validation – all parameters must be validated before processing
- Rate limiting – limiting the number of requests per time unit
- Auditing – logging all operations for debugging and security monitoring
@app.tool("execute_sql")
async def execute_sql(query: str) -> TextContent:
"""Safe execution of SQL query"""
# Whitelist of allowed operations
allowed_operations = ["SELECT", "SHOW", "DESCRIBE"]
query_upper = query.strip().upper()
if not any(query_upper.startswith(op) for op in allowed_operations):
return TextContent(
type="text",
text="Error: Only SELECT queries are allowed"
)
# Additional validation and sanitization
# ...
result = await execute_readonly_query(query)
return TextContent(type="text", text=str(result))
Integration with Existing Systems¶
MCP can be easily integrated with existing infrastructure. Example integration with Redis cache and PostgreSQL database:
import redis
import asyncpg
from mcp import McpServer
app = McpServer("data-services")
# Connection to external services
redis_client = redis.Redis(host='localhost', port=6379, db=0)
pg_pool = None
async def init_db():
global pg_pool
pg_pool = await asyncpg.create_pool(
"postgresql://user:password@localhost/mydb"
)
@app.tool("cache_get")
async def cache_get(key: str) -> TextContent:
"""Retrieves value from Redis cache"""
try:
value = redis_client.get(key)
if value is None:
return TextContent(type="text", text=f"Key '{key}' not found")
return TextContent(
type="text",
text=f"Value for '{key}': {value.decode('utf-8')}"
)
except Exception as e:
return TextContent(type="text", text=f"Redis error: {str(e)}")
@app.tool("db_query")
async def db_query(sql: str) -> TextContent:
"""Executes SELECT query on PostgreSQL"""
async with pg_pool.acquire() as connection:
try:
rows = await connection.fetch(sql)
result = [dict(row) for row in rows]
return TextContent(
type="text",
text=json.dumps(result, indent=2, ensure_ascii=False)
)
except Exception as e:
return TextContent(type="text", text=f"DB error: {str(e)}")
Summary¶
Model Context Protocol represents a significant step forward in the field of AI agents and tool use. It provides a standardized, secure, and scalable way to connect LLM models with external systems. For developers, MCP means the ability to quickly create powerful AI applications without having to solve complex integration problems. The protocol is still in active development, but already shows enormous potential for automation and efficiency improvements in enterprise environments. We expect MCP to become the standard for AI tool integration in the coming months.