spinny:~/writing $ less mcp-model-context-protocol-guide.md
12The **Model Context Protocol (MCP)** is an open standard created by Anthropic that defines how AI models communicate with external tools, data sources, and services. Think of it as the "USB-C of AI" - a universal connector that lets any AI agent talk to any tool through a standardized interface.34Since its launch, MCP has crossed **97 million monthly SDK downloads** and has been adopted by every major AI provider: Anthropic, OpenAI, Google, Microsoft, and Amazon. In this guide, we'll explore everything you need to know to build with MCP.56## Why MCP Exists78Before MCP, every AI application had to build custom integrations for each tool it wanted to use. Want your AI to read files? Write custom code. Query a database? More custom code. Post to Slack? Yet another integration.910This created an **N×M problem**: N AI applications each needed M custom integrations, leading to duplicated effort and fragmented ecosystems.1112```mermaid13graph TD14 subgraph "Before MCP (N×M)"15 A1[AI App 1] --> T1[GitHub Integration]16 A1 --> T2[Slack Integration]17 A1 --> T3[DB Integration]18 A2[AI App 2] --> T4[GitHub Integration]19 A2 --> T5[Slack Integration]20 A2 --> T6[DB Integration]21 end22```2324MCP solves this with a **single protocol** that any AI client can use to communicate with any MCP server:2526```mermaid27graph TD28 subgraph "With MCP (N+M)"29 A1[AI App 1] --> MCP[MCP Protocol]30 A2[AI App 2] --> MCP31 MCP --> S1[GitHub Server]32 MCP --> S2[Slack Server]33 MCP --> S3[DB Server]34 end35```3637## Core Concepts3839MCP has three fundamental primitives:4041### 1. Tools42Tools are functions that the AI can call. They represent actions like "create a file", "query a database", or "send a message". Each tool has a name, description, and a JSON Schema for its parameters.4344```typescript45{46 name: "create_issue",47 description: "Create a new GitHub issue",48 inputSchema: {49 type: "object",50 properties: {51 title: { type: "string", description: "Issue title" },52 body: { type: "string", description: "Issue body" },53 repo: { type: "string", description: "Repository name" }54 },55 required: ["title", "repo"]56 }57}58```5960### 2. Resources61Resources are data that the AI can read. They represent files, database records, API responses, or any other data source. Resources are identified by URIs.6263```typescript64{65 uri: "file:///Users/dev/project/README.md",66 name: "Project README",67 mimeType: "text/markdown"68}69```7071### 3. Prompts72Prompts are reusable templates that help structure interactions. They can include dynamic parameters and are useful for standardizing common workflows.7374```typescript75{76 name: "code_review",77 description: "Review code changes for quality and security",78 arguments: [79 { name: "diff", description: "The code diff to review", required: true }80 ]81}82```8384## Architecture8586MCP follows a client-server architecture:8788```mermaid89graph LR90 subgraph "Host Application"91 Client[MCP Client]92 end9394 subgraph "MCP Server"95 Server[Server Process]96 Server --> Tools[Tools]97 Server --> Resources[Resources]98 Server --> Prompts[Prompts]99 end100101 Client -- "JSON-RPC 2.0\n(stdio or SSE)" --> Server102```103104- **Host**: The AI application (Claude Desktop, Cursor, your custom app)105- **Client**: Maintains a 1:1 connection with an MCP server106- **Server**: Exposes tools, resources, and prompts to the client107- **Transport**: Communication happens via JSON-RPC 2.0 over stdio (local) or Server-Sent Events (remote)108109## Building an MCP Server110111Let's build a practical MCP server that interacts with a todo list stored in a JSON file.112113### Setup114115```bash116mkdir mcp-todo-server && cd mcp-todo-server117npm init -y118npm install @modelcontextprotocol/sdk zod119```120121### Server Implementation122123```typescript124// src/index.ts125import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";126import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";127import { z } from "zod";128import fs from "fs";129130const TODO_FILE = "./todos.json";131132function readTodos(): { id: number; text: string; done: boolean }[] {133 if (!fs.existsSync(TODO_FILE)) return [];134 return JSON.parse(fs.readFileSync(TODO_FILE, "utf-8"));135}136137function writeTodos(todos: { id: number; text: string; done: boolean }[]) {138 fs.writeFileSync(TODO_FILE, JSON.stringify(todos, null, 2));139}140141const server = new McpServer({142 name: "todo-server",143 version: "1.0.0",144});145146// Tool: Add a todo147server.tool(148 "add_todo",149 "Add a new todo item",150 { text: z.string().describe("The todo text") },151 async ({ text }) => {152 const todos = readTodos();153 const newTodo = { id: Date.now(), text, done: false };154 todos.push(newTodo);155 writeTodos(todos);156 return { content: [{ type: "text", text: `Added: "${text}"` }] };157 }158);159160// Tool: List todos161server.tool(162 "list_todos",163 "List all todo items",164 {},165 async () => {166 const todos = readTodos();167 const list = todos168 .map((t) => `${t.done ? "✅" : "⬜"} [${t.id}] ${t.text}`)169 .join("\n");170 return { content: [{ type: "text", text: list || "No todos yet." }] };171 }172);173174// Tool: Complete a todo175server.tool(176 "complete_todo",177 "Mark a todo as completed",178 { id: z.number().describe("The todo ID to complete") },179 async ({ id }) => {180 const todos = readTodos();181 const todo = todos.find((t) => t.id === id);182 if (!todo) return { content: [{ type: "text", text: "Todo not found." }] };183 todo.done = true;184 writeTodos(todos);185 return { content: [{ type: "text", text: `Completed: "${todo.text}"` }] };186 }187);188189// Resource: Current todos as a readable resource190server.resource(191 "todos://list",192 "Current todo list",193 async () => ({194 contents: [{195 uri: "todos://list",196 mimeType: "application/json",197 text: JSON.stringify(readTodos(), null, 2),198 }],199 })200);201202// Start the server203const transport = new StdioServerTransport();204await server.connect(transport);205```206207### Configuration208209To use this server with Claude Desktop, add it to your config:210211```json212{213 "mcpServers": {214 "todo": {215 "command": "npx",216 "args": ["tsx", "/path/to/mcp-todo-server/src/index.ts"]217 }218 }219}220```221222## Building an MCP Client223224You can also build a custom client that connects to any MCP server:225226```typescript227import { Client } from "@modelcontextprotocol/sdk/client/index.js";228import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";229230const transport = new StdioClientTransport({231 command: "npx",232 args: ["tsx", "./src/index.ts"],233});234235const client = new Client({ name: "my-client", version: "1.0.0" });236await client.connect(transport);237238// List available tools239const { tools } = await client.listTools();240console.log("Available tools:", tools.map((t) => t.name));241242// Call a tool243const result = await client.callTool({244 name: "add_todo",245 arguments: { text: "Write MCP blog post" },246});247console.log(result);248```249250## Popular MCP Servers251252The MCP ecosystem has grown rapidly. Here are some of the most popular servers:253254| Server | Description | Use Case |255|--------|-------------|----------|256| **GitHub** | Create issues, PRs, manage repos | Development workflows |257| **Slack** | Send messages, manage channels | Team communication |258| **PostgreSQL** | Query and manage databases | Data access |259| **Filesystem** | Read, write, and search files | Local development |260| **Puppeteer** | Browser automation and scraping | Web testing |261| **Sentry** | Error monitoring and debugging | Production support |262| **Supabase** | Database, auth, storage | Backend operations |263264## MCP vs A2A (Agent-to-Agent)265266While MCP handles **agent-to-tool** communication, Google's **A2A (Agent-to-Agent)** protocol handles **agent-to-agent** communication. They are complementary:267268```mermaid269graph TD270 Agent1[Agent 1] -- "A2A Protocol" --> Agent2[Agent 2]271 Agent1 -- "MCP Protocol" --> Tool1[GitHub MCP Server]272 Agent2 -- "MCP Protocol" --> Tool2[Database MCP Server]273```274275- **MCP**: How an AI agent uses tools (vertical integration)276- **A2A**: How AI agents collaborate with each other (horizontal integration)277278## Best Practices2792801. **Keep servers focused**: One server per domain (GitHub server, Slack server, etc.). Don't build monolithic servers.2812. **Validate inputs with Zod**: Always validate tool inputs with proper schemas.2823. **Handle errors gracefully**: Return meaningful error messages, not stack traces.2834. **Use resources for read-only data**: If the AI only needs to read data, expose it as a resource rather than a tool.2845. **Add proper descriptions**: Good tool and parameter descriptions help the AI understand when and how to use each tool.2856. **Test with the MCP Inspector**: Use `npx @modelcontextprotocol/inspector` to test your server interactively.286287## Getting Started288289```bash290# Create a new MCP server from template291npx @modelcontextprotocol/create-server my-server292293# Test with the MCP Inspector294npx @modelcontextprotocol/inspector npx tsx ./src/index.ts295```296297## Conclusion298299MCP has become the de facto standard for AI tool use in 2026. Whether you're building custom AI agents, extending Claude Code, or creating integrations for existing platforms, understanding MCP is essential. The protocol is simple enough to learn in an afternoon but powerful enough to build production-grade AI workflows.300301**Next steps:**302- Explore the [MCP Specification](https://spec.modelcontextprotocol.io/)303- Browse [existing MCP servers](https://github.com/modelcontextprotocol/servers) for inspiration304- Build your first server with the TypeScript or Python SDK305- Test it with Claude Desktop or the MCP Inspector306
:MCP (Model Context Protocol): The Complete Guide for Developerslines 1-306 (END) — press q to close