Model Context Protocol

Introduction

If you’ve built AI integrations before, you know the pain: connecting Claude to Slack requires custom code. Switch to GPT? Rebuild it. Add GitHub? Write another integration. Multiply this across every tool and every AI provider, and you’re drowning in glue code.

MCP (Model Context Protocol) fixes this. Released by Anthropic in November 2024 and now governed by the Linux Foundation with backing from OpenAI, Google, and Microsoft, MCP has become the industry standard for connecting AI to external systems. Think of it as USB-C for AI: one universal protocol that lets any compliant client talk to any compliant server.

TL;DR

MCP standardizes how AI models connect to tools and data. Instead of writing custom integrations for each AI provider, you build one MCP server and any MCP-compatible client (Claude, ChatGPT, Cursor, VS Code) can use it. The protocol uses JSON-RPC 2.0, supports three primitives (Tools, Resources, Prompts), and has SDKs for Python, TypeScript, and more. The ecosystem now includes 10,000+ public servers.

The Problem MCP Solves

Before MCP, connecting an AI assistant to external tools meant the classic M×N integration problem. Five AI providers times ten tools equals fifty custom integrations. Each one with its own authentication, error handling, and maintenance burden.

MCP inverts this equation. Each tool exposes a single MCP server. Each AI application implements a single MCP client. The protocol handles everything in between:

┌─────────────────────────────────────────────────────────┐
│                       MCP HOST                          │
│  (Claude Desktop, Cursor, VS Code, custom apps)         │
│                                                         │
│    ┌─────────────┐  ┌─────────────┐  ┌─────────────┐   │
│    │ MCP Client  │  │ MCP Client  │  │ MCP Client  │   │
│    └──────┬──────┘  └──────┬──────┘  └──────┬──────┘   │
└───────────┼────────────────┼────────────────┼──────────┘
            │                │                │
      JSON-RPC 2.0     JSON-RPC 2.0     JSON-RPC 2.0
            │                │                │
     ┌──────▼──────┐  ┌──────▼──────┐  ┌──────▼──────┐
     │ MCP Server  │  │ MCP Server  │  │ MCP Server  │
     │  (GitHub)   │  │  (Postgres) │  │   (Slack)   │
     └─────────────┘  └─────────────┘  └─────────────┘

Anthropic reported that early adopters saw 30% reduction in development overhead and 50-75% time savings on common integration tasks.

Core Architecture

MCP follows a client-server architecture built on JSON-RPC 2.0, inspired by the Language Server Protocol (LSP) that powers IDE features. Three key roles:

  • Host: The AI application (Claude Desktop, Cursor, your custom agent) that runs the model and manages connections
  • Client: A component within the host that maintains a 1:1 connection with a server
  • Server: A program exposing tools, data, or prompts to clients

Servers expose three primitives:

PrimitiveControlPurposeExample
ToolsModel-controlledExecutable functions the LLM can invokeDatabase queries, API calls
ResourcesApplication-controlledRead-only data exposed to the modelFile contents, schemas
PromptsUser-controlledReusable templates for workflowsCode review checklists

Two transport mechanisms handle communication:

  • stdio: Server runs as a local subprocess via stdin/stdout. Fast, no network overhead. Ideal for Claude Desktop integrations.
  • Streamable HTTP: HTTP POST with Server-Sent Events for remote deployments. Supports multiple concurrent clients.

Building an MCP Server in Python

The Python SDK provides FastMCP, a high-level API that handles protocol details:

pip install "mcp[cli]"
# server.py
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("MyServer")

@mcp.tool()
def query_database(query: str, limit: int = 100) -> str:
    """Execute a read-only SQL query against the database."""
    # In production, execute against actual database
    return f"Results for: {query} (limit {limit})"

@mcp.resource("config://{key}")
def get_config(key: str) -> str:
    """Read configuration values."""
    configs = {"api_url": "https://api.example.com", "timeout": "30"}
    return configs.get(key, "not found")

@mcp.prompt()
def review_code(language: str = "python") -> str:
    """Generate a code review prompt."""
    return f"Review this {language} code for bugs, security issues, and style."

if __name__ == "__main__":
    mcp.run()  # stdio transport by default

For production HTTP deployments:

if __name__ == "__main__":
    mcp.run(transport="streamable-http", port=8000)

Test with the MCP Inspector: mcp dev server.py

Critical: For stdio servers, never print to stdout. It corrupts the JSON-RPC stream. Use stderr or a logging library configured to avoid stdout.

Building an MCP Server in TypeScript

npm install @modelcontextprotocol/sdk zod
// src/index.ts
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { z } from 'zod';

const server = new McpServer({
    name: 'my-server',
    version: '1.0.0'
});

server.registerTool(
    'query_database',
    {
        description: 'Execute a read-only SQL query',
        inputSchema: {
            query: z.string().describe('SQL SELECT statement'),
            limit: z.number().default(100)
        }
    },
    async ({ query, limit }) => ({
        content: [{ type: 'text', text: `Results for: ${query}` }]
    })
);

const transport = new StdioServerTransport();
await server.connect(transport);

Configuring Claude Desktop

Add servers to your config file. On macOS: ~/Library/Application Support/Claude/claude_desktop_config.json. On Windows: %APPDATA%\Claude\claude_desktop_config.json.

{
  "mcpServers": {
    "my-python-server": {
      "command": "python",
      "args": ["/path/to/server.py"],
      "env": { "DATABASE_URL": "postgres://..." }
    },
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/me/projects"]
    }
  }
}

Claude Desktop launches these servers on startup and makes their tools available in your conversations.

The Ecosystem

MCP adoption has exploded. Major platforms now support it:

ClientMCP Support
Claude DesktopFull native support
ChatGPTDeveloper Mode (September 2025)
CursorNative integration, one-click installs
VS CodeGitHub Copilot MCP extension
GeminiConfirmed by Google DeepMind
Windows 11Native Microsoft Copilot integration

Pre-built servers cover common integrations:

  • Official reference servers: Filesystem, Git, Memory, Fetch, Time
  • Company-maintained: GitHub, Microsoft Azure, AWS, Cloudflare, Stripe, Atlassian, MongoDB, Docker
  • Community registries: MCP.so (17,000+ servers), Smithery.ai, PulseMCP

Block (Square/Cash App) deployed MCP company-wide with 60+ custom servers for code migration, database access, and ticket triage. Thousands of their engineers use it daily.

When to Choose MCP vs Alternatives

Use MCP when:

  • Building production systems with 5+ tool integrations
  • Tools need to work across multiple AI providers
  • Security isolation between tools is critical
  • You want reusable integrations shared across teams

Use function calling when:

  • Prototyping with 1-3 custom tools
  • Working within a single LLM provider’s ecosystem
  • Quick iteration matters more than long-term maintainability

Use direct API integration when:

  • Ultra-low latency requirements (MCP adds protocol overhead)
  • Non-LLM applications
  • Legacy systems where MCP servers would require significant adaptation

The approaches complement each other: function calling translates prompts into instructions; MCP standardizes execution.

Production Best Practices

Single responsibility: Each MCP server should do one thing well. Avoid monolithic servers combining unrelated tools.

Error handling: Return errors in the response with isError: true. Implement retry with exponential backoff:

import asyncio
import random

async def retry_with_backoff(operation, max_attempts=3):
    for attempt in range(max_attempts):
        try:
            return await operation()
        except Exception as e:
            if attempt == max_attempts - 1:
                raise
            delay = 2 ** attempt + random.uniform(0, 1)
            await asyncio.sleep(delay)

Security: Remote servers must use OAuth 2.1 with recognized certificates. Provide tool annotations (readOnlyHint, destructiveHint) so hosts can implement consent flows. Never collect extraneous conversation data.

Observability: Use structured logging with correlation IDs. Track throughput, latency percentiles (p50/p95/p99), and error rates.

Current Limitations

Context window pressure: Loading all tool definitions upfront consumes tokens. With hundreds of tools, performance degrades. Use progressive tool disclosure.

OAuth 2.1 adoption lag: The spec defines OAuth 2.1 for authentication, but many clients haven’t fully implemented it yet.

Enterprise compliance gaps: Native audit trails, RBAC, and data residency controls are limited. Organizations requiring GDPR/SOX compliance need additional layers.

Stateful scaling: The protocol assumes stateful sessions by default. Use Streamable HTTP transport with external session stores for horizontal scaling.

Conclusion

MCP represents a genuine inflection point in AI infrastructure. By standardizing how models connect to external systems, it eliminates the integration fragmentation that previously made production AI deployments expensive and fragile. The protocol’s rapid adoption, from Anthropic to OpenAI to Microsoft in under a year, signals that the industry has converged on a shared solution.

For technical leaders evaluating MCP: start with pre-built servers for common integrations (GitHub, databases, file systems) to understand the developer experience. Build custom servers for proprietary systems using the Python or TypeScript SDKs. Expect to layer additional security and observability tooling for enterprise deployments.

The “USB-C for AI” analogy captures MCP’s ambition accurately. Just as USB-C unified physical connectivity after years of proprietary cables, MCP is unifying AI’s connection layer. It doesn’t make models smarter, but it removes a significant infrastructure burden, letting teams focus on what AI tools do rather than how they connect.

Next steps: explore the official MCP documentation at modelcontextprotocol.io, browse pre-built servers at MCP.so, and try connecting Claude Desktop to a filesystem or GitHub server to see the experience firsthand.