Chapter 8
12 min read
Section 46 of 175

What is MCP

Model Context Protocol (MCP)

Introduction

Every AI agent eventually needs to connect to external systemsβ€”databases, APIs, file systems, and third-party services. Until recently, each integration was custom-built, creating fragmented ecosystems where tools built for one AI system couldn't work with another. The Model Context Protocol (MCP) changes this.

The Vision: MCP is to AI agents what USB was to hardware peripheralsβ€”a universal standard that lets any tool work with any AI system.

Developed by Anthropic and released as an open standard, MCP provides a unified way for AI applications to connect with external data sources and tools. It's already supported by Claude Desktop, VS Code, and numerous other applications, with adoption accelerating across the AI industry.


The Integration Problem

Before MCP, connecting AI agents to external systems was a fragmented mess:

The NΓ—M Problem

πŸ“integration_nightmare.txt
1BEFORE MCP: The Integration Nightmare
2
3AI Applications:           External Systems:
4β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
5β”‚ Claude Desktop  │───┬───▢│ GitHub API      β”‚
6β”‚                 β”‚   β”‚    β”‚ (custom adapter)β”‚
7β”‚                 │───┼───▢│ Slack API       β”‚
8β”‚                 β”‚   β”‚    β”‚ (custom adapter)β”‚
9β”‚                 │───┼───▢│ PostgreSQL      β”‚
10β”‚                 β”‚   β”‚    β”‚ (custom adapter)β”‚
11β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
12                      β”‚
13β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
14β”‚ ChatGPT         │───┼───▢│ GitHub API      β”‚
15β”‚                 β”‚   β”‚    β”‚ (different code)β”‚
16β”‚                 │───┼───▢│ Slack API       β”‚
17β”‚                 β”‚   β”‚    β”‚ (different code)β”‚
18β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
19                      β”‚
20β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
21β”‚ Custom Agent    │───┴───▢│ Same APIs...    β”‚
22β”‚                 β”‚        β”‚ (yet another    β”‚
23β”‚                 β”‚        β”‚  implementation)β”‚
24β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
25
26N applications Γ— M data sources = NΓ—M custom integrations
2710 apps Γ— 20 sources = 200 separate integrations!

Problems with Custom Integrations

ProblemImpactExample
Duplicated effortSame integration built many timesEvery app builds its own GitHub connector
Inconsistent qualitySome integrations better than othersOAuth handling varies wildly
Maintenance burdenUpdates needed across many codebasesAPI change breaks N implementations
Security gapsEach implementation has own vulnerabilitiesToken handling differs per integration
No portabilityTools locked to one AI systemCan't reuse Claude tools with GPT
🐍before_mcp.py
1# Before MCP: Custom integration for each AI system
2
3# For Claude
4class ClaudeGitHubTool:
5    """GitHub tool specifically for Claude."""
6
7    def get_file(self, repo: str, path: str):
8        # Claude-specific implementation
9        token = self.get_claude_oauth_token()
10        response = requests.get(
11            f"https://api.github.com/repos/{repo}/contents/{path}",
12            headers={"Authorization": f"token {token}"}
13        )
14        # Format for Claude's expected response format
15        return self._format_for_claude(response.json())
16
17# For GPT - completely separate implementation
18class GPTGitHubTool:
19    """GitHub tool specifically for GPT."""
20
21    def read_file(self, repository: str, file_path: str):
22        # GPT-specific implementation
23        api_key = self.get_gpt_stored_key()
24        response = requests.get(
25            f"https://api.github.com/repos/{repository}/contents/{file_path}",
26            headers={"Authorization": f"token {api_key}"}
27        )
28        # Format for GPT's expected response format
29        return self._format_for_gpt(response.json())
30
31# Different method names, different auth, different formatting
32# Duplicated logic, duplicated bugs, duplicated maintenance

What is MCP

The Model Context Protocol (MCP) is an open protocol that standardizes how AI applications communicate with external data sources and tools. It transforms the NΓ—M problem into an N+M solution.

πŸ“with_mcp.txt
1WITH MCP: The Standardized Approach
2
3AI Applications:              MCP Servers:
4β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
5β”‚ Claude Desktop  │────┐     β”‚ GitHub Server   β”‚
6β”‚ (MCP Client)    β”‚    β”‚     β”‚ (one impl)      β”‚
7β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚     β””β”€β”€β”€β”€β”€β”€β”€β”€β–²β”€β”€β”€β”€β”€β”€β”€β”€β”˜
8                       β”‚              β”‚
9β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”
10β”‚ VS Code         │────┼────▢│ MCP Protocol    β”‚
11β”‚ (MCP Client)    β”‚    β”‚     β”‚ (standard)      β”‚
12β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚     β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
13                       β”‚              β”‚
14β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”
15β”‚ Custom Agent    β”‚β”€β”€β”€β”€β”˜     β”‚ Slack Server    β”‚
16β”‚ (MCP Client)    β”‚          β”‚ (one impl)      β”‚
17β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
18
19N applications + M servers = N+M implementations
2010 apps + 20 servers = 30 implementations (not 200!)

Core Components

MCP defines a client-server architecture:

ComponentRoleExamples
MCP HostThe AI application users interact withClaude Desktop, VS Code, custom apps
MCP ClientProtocol handler within the hostManages server connections
MCP ServerProvides tools/resources to clientsGitHub server, database server
TransportCommunication channelstdio, HTTP/SSE, WebSocket
πŸ“˜mcp_architecture.ts
1// MCP Architecture Overview
2
3// The MCP Host is your AI application
4interface MCPHost {
5  // Contains one or more MCP clients
6  clients: Map<string, MCPClient>;
7
8  // The LLM doing the reasoning
9  llm: LanguageModel;
10
11  // Route tool calls to appropriate servers
12  routeToolCall(name: string, args: object): Promise<Result>;
13}
14
15// MCP Client manages connection to one server
16interface MCPClient {
17  // Connect to an MCP server
18  connect(transport: Transport): Promise<void>;
19
20  // Discover what the server provides
21  listTools(): Promise<Tool[]>;
22  listResources(): Promise<Resource[]>;
23  listPrompts(): Promise<Prompt[]>;
24
25  // Execute operations
26  callTool(name: string, args: object): Promise<ToolResult>;
27  readResource(uri: string): Promise<ResourceContent>;
28  getPrompt(name: string, args?: object): Promise<PromptMessage[]>;
29}
30
31// MCP Server exposes capabilities
32interface MCPServer {
33  // Declare available capabilities
34  tools: Tool[];
35  resources: Resource[];
36  prompts: Prompt[];
37
38  // Handle requests from clients
39  handleToolCall(name: string, args: object): Promise<ToolResult>;
40  handleResourceRead(uri: string): Promise<ResourceContent>;
41  handlePromptGet(name: string, args?: object): Promise<PromptMessage[]>;
42}

The USB Analogy

MCP is often compared to USB, and the analogy is instructive:

Before USB (Before MCP)

πŸ“before_usb.txt
1HARDWARE BEFORE USB:
2
3Keyboard ──────▢ PS/2 Port (purple)
4Mouse ─────────▢ PS/2 Port (green)
5Printer ───────▢ Parallel Port (25-pin)
6Modem ─────────▢ Serial Port (9-pin)
7Scanner ───────▢ SCSI Port (50-pin)
8
9Every device type needed:
10- Different physical connector
11- Different electrical spec
12- Different driver architecture
13- Different communication protocol
14
15Adding new device = new port type needed on motherboard

After USB (After MCP)

πŸ“after_usb.txt
1HARDWARE WITH USB:
2
3Keyboard ──────▢ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
4Mouse ─────────▢ β”‚          β”‚
5Printer ───────▢ β”‚   USB    │──────▢ Computer
6Modem ─────────▢ β”‚ Standard β”‚
7Scanner ───────▢ β”‚          β”‚
8New Device ────▢ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
9
10One universal standard:
11- Same physical connector
12- Same electrical spec
13- Same driver model
14- Same communication protocol
15
16Adding new device = just implement USB protocol

MCP as AI's USB

πŸ“mcp_as_usb.txt
1AI INTEGRATIONS WITH MCP:
2
3GitHub ────────▢ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
4Slack ─────────▢ β”‚          β”‚
5Database ──────▢ β”‚   MCP    │──────▢ Any AI App
6Files ─────────▢ β”‚ Standard β”‚
7Web Search ────▢ β”‚          β”‚
8New Service ───▢ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
9
10One universal protocol:
11- Same message format
12- Same capability discovery
13- Same authentication flow
14- Same error handling
15
16Adding new integration = just implement MCP server

Why Standards Win

USB succeeded not because it was technically superior to every specialized connector, but because the benefits of standardization outweighed optimization for specific use cases. MCP follows the same principleβ€”universal compatibility beats custom optimization.

Key Concepts

MCP provides three main types of capabilities:

1. Tools

Tools are functions the LLM can call to perform actions:

{}tool_example.json
1{
2  "name": "create_github_issue",
3  "description": "Create a new issue in a GitHub repository",
4  "inputSchema": {
5    "type": "object",
6    "properties": {
7      "repo": {
8        "type": "string",
9        "description": "Repository in format owner/repo"
10      },
11      "title": {
12        "type": "string",
13        "description": "Issue title"
14      },
15      "body": {
16        "type": "string",
17        "description": "Issue body/description"
18      },
19      "labels": {
20        "type": "array",
21        "items": { "type": "string" },
22        "description": "Labels to apply"
23      }
24    },
25    "required": ["repo", "title"]
26  }
27}

2. Resources

Resources are data the LLM can read (like files or database records):

{}resource_example.json
1{
2  "uri": "file:///project/src/main.py",
3  "name": "Main Application",
4  "description": "Primary application entry point",
5  "mimeType": "text/x-python"
6}
7
8// Resources can also be dynamic
9{
10  "uri": "postgres://db/users?query=active",
11  "name": "Active Users",
12  "description": "Currently active user records"
13}

3. Prompts

Prompts are reusable templates for common interactions:

{}prompt_example.json
1{
2  "name": "code_review",
3  "description": "Template for reviewing code changes",
4  "arguments": [
5    {
6      "name": "diff",
7      "description": "The code diff to review",
8      "required": true
9    },
10    {
11      "name": "focus_areas",
12      "description": "Specific areas to focus on",
13      "required": false
14    }
15  ]
16}

Capability Discovery

πŸ“˜discovery.ts
1// MCP enables automatic capability discovery
2
3async function discoverServerCapabilities(client: MCPClient) {
4  // Connect to server
5  await client.connect();
6
7  // Discover what's available
8  const tools = await client.listTools();
9  const resources = await client.listResources();
10  const prompts = await client.listPrompts();
11
12  console.log("Available tools:", tools.map(t => t.name));
13  // ["create_issue", "list_repos", "get_file", "search_code"]
14
15  console.log("Available resources:", resources.map(r => r.uri));
16  // ["file:///repo/...", "github://issues/..."]
17
18  console.log("Available prompts:", prompts.map(p => p.name));
19  // ["code_review", "bug_report", "pr_summary"]
20}

MCP vs Alternatives

How does MCP compare to other approaches for AI tool integration?

MCP vs Direct Function Calling

AspectDirect Function CallingMCP
SetupDefine functions in codeConnect to MCP servers
PortabilityTied to one applicationWorks across any MCP client
DiscoveryHardcoded tool listDynamic capability discovery
UpdatesRedeploy applicationUpdate server independently
EcosystemBuild everything yourselfReuse community servers

MCP vs OpenAI Plugins (deprecated)

AspectOpenAI PluginsMCP
OwnershipControlled by OpenAIOpen protocol by Anthropic
SpecificationProprietaryOpen standard
TransportsHTTP onlystdio, HTTP/SSE, WebSocket
Local executionNoYes (stdio)
StatusDeprecatedActively developed

MCP vs Custom REST APIs

AspectCustom REST APIsMCP
Schema formatOpenAPI/SwaggerJSON Schema (simpler)
AI optimizationGeneric HTTPDesigned for LLM interaction
ResourcesGET endpointsFirst-class resource concept
PromptsNot supportedBuilt-in prompt templates
StreamingVariesNative support
MCP doesn't replace REST APIsβ€”MCP servers often wrap REST APIs to expose them to AI systems in a standardized way.

Summary

Key takeaways about MCP:

  1. Universal standard: MCP provides a single protocol for AI-to-tool communication
  2. Client-server architecture: AI apps (clients) connect to capability providers (servers)
  3. Three capability types: Tools (actions), Resources (data), Prompts (templates)
  4. Dynamic discovery: Clients can discover what servers provide at runtime
  5. Portable: Build once, use with any MCP-compatible AI application
  6. Open: Not locked to any single AI provider
Next: Let's dive deep into MCP's architectureβ€”the transport layers, message formats, and protocol flow that make it work.