🧭 Roadmap

concept_number: 20 title: Model Context Protocol (MCP) stage: Advanced difficulty: ⭐⭐⭐☆☆ time_to_learn: 3-4 hours status: not-started date_created: 2026-03-07 date_started: date_completed: progress: 0% prerequisites:

🗺️ Concept Mind Map

        MODEL CONTEXT PROTOCOL (MCP)
                    |
        +-----------+-----------+
        |           |           |
    COMPONENTS  BENEFITS    USE CASES
        |           |           |
        |           |           |
    MCP Client  Standardization Enterprise
    - Claude    - One protocol - Company data
    - ChatGPT   - Any tool     - Databases
    - Custom AI - No custom    - CRM systems
    - Your app    code         - File systems
        |           |           |
        |           |           |
    MCP Server  Interoperability Development
    - Salesforce- Works with   - IDE integration
    - Google      all AIs      - Code repos
      Drive     - Future-proof - Documentation
    - Slack     - Ecosystem    - APIs
    - Database      |           |
        |           |           |
    Protocol    Security      Personal
    - JSON-RPC  - Auth tokens  - Local files
    - WebSocket - Permissions  - Databases
    - HTTP      - Encryption   - Notes
    - Standard  - Audit logs   - Calendar
        |           |           |
        |           |           |
    Resources   Scalability   Automation
    - Files     - Handle 1000s - Workflows
    - Data        of tools     - Agents
    - APIs      - Efficient    - Pipelines
    - Tools     - Caching      - Integration

Architecture:

┌─────────────────────────────────────┐
│ AI APPLICATION (Client)             │
│ - Claude, ChatGPT, Custom AI        │
└─────────────┬───────────────────────┘
              │ MCP Protocol
              │ (Standardized)
┌─────────────┴───────────────────────┐
│ MCP SERVERS (Data Sources)          │
├─────────────────────────────────────┤
│ • Salesforce MCP Server             │
│ • Google Drive MCP Server           │
│ • Slack MCP Server                  │
│ • Database MCP Server               │
│ • File System MCP Server            │
│ • Custom API MCP Server             │
└─────────────────────────────────────┘

Before vs After MCP:

BEFORE MCP:
AI ─┬─ Custom Connector 1 ─→ Salesforce
    ├─ Custom Connector 2 ─→ Google Drive
    ├─ Custom Connector 3 ─→ Slack
    ├─ Custom Connector 4 ─→ Database
    └─ Custom Connector N ─→ Tool N
Problem: N tools = N custom integrations!

AFTER MCP:
AI ─→ MCP Protocol ─┬─→ Salesforce (MCP)
                    ├─→ Google Drive (MCP)
                    ├─→ Slack (MCP)
                    ├─→ Database (MCP)
                    └─→ Any Tool (MCP)
Solution: 1 protocol = ∞ tools!

MCP Message Flow:

1. USER: "What's our Q4 revenue?"
   ↓
2. AI: Needs Salesforce data
   ↓
3. MCP REQUEST:
   {
     "method": "query",
     "resource": "salesforce://revenue",
     "params": {"quarter": "Q4"}
   }
   ↓
4. MCP SERVER: Queries Salesforce
   ↓
5. MCP RESPONSE:
   {
     "data": {"revenue": "$2.5M"},
     "metadata": {"source": "Salesforce"}
   }
   ↓
6. AI: "Q4 revenue was $2.5M, up 15% from Q3"

Key Benefits:

  • Standardization: One protocol for all tools
  • Interoperability: Works with any AI
  • Security: Built-in auth and permissions
  • Scalability: Add tools without code changes
  • Future-proof: New tools work automatically

🌟 Start With a Real-World Scenario

You want ChatGPT to access your company data:

The Problem:

You: "What's our Q4 revenue?"
ChatGPT: "I don't have access to your company's financial data."

You: "Check our Salesforce database"
ChatGPT: "I can't access external databases."

You: "Read the latest sales report"
ChatGPT: "I can't access your files."

❌ ChatGPT is isolated! Can't access YOUR data!


The Old Solution (Messy):

Build custom integrations for EACH tool:
- Custom Salesforce connector
- Custom Google Drive connector
- Custom Slack connector
- Custom Database connector
- Custom API for everything!

Result: 100+ custom integrations, maintenance nightmare!

The New Solution: Model Context Protocol (MCP)

One standard protocol for ALL tools!

You: "What's our Q4 revenue?"

MCP:
1. Connects to Salesforce (via MCP)
2. Queries revenue data
3. Returns to ChatGPT
4. ChatGPT answers: "Q4 revenue was $2.5M, up 15% from Q3"

✅ Works with ANY tool that supports MCP!

The Power of MCP:

Before MCP:

ChatGPT → Custom Connector 1 → Salesforce
ChatGPT → Custom Connector 2 → Google Drive
ChatGPT → Custom Connector 3 → Slack
ChatGPT → Custom Connector 4 → Database
... (100+ custom connectors!)

With MCP:

ChatGPT → MCP Protocol → Any Tool!
- Salesforce (MCP server)
- Google Drive (MCP server)
- Slack (MCP server)
- Database (MCP server)
- ANY tool with MCP support!

One protocol, infinite tools! 🔌


Real Example:

MCP Server for Your Database:

# Your database becomes accessible to ANY AI!
mcp_server = MCPServer(
    name="company_db",
    tools=[
        "query_revenue",
        "get_customers",
        "sales_report"
    ]
)

# Now Claude, ChatGPT, or ANY AI can use it!

Using it:

You: "Show me top 10 customers by revenue"

Claude (via MCP):
1. Calls company_db.query_revenue()
2. Gets data
3. Formats response
4. Returns: "Top 10 customers:
   1. Acme Corp - $500K
   2. TechStart - $450K
   ..."

Real-World Applications:

1. Enterprise AI Assistant

MCP connects to:
- Salesforce (CRM data)
- Google Workspace (docs, emails)
- Slack (team communication)
- Jira (project management)
- Database (company data)

Result: AI that knows EVERYTHING about your company!

2. Personal AI Assistant

MCP connects to:
- Calendar (schedule)
- Email (communications)
- Notes (personal knowledge)
- Files (documents)
- Browser (web access)

Result: AI that manages your life!

3. Development Tools

MCP connects to:
- GitHub (code)
- Terminal (commands)
- Database (data)
- APIs (services)
- Documentation (knowledge)

Result: AI that codes with full context!

The MCP Ecosystem:

MCP Servers (Data Sources):

  • Filesystem (read/write files)
  • Database (SQL queries)
  • Web (HTTP requests)
  • Git (version control)
  • Custom (anything you build!)

MCP Clients (AI Models):

  • Claude (Anthropic)
  • ChatGPT (OpenAI)
  • Custom AI apps
  • Any LLM with MCP support

MCP Tools (Actions):

  • Read data
  • Write data
  • Execute commands
  • Call APIs
  • Anything programmable!

The Benefits:

For Developers:

  • Build once, works with all AIs
  • Standard protocol (no custom code)
  • Easy to maintain
  • Reusable components

For Users:

  • AI that accesses YOUR data
  • Seamless integrations
  • Privacy (data stays local)
  • Powerful capabilities

For Companies:

  • Reduce integration costs
  • Faster deployment
  • Better AI applications
  • Competitive advantage

By the end of this guide, you'll understand:

  • How MCP works (protocol details)
  • How to build MCP servers
  • How to connect AI to your tools
  • Security and privacy considerations
  • Real-world deployment
  • Future of AI integrations

The revolution: MCP is the "USB for AI" - one standard protocol to connect AI to everything! 🔌

Let's dive in! 🚀


🔌 Model Context Protocol (MCP)

Standardized protocol for connecting AI models to external data sources and tools

zations](#interactive-tools--visualizations)

What is MCP?

Model Context Protocol (MCP) is an open standard developed by Anthropic that enables AI models to securely connect to external data sources, tools, and services. Think of it as a universal adapter that lets AI assistants access your files, databases, APIs, and applications in a standardized way.

Key Idea

AI Model (Claude, GPT, etc.)
        ↕️ MCP Protocol
    MCP Server
        ↕️
External Resources (Files, DBs, APIs, Tools)

Real-World Analogy

Think of MCP like USB-C:

  • Before: Every device had different connectors (chaos!)
  • After: One standard connector works everywhere
  • MCP: One protocol connects AI to any data source
  • Result: Build once, use with any AI model

Why MCP Matters

1. Standardization 🔧

  • One protocol for all AI models
  • No vendor lock-in
  • Reusable integrations

2. Security 🔒

  • Controlled access to resources
  • Permission management
  • Audit trails

3. Flexibility 🎯

  • Connect to any data source
  • Add custom tools
  • Extend functionality

4. Composability 🧩

  • Mix and match servers
  • Build complex workflows
  • Modular architecture

5. Developer Experience 💻

  • Simple API
  • Clear documentation
  • Active ecosystem

Core Concepts

1. MCP Components

┌─────────────────┐
│   MCP Client    │  (AI Application)
│  (Claude, etc.) │
└────────┬────────┘
         │ MCP Protocol
┌────────┴────────┐
│   MCP Server    │  (Integration Layer)
└────────┬────────┘
         │
┌────────┴────────┐
│    Resources    │  (Files, DBs, APIs)
└─────────────────┘

2. Resources

Resources are data sources that AI can read:

# File resource
{
    "uri": "file:///path/to/document.txt",
    "name": "Project Documentation",
    "mimeType": "text/plain"
}

# Database resource
{
    "uri": "postgres://localhost/mydb/users",
    "name": "User Database",
    "mimeType": "application/sql"
}

# API resource
{
    "uri": "https://api.example.com/data",
    "name": "External API",
    "mimeType": "application/json"
}

3. Tools

Tools are functions that AI can execute:

# Calculator tool
{
    "name": "calculate",
    "description": "Perform mathematical calculations",
    "inputSchema": {
        "type": "object",
        "properties": {
            "expression": {"type": "string"}
        }
    }
}

# Search tool
{
    "name": "search",
    "description": "Search the web",
    "inputSchema": {
        "type": "object",
        "properties": {
            "query": {"type": "string"}
        }
    }
}

4. Prompts

Reusable prompt templates:

{
    "name": "code_review",
    "description": "Review code for best practices",
    "arguments": [
        {
            "name": "code",
            "description": "Code to review",
            "required": True
        }
    ]
}

How It Works

MCP Request-Response Flow

sequenceDiagram
    participant Client as AI Client
    participant Server as MCP Server
    participant Resource as Data Source
    
    Client->>Server: List Resources
    Server-->>Client: Available Resources
    
    Client->>Server: Read Resource
    Server->>Resource: Fetch Data
    Resource-->>Server: Data
    Server-->>Client: Resource Content
    
    Client->>Server: Call Tool
    Server->>Resource: Execute Action
    Resource-->>Server: Result
    Server-->>Client: Tool Response

Message Types

1. Initialize

{
    "jsonrpc": "2.0",
    "method": "initialize",
    "params": {
        "protocolVersion": "1.0",
        "capabilities": {
            "resources": {},
            "tools": {}
        }
    }
}

2. List Resources

{
    "jsonrpc": "2.0",
    "method": "resources/list"
}

3. Read Resource

{
    "jsonrpc": "2.0",
    "method": "resources/read",
    "params": {
        "uri": "file:///path/to/file.txt"
    }
}

4. Call Tool

{
    "jsonrpc": "2.0",
    "method": "tools/call",
    "params": {
        "name": "search",
        "arguments": {
            "query": "MCP protocol"
        }
    }
}

MCP Architecture

Server Types

1. Filesystem Server

# Provides access to local files
mcp_server = FilesystemServer(
    root_path="/path/to/documents",
    allowed_extensions=[".txt", ".md", ".pdf"]
)

2. Database Server

# Connects to databases
mcp_server = DatabaseServer(
    connection_string="postgresql://localhost/mydb",
    allowed_tables=["users", "products"]
)

3. API Server

# Wraps external APIs
mcp_server = APIServer(
    base_url="https://api.example.com",
    auth_token="your-token"
)

4. Custom Server

# Your own integration
class CustomMCPServer(MCPServer):
    def list_resources(self):
        # Return available resources
        pass
    
    def read_resource(self, uri):
        # Fetch resource content
        pass
    
    def list_tools(self):
        # Return available tools
        pass
    
    def call_tool(self, name, arguments):
        # Execute tool
        pass

Local Setup

Installation (15-20 minutes)

# Install MCP SDK
pip install mcp

# Install MCP servers (examples)
pip install mcp-server-filesystem
pip install mcp-server-postgres
pip install mcp-server-github

# Install Claude Desktop (for testing)
# Download from: https://claude.ai/download

Quick Start - Filesystem Server

from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp.types import Resource, Tool
import os

# Create MCP server
app = Server("filesystem-server")

@app.list_resources()
async def list_resources():
    """List available files"""
    files = []
    for root, dirs, filenames in os.walk("/path/to/docs"):
        for filename in filenames:
            if filename.endswith(('.txt', '.md')):
                path = os.path.join(root, filename)
                files.append(Resource(
                    uri=f"file://{path}",
                    name=filename,
                    mimeType="text/plain"
                ))
    return files

@app.read_resource()
async def read_resource(uri: str):
    """Read file content"""
    path = uri.replace("file://", "")
    with open(path, 'r') as f:
        content = f.read()
    return content

# Run server
if __name__ == "__main__":
    stdio_server(app)

Configuration

// claude_desktop_config.json
{
    "mcpServers": {
        "filesystem": {
            "command": "python",
            "args": ["/path/to/filesystem_server.py"],
            "env": {
                "ROOT_PATH": "/path/to/documents"
            }
        },
        "postgres": {
            "command": "mcp-server-postgres",
            "args": ["postgresql://localhost/mydb"]
        }
    }
}

Debug MCP connections

from mcp.inspector import Inspector

inspector = Inspector() inspector.connect("filesystem-server") inspector.list_resources() inspector.test_tool("search", {"query": "test"})


### 2. **MCP Playground**
```python
# Interactive testing environment
from mcp.playground import Playground

playground = Playground()
playground.add_server("filesystem", filesystem_server)
playground.add_server("database", database_server)
playground.start()  # Opens web interface

3. Resource Visualizer

import networkx as nx
import matplotlib.pyplot as plt

def visualize_mcp_architecture(servers):
    """Visualize MCP server connections"""
    G = nx.DiGraph()
    
    # Add nodes
    G.add_node("AI Client", node_type="client")
    for server in servers:
        G.add_node(server.name, node_type="server")
        G.add_edge("AI Client", server.name)
        
        for resource in server.list_resources():
            G.add_node(resource.uri, node_type="resource")
            G.add_edge(server.name, resource.uri)
    
    # Draw
    pos = nx.spring_layout(G)
    colors = ['red' if G.nodes[n].get('node_type') == 'client' else
              'blue' if G.nodes[n].get('node_type') == 'server' else
              'green' for n in G.nodes()]
    
    nx.draw(G, pos, node_color=colors, with_labels=True)
    plt.show()

Code Examples

Example 1: Basic MCP Server (Beginner)

from mcp.server import Server
from mcp.types import Resource, TextContent
import json

# Create server
app = Server("simple-server")

# In-memory data store
data_store = {
    "users": [
        {"id": 1, "name": "Alice"},
        {"id": 2, "name": "Bob"}
    ],
    "products": [
        {"id": 1, "name": "Widget", "price": 9.99}
    ]
}

@app.list_resources()
async def list_resources():
    """List available data collections"""
    return [
        Resource(
            uri="data://users",
            name="Users",
            mimeType="application/json",
            description="User database"
        ),
        Resource(
            uri="data://products",
            name="Products",
            mimeType="application/json",
            description="Product catalog"
        )
    ]

@app.read_resource()
async def read_resource(uri: str):
    """Read data from collection"""
    collection = uri.split("://")[1]
    data = data_store.get(collection, [])
    
    return TextContent(
        type="text",
        text=json.dumps(data, indent=2)
    )

@app.list_tools()
async def list_tools():
    """List available tools"""
    return [
        Tool(
            name="add_user",
            description="Add a new user",
            inputSchema={
                "type": "object",
                "properties": {
                    "name": {"type": "string"}
                },
                "required": ["name"]
            }
        )
    ]

@app.call_tool()
async def call_tool(name: str, arguments: dict):
    """Execute tool"""
    if name == "add_user":
        new_id = max([u["id"] for u in data_store["users"]]) + 1
        new_user = {"id": new_id, "name": arguments["name"]}
        data_store["users"].append(new_user)
        return f"Added user: {new_user}"
    
    return "Unknown tool"

# Run server
if __name__ == "__main__":
    from mcp.server.stdio import stdio_server
    stdio_server(app)

Example 2: GitHub Integration (Intermediate)

from mcp.server import Server
from mcp.types import Resource, Tool, TextContent
import requests
import os

class GitHubMCPServer:
    """MCP server for GitHub integration"""
    
    def __init__(self, token: str):
        self.token = token
        self.base_url = "https://api.github.com"
        self.headers = {
            "Authorization": f"token {token}",
            "Accept": "application/vnd.github.v3+json"
        }
    
    def create_server(self):
        app = Server("github-server")
        
        @app.list_resources()
        async def list_resources():
            """List user's repositories"""
            response = requests.get(
                f"{self.base_url}/user/repos",
                headers=self.headers
            )
            repos = response.json()
            
            return [
                Resource(
                    uri=f"github://repo/{repo['full_name']}",
                    name=repo['name'],
                    description=repo['description'] or "No description",
                    mimeType="application/json"
                )
                for repo in repos
            ]
        
        @app.read_resource()
        async def read_resource(uri: str):
            """Read repository information"""
            repo_name = uri.split("github://repo/")[1]
            response = requests.get(
                f"{self.base_url}/repos/{repo_name}",
                headers=self.headers
            )
            return TextContent(
                type="text",
                text=response.text
            )
        
        @app.list_tools()
        async def list_tools():
            return [
                Tool(
                    name="create_issue",
                    description="Create a GitHub issue",
                    inputSchema={
                        "type": "object",
                        "properties": {
                            "repo": {"type": "string"},
                            "title": {"type": "string"},
                            "body": {"type": "string"}
                        },
                        "required": ["repo", "title"]
                    }
                ),
                Tool(
                    name="search_code",
                    description="Search code in repositories",
                    inputSchema={
                        "type": "object",
                        "properties": {
                            "query": {"type": "string"}
                        },
                        "required": ["query"]
                    }
                )
            ]
        
        @app.call_tool()
        async def call_tool(name: str, arguments: dict):
            if name == "create_issue":
                response = requests.post(
                    f"{self.base_url}/repos/{arguments['repo']}/issues",
                    headers=self.headers,
                    json={
                        "title": arguments["title"],
                        "body": arguments.get("body", "")
                    }
                )
                return f"Created issue #{response.json()['number']}"
            
            elif name == "search_code":
                response = requests.get(
                    f"{self.base_url}/search/code",
                    headers=self.headers,
                    params={"q": arguments["query"]}
                )
                results = response.json()
                return f"Found {results['total_count']} results"
        
        return app

# Usage
github_server = GitHubMCPServer(token=os.getenv("GITHUB_TOKEN"))
app = github_server.create_server()

if __name__ == "__main__":
    from mcp.server.stdio import stdio_server
    stdio_server(app)

Example 3: Database MCP Server (Advanced)

from mcp.server import Server
from mcp.types import Resource, Tool, TextContent
import psycopg2
import json

class DatabaseMCPServer:
    """MCP server for PostgreSQL database"""
    
    def __init__(self, connection_string: str):
        self.conn_string = connection_string
        self.conn = psycopg2.connect(connection_string)
    
    def create_server(self):
        app = Server("database-server")
        
        @app.list_resources()
        async def list_resources():
            """List database tables"""
            cursor = self.conn.cursor()
            cursor.execute("""
                SELECT table_name 
                FROM information_schema.tables 
                WHERE table_schema = 'public'
            """)
            tables = cursor.fetchall()
            
            return [
                Resource(
                    uri=f"postgres://table/{table[0]}",
                    name=table[0],
                    mimeType="application/sql",
                    description=f"Database table: {table[0]}"
                )
                for table in tables
            ]
        
        @app.read_resource()
        async def read_resource(uri: str):
            """Read table data"""
            table_name = uri.split("postgres://table/")[1]
            cursor = self.conn.cursor()
            cursor.execute(f"SELECT * FROM {table_name} LIMIT 100")
            
            columns = [desc[0] for desc in cursor.description]
            rows = cursor.fetchall()
            
            data = [dict(zip(columns, row)) for row in rows]
            
            return TextContent(
                type="text",
                text=json.dumps(data, indent=2, default=str)
            )
        
        @app.list_tools()
        async def list_tools():
            return [
                Tool(
                    name="query",
                    description="Execute SQL query",
                    inputSchema={
                        "type": "object",
                        "properties": {
                            "sql": {"type": "string"}
                        },
                        "required": ["sql"]
                    }
                ),
                Tool(
                    name="insert",
                    description="Insert data into table",
                    inputSchema={
                        "type": "object",
                        "properties": {
                            "table": {"type": "string"},
                            "data": {"type": "object"}
                        },
                        "required": ["table", "data"]
                    }
                )
            ]
        
        @app.call_tool()
        async def call_tool(name: str, arguments: dict):
            cursor = self.conn.cursor()
            
            if name == "query":
                # Only allow SELECT queries for safety
                sql = arguments["sql"].strip()
                if not sql.upper().startswith("SELECT"):
                    return "Error: Only SELECT queries allowed"
                
                cursor.execute(sql)
                results = cursor.fetchall()
                return json.dumps(results, default=str)
            
            elif name == "insert":
                table = arguments["table"]
                data = arguments["data"]
                
                columns = ", ".join(data.keys())
                values = ", ".join(["%s"] * len(data))
                sql = f"INSERT INTO {table} ({columns}) VALUES ({values})"
                
                cursor.execute(sql, list(data.values()))
                self.conn.commit()
                return "Data inserted successfully"
        
        return app

# Usage
db_server = DatabaseMCPServer("postgresql://localhost/mydb")
app = db_server.create_server()

Example 4: Multi-Server Client (Production)

from mcp.client import Client
from mcp.client.stdio import stdio_client
import asyncio

class MCPOrchestrator:
    """Orchestrate multiple MCP servers"""
    
    def __init__(self):
        self.servers = {}
    
    async def add_server(self, name: str, command: str, args: list):
        """Add MCP server"""
        client = await stdio_client(command, args)
        await client.initialize()
        self.servers[name] = client
    
    async def list_all_resources(self):
        """List resources from all servers"""
        all_resources = {}
        for name, client in self.servers.items():
            resources = await client.list_resources()
            all_resources[name] = resources
        return all_resources
    
    async def search_resources(self, query: str):
        """Search across all resources"""
        results = []
        for name, client in self.servers.items():
            resources = await client.list_resources()
            for resource in resources:
                if query.lower() in resource.name.lower():
                    results.append({
                        "server": name,
                        "resource": resource
                    })
        return results
    
    async def execute_workflow(self, steps: list):
        """Execute multi-step workflow across servers"""
        results = []
        for step in steps:
            server = self.servers[step["server"]]
            
            if step["action"] == "read":
                result = await server.read_resource(step["uri"])
            elif step["action"] == "tool":
                result = await server.call_tool(
                    step["tool"],
                    step["arguments"]
                )
            
            results.append(result)
        
        return results

# Usage
async def main():
    orchestrator = MCPOrchestrator()
    
    # Add servers
    await orchestrator.add_server(
        "filesystem",
        "python",
        ["filesystem_server.py"]
    )
    await orchestrator.add_server(
        "github",
        "python",
        ["github_server.py"]
    )
    await orchestrator.add_server(
        "database",
        "python",
        ["database_server.py"]
    )
    
    # List all resources
    resources = await orchestrator.list_all_resources()
    print("Available resources:", resources)
    
    # Execute workflow
    workflow = [
        {
            "server": "database",
            "action": "read",
            "uri": "postgres://table/users"
        },
        {
            "server": "github",
            "action": "tool",
            "tool": "create_issue",
            "arguments": {
                "repo": "myorg/myrepo",
                "title": "User sync needed",
                "body": "Sync users from database"
            }
        }
    ]
    
    results = await orchestrator.execute_workflow(workflow)
    print("Workflow results:", results)

if __name__ == "__main__":
    asyncio.run(main())

Example 5: Custom Tool Server (Expert)

from mcp.server import Server
from mcp.types import Tool, TextContent
import subprocess
import json

class DevToolsMCPServer:
    """MCP server for development tools"""
    
    def create_server(self):
        app = Server("devtools-server")
        
        @app.list_tools()
        async def list_tools():
            return [
                Tool(
                    name="run_tests",
                    description="Run project tests",
                    inputSchema={
                        "type": "object",
                        "properties": {
                            "path": {"type": "string"},
                            "pattern": {"type": "string"}
                        }
                    }
                ),
                Tool(
                    name="lint_code",
                    description="Lint code files",
                    inputSchema={
                        "type": "object",
                        "properties": {
                            "files": {
                                "type": "array",
                                "items": {"type": "string"}
                            }
                        }
                    }
                ),
                Tool(
                    name="format_code",
                    description="Format code with black",
                    inputSchema={
                        "type": "object",
                        "properties": {
                            "path": {"type": "string"}
                        }
                    }
                ),
                Tool(
                    name="git_status",
                    description="Get git repository status",
                    inputSchema={
                        "type": "object",
                        "properties": {
                            "repo_path": {"type": "string"}
                        }
                    }
                )
            ]
        
        @app.call_tool()
        async def call_tool(name: str, arguments: dict):
            if name == "run_tests":
                result = subprocess.run(
                    ["pytest", arguments.get("path", "."),
                     "-k", arguments.get("pattern", "")],
                    capture_output=True,
                    text=True
                )
                return f"Tests: {result.stdout}\n{result.stderr}"
            
            elif name == "lint_code":
                files = arguments.get("files", [])
                result = subprocess.run(
                    ["pylint"] + files,
                    capture_output=True,
                    text=True
                )
                return f"Lint results:\n{result.stdout}"
            
            elif name == "format_code":
                result = subprocess.run(
                    ["black", arguments.get("path", ".")],
                    capture_output=True,
                    text=True
                )
                return f"Formatted: {result.stdout}"
            
            elif name == "git_status":
                result = subprocess.run(
                    ["git", "status", "--short"],
                    cwd=arguments.get("repo_path", "."),
                    capture_output=True,
                    text=True
                )
                return f"Git status:\n{result.stdout}"
        
        return app

# Usage
devtools_server = DevToolsMCPServer()
app = devtools_server.create_server()

TODO: Implement file server with search

class FileServerMCP: def list_resources(self): """List all files in directory""" pass

def read_resource(self, uri):
    """Read file content"""
    pass

def search_files(self, query):
    """Search files by content"""
    pass

### Exercise 2: API Wrapper
**Goal**: Wrap REST API as MCP server

```python
# TODO: Create MCP server for weather API
class WeatherMCPServer:
    def get_current_weather(self, location):
        """Get current weather"""
        pass
    
    def get_forecast(self, location, days):
        """Get weather forecast"""
        pass

Exercise 3: Multi-Server Integration

Goal: Combine multiple MCP servers

# TODO: Create orchestrator for multiple servers
class MCPHub:
    def add_server(self, name, server):
        """Add server to hub"""
        pass
    
    def route_request(self, request):
        """Route to appropriate server"""
        pass

Exercise 4: Custom Protocol Extension

Goal: Extend MCP with custom features

# TODO: Add streaming support to MCP
class StreamingMCPServer:
    def stream_resource(self, uri):
        """Stream large resource"""
        pass

Exercise 5: Security Layer

Goal: Add authentication and authorization

# TODO: Implement security for MCP server
class SecureMCPServer:
    def authenticate(self, credentials):
        """Verify user credentials"""
        pass
    
    def authorize(self, user, resource):
        """Check resource permissions"""
        pass

Assignments & Practice

Assignment 1: Personal Knowledge Base

Difficulty: ⭐⭐⭐☆☆

Build MCP server for personal notes:

  1. Index markdown files
  2. Full-text search
  3. Tag management
  4. Link extraction
  5. Claude Desktop integration

Deliverables:

  • MCP server code
  • Configuration file
  • Usage documentation
  • Demo video

Assignment 2: Development Assistant

Difficulty: ⭐⭐⭐⭐☆

Create MCP server for coding:

  1. Git integration
  2. Test runner
  3. Code formatter
  4. Documentation generator
  5. CI/CD integration

Deliverables:

  • Complete MCP server
  • Tool documentation
  • Integration guide
  • Example workflows

Assignment 3: Enterprise Integration

Difficulty: ⭐⭐⭐⭐⭐

Build production MCP system:

  1. Multiple data sources
  2. Authentication/authorization
  3. Audit logging
  4. Rate limiting
  5. Monitoring/metrics

Deliverables:

  • Production-ready code
  • Security documentation
  • Deployment guide
  • Performance benchmarks

Server not connecting

Error: Failed to connect to MCP server


**Solutions**:
```python
# 1. Check server is running
ps aux | grep mcp-server

# 2. Verify configuration
cat ~/.config/claude/claude_desktop_config.json

# 3. Check logs
tail -f ~/.config/claude/logs/mcp-server.log

# 4. Test server directly
python mcp_server.py --test

Issue 2: Resource Not Found

Symptoms:

# Resource URI not resolving
Error: Resource not found: file:///path/to/file

Solutions:

# 1. Validate URI format
def validate_uri(uri):
    if not uri.startswith(('file://', 'http://', 'data://')):
        raise ValueError(f"Invalid URI: {uri}")

# 2. Check permissions
import os
if not os.access(path, os.R_OK):
    raise PermissionError(f"Cannot read: {path}")

# 3. Normalize paths
from pathlib import Path
path = Path(uri.replace("file://", "")).resolve()

Issue 3: Tool Execution Errors

Symptoms:

# Tool fails silently
Tool executed but no result

Solutions:

# 1. Add error handling
@app.call_tool()
async def call_tool(name: str, arguments: dict):
    try:
        result = execute_tool(name, arguments)
        return result
    except Exception as e:
        return f"Error: {str(e)}"

# 2. Validate arguments
def validate_arguments(schema, arguments):
    # Check required fields
    for field in schema.get("required", []):
        if field not in arguments:
            raise ValueError(f"Missing required field: {field}")

# 3. Add logging
import logging
logging.info(f"Executing tool: {name} with {arguments}")

Hack 1: Resource caching

class CachedMCPServer: def init(self): self.cache = {}

async def read_resource(self, uri):
    if uri in self.cache:
        return self.cache[uri]
    
    content = await fetch_resource(uri)
    self.cache[uri] = content
    return content

Hack 2: Lazy loading

class LazyMCPServer: async def list_resources(self): # Return metadata only, load content on demand return [ Resource(uri=uri, name=name, lazy=True) for uri, name in self.get_resource_list() ]

Hack 3: Resource composition

async def compose_resources(uris): """Combine multiple resources""" contents = [] for uri in uris: content = await read_resource(uri) contents.append(content) return "\n\n".join(contents)

Hack 4: Tool chaining

async def chain_tools(tools): """Execute tools in sequence""" result = None for tool in tools: result = await call_tool( tool["name"], {**tool["args"], "input": result} ) return result

Hack 5: Dynamic server discovery

class ServerRegistry: def discover_servers(self): """Auto-discover MCP servers""" servers = [] for path in os.listdir("/usr/local/bin"): if path.startswith("mcp-server-"): servers.append(path) return servers


---

<!--REF_OPEN:Related Concepts-->

### Prerequisites
- Agents - MCP enables agent tool use
- [RAG](02-Intermediate--12-RAG.html) - MCP provides data access
- [LLMs](01-Foundations--06-Large-Language-Models.html) - MCP connects LLMs to data

### Related Topics
- [Vector Database](02-Intermediate--11-Vector-Database.html) - Store MCP resources
- Microservices - Similar architectural patterns
- GraphQL - Alternative data access pattern

---

<!--REF_CLOSE-->
<!--REF_OPEN:Resources-->

### 📚 Official Documentation

1. **MCP Specification**
   - https://spec.modelcontextprotocol.io/

2. **MCP SDK Documentation**
   - https://github.com/anthropics/mcp

3. **Claude Desktop Integration**
   - https://claude.ai/docs/mcp

### 🎥 Video Tutorials

1. **"Introducing Model Context Protocol"** - Anthropic
   - https://www.youtube.com/watch?v=MCP_intro

2. **"Building MCP Servers"** - Tutorial Series
   - https://www.youtube.com/playlist?list=MCP_tutorials

### 🛠️ Tools & Libraries

1. **MCP Python SDK**
   - https://github.com/anthropics/mcp-python

2. **MCP TypeScript SDK**
   - https://github.com/anthropics/mcp-typescript

3. **Community MCP Servers**
   - https://github.com/topics/mcp-server

### 📖 Tutorials & Guides

1. **Getting Started with MCP**
   - https://docs.anthropic.com/mcp/quickstart

2. **Building Custom MCP Servers**
   - https://docs.anthropic.com/mcp/custom-servers

3. **MCP Best Practices**
   - https://docs.anthropic.com/mcp/best-practices

---

5. **What is MCP? - Daily Dose of DS** #MyTopic
   - https://www.dailydoseofds.com/what-is-mcp/
   - Excellent beginner-friendly explanation
   - Real-world use cases and examples
   - Recommended by community


<!--REF_CLOSE-->
## Progress Tracking

- [ ] Understand MCP architecture
- [ ] Install MCP SDK
- [ ] Create basic MCP server
- [ ] Integrate with Claude Desktop
- [ ] Build custom tools
- [ ] Connect to external APIs
- [ ] Implement security
- [ ] Deploy production server

---

<div style="text-align:center; margin-top:30px; padding:20px; background:linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius:10px; color:white;">
<h2>🔌 Master Model Context Protocol!</h2>
<p>Connect AI to any data source with the universal protocol</p>
</div>