Understanding MCP (Model Context Protocol)
A practical introduction to MCP — what it is, how it works, and why it matters for building AI-powered tools.
What is MCP?
MCP (Model Context Protocol) is an open protocol that standardizes how applications provide context to LLMs. Think of it as USB-C for AI integrations — a universal connector that lets tools, data sources, and AI models communicate through a shared interface.
Before MCP, every AI integration was bespoke. You would write custom code to connect Claude to your database, your file system, your APIs. MCP makes this a solved problem.
How it works
An MCP system has three parts:
Host — the application running the LLM (e.g., Claude.ai, your app).
Client — a component inside the host that manages connections to servers.
Server — a lightweight program that exposes tools and data via the MCP protocol. Each server has a specific purpose: one might access your filesystem, another your database.
When the LLM needs to use a tool, it sends a request through the MCP client to the appropriate server. The server executes the operation and returns the result. The LLM can chain multiple tool calls to complete complex tasks.
Key primitives
MCP exposes three types of capabilities:
- Tools — functions the LLM can call (run a query, read a file, send a request)
- Resources — data the LLM can read (files, database rows, API responses)
- Prompts — reusable prompt templates the LLM can reference
Why it matters
Before MCP, integration work was the bottleneck in AI tooling. Every team reimplemented the same patterns. MCP shifts the conversation from “how do we connect this” to “what should the AI be able to do.”
The ecosystem is growing fast. Most major developer tools now have MCP servers, and building a new one takes a few hours.
Building your first MCP server
The TypeScript SDK makes this straightforward:
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { z } from 'zod';
const server = new McpServer({ name: 'my-server', version: '1.0.0' });
server.tool(
'get_weather',
{ city: z.string() },
async ({ city }) => ({
content: [{ type: 'text', text: `Weather in ${city}: sunny, 22°C` }]
})
);
The LLM can now call get_weather as a tool. Add more tools, expose resources, and you have a powerful AI integration — no custom plumbing required.