What is MCP? Model Context Protocol & MCP Servers Fully Explained (2026)
The Bespoke Integration Nightmare: AI in a Sandbox
Imagine purchasing a state-of-the-art computer, only to find that it lacks USB ports, HDMI connectors, or internet access. It has no way to interface with the outside world. To connect a printer or a keyboard, you would have to open the computer chassis, solder wires directly to the motherboard, and write a custom driver from scratch. This is exactly what developers faced when building AI-powered applications before the arrival of the Model Context Protocol (MCP).
Large Language Models (LLMs) are incredibly smart. They write code, draft essays, and analyze complex logical problems. However, by default, they are locked inside an execution sandbox. They have no access to your local files, no knowledge of your customer database, no capability to query real-time APIs, and no power to run terminal commands. To give them these powers, developers built custom, bespoke integration code for every single tool and model. A database connection code for Claude could not be used with Gemini. An API integration wrapper in Cursor had to be rewritten for Zed. This fragmented approach led to duplicate codebases, security vulnerabilities, and massive engineering overhead.
This is the problem solved by the Model Context Protocol (MCP). Created by Anthropic and open-sourced to the community, MCP acts as the "USB-C port" for AI models. It defines a single, open standard for how AI clients (like Claude Desktop or Cursor) connect to external servers (which expose databases, APIs, and tools). Write the integration once as an MCP server, and any compliant AI application can use it instantly.
What is Model Context Protocol (MCP)?
The Model Context Protocol (MCP) is a standardized, open-source protocol that establishes a secure, structured communication channel between AI applications (clients) and external data sources or tools (servers). The protocol utilizes JSON-RPC 2.0 over standard transport channels (like stdio or HTTP with Server-Sent Events) to negotiate capabilities, request data, and execute functions.
By defining a shared contract, MCP decouples the AI model from the tooling layer. The AI client doesn't need to know how to query a database or scrape a web page; it simply asks the MCP server to do it. The server executes the operation and returns the results formatted in a way the model can easily digest.
The Three Core Primitives of MCP
An MCP server can expose three primary capabilities to a client. These are called the core primitives:
1. Tools (Action Execution)
Tools are executable functions that allow the AI to perform actions or compute results in the external world. A tool has a defined name, a description, and an input schema defined using **JSON Schema** or **Zod**. When the AI model decides it needs to take an actionfor instance, writing a file or calling an APIit issues a tool-call request. The client routes this request to the server, which runs the underlying code and returns the outcome.
Examples of tools include: search_web(query), run_query(sql), or send_slack_message(channel, text).
2. Resources (Context Injection)
Resources are read-only data sources that provide the AI with static or dynamic context. Resources are identified by unique URIs (e.g., file:///workspace/src/app.ts or api://docs/mcp-setup). The client can query these resources to retrieve snapshots of code, documentation files, configuration settings, or database schemas. Because they are read-only, resources are a safe way to inject data into the model's context window without risking destructive modifications.
3. Prompts (Pre-configured Templates)
Prompts are reusable templates stored on the server that help users structure their interactions with the AI. They can contain pre-written instructions and placeholders for variables. An MCP server for git, for example, might expose a prompt called review-code that tells the model exactly how to perform a security review on a specified file path. Prompts encode expert workflows directly into the server.
Before MCP vs. After MCP: The Architecture Shift
To see how revolutionary the protocol is, examine this comparative table of development before and after the MCP standard:
| Before MCP | With MCP Protocol |
|---|---|
| Bespoke API wrappers rewritten for every tool and app. | One universal standard. A server built once works everywhere. |
| Platform lock-in. Tools tied to Cursor don't work in Claude. | Platform agnostic. Works in Claude, Cursor, Zed, and custom apps. |
| Fragile client logic. Custom parsers for diverse JSON formats. | Strict JSON-RPC contracts ensuring reliable message exchange. |
| Security handled ad-hoc. High risk of token exposure. | Defined security boundaries. Sandboxed stdio processes. |
How the Protocol Works Under the Hood: Technical Deep Dive
MCP is built on top of JSON-RPC 2.0, a lightweight remote procedure call protocol. In an MCP connection, there is always a **Client** (the AI app) and a **Server** (the tool provider). The communication is message-based, following a request-response pattern. Here is the step-by-step flow of an active session:
- Handshake & Initialization: The client spawns the server process (via stdio transport) or opens a network socket (via SSE transport). They exchange initialization requests to align on protocol versions and optional capabilities.
- Discovery: The client calls
tools/list,resources/list, andprompts/list. The server replies with schemas containing descriptions and arguments for all available capabilities. - Context Construction: The client formats the server schemas and registers them in the system instructions for the LLM. The model is now aware of the tools it can use.
- Tool Execution: When the model decides to run a tool, it generates a JSON block containing the tool's name and arguments. The client intercepts this tool call, builds a
tools/callJSON-RPC request, and forwards it to the server. - Response: The server executes the function locally, formats the output (text, images, or JSON), and replies. The client feeds the result back to the model, which resumes its task.
Available Transports: stdio vs HTTP SSE
MCP supports two main communication channels:
- stdio Transport: The client launches the server as a local subprocess and communicates via standard input/output streams. This is the default transport for local tools (like filesystem search) because it inherits the client's local security context and doesn't expose any ports to the network.
- Server-Sent Events (SSE) Transport: The client establishes an HTTP connection to a remote hosted server. The server sends events downstream via SSE, and the client sends requests upstream using HTTP POST. This is designed for hosted cloud services and collaborative enterprise data repositories.
Step-by-Step Tutorial: Building Your First MCP Server in TypeScript
Let's build a practical, functional MCP server from scratch. We will write a server that exposes a calculator tool and a local file explorer tool using Node.js, TypeScript, and the official @modelcontextprotocol/sdk package.
1. Initializing the Project
Create a new directory and initialize your project:
mkdir my-mcp-server
cd my-mcp-server
npm init -y
npm install @modelcontextprotocol/sdk zod
npm install -D typescript ts-node @types/node
Create a basic tsconfig.json file in your directory:
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"esModuleInterop": true,
"strict": true,
"skipLibCheck": true
}
}
2. Writing the Server Code
Create a file named src/index.ts and add the following complete implementation:
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
import * as fs from "fs/promises";
import * as path from "path";
// Initialize the MCP server metadata
const server = new McpServer({
name: "custom-utility-server",
version: "1.0.0"
});
// Register Tool 1: Math Calculator
server.tool(
"calculate",
{
operation: z.enum(["add", "subtract", "multiply", "divide"]).describe("Operation to perform"),
a: z.number().describe("First operand"),
b: z.number().describe("Second operand")
},
async ({ operation, a, b }) => {
let result = 0;
switch (operation) {
case "add": result = a + b; break;
case "subtract": result = a - b; break;
case "multiply": result = a * b; break;
case "divide":
if (b === 0) {
return {
isError: true,
content: [{ type: "text", text: "Error: Division by zero is not allowed." }]
};
}
result = a / b;
break;
}
return {
content: [{ type: "text", text: `Calculation result: ${result}` }]
};
}
);
// Register Tool 2: Read Local Directory
server.tool(
"list_directory_contents",
{
dirPath: z.string().describe("Absolute path to the directory to list")
},
async ({ dirPath }) => {
try {
const resolvedPath = path.resolve(dirPath);
const files = await fs.readdir(resolvedPath);
const details = await Promise.all(
files.map(async (file) => {
const stats = await fs.stat(path.join(resolvedPath, file));
return `${stats.isDirectory() ? "[DIR]" : "[FILE]"} ${file} (${stats.size} bytes)`;
})
);
return {
content: [{ type: "text", text: details.join("\n") || "Directory is empty." }]
};
} catch (error: any) {
return {
isError: true,
content: [{ type: "text", text: `Failed to read directory: ${error.message}` }]
};
}
}
);
// Start the server using stdio transport
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("Custom MCP Server running on stdio transport");
}
main().catch((error) => {
console.error("Fatal error in main:", error);
process.exit(1);
});
console.error. The main stdout stream is reserved exclusively for the JSON-RPC protocol messages. Sending plain text to stdout will corrupt the handshake and crash the client connection.
3. Building the Server
Add a build step in your package.json:
"scripts": {
"build": "tsc",
"start": "node dist/index.js"
}
Run npm run build to compile the TypeScript code into JavaScript.
How to Connect the Server to AI Clients
Now that your server is compiled, you can plug it into standard developer-facing AI clients. Here are the config details:
1. Claude Desktop Configuration
Claude Desktop is the flagship client. Open your configurations file:
- Windows:
%APPDATA%\Claude\claude_desktop_config.json - macOS:
~/Library/Application Support/Claude/claude_desktop_config.json
Add your server to the mcpServers dictionary:
{
"mcpServers": {
"my-custom-server": {
"command": "node",
"args": ["C:/path/to/my-mcp-server/dist/index.js"]
}
}
}
Restart Claude Desktop. You will see a small plug icon in the prompt box, indicating that Claude has discovered and registered your calculator and directory tools.
2. Cursor Configuration
To configure your custom server in Cursor:
- Go to Settings → Cursor Settings → Features → MCP.
- Click + Add New MCP Server.
- Set the name to
my-custom-server, transport tocommand, and value tonode C:/path/to/my-mcp-server/dist/index.js. - Click Save. Cursor will connect to the process and show green status indicators next to the registered tools.
MCP Security Model: Keeping the Sandbox Safe
Giving an AI model access to your local machine is inherently risky. A malicious tool could wipe your hard drive, access credentials, or leak sensitive source code. MCP implements strict security boundary rules to protect the user:
- User Authorization: compliant clients surface notifications to the user before running destructive tools. For instance, if the model attempts to run a tool to write code, the client alerts the user with a prompt asking for permission.
- Standard Streams Separation: The stdio transport model sandboxes the process context. The server has access only to the file directory ranges it was explicitly launched in, preventing general access hikes.
- Authentication on SSE: Remote connections over HTTP SSE require standard API key authorization or OAuth wrappers, ensuring only authenticated clients can trigger backend database servers.
The Rising MCP Ecosystem: Popular Community Servers
The standard has triggered massive community growth. There are thousands of pre-built MCP servers you can use without writing code. Highlights include:
- Filesystem Server: Exposes local directory search, file reads, and edits to Claude and Cursor.
- GitHub Server: Lets the AI view issues, open pull requests, look up commit logs, and search repositories.
- Puppeteer Server: Allows the AI to browse the web, click navigation targets, enter form parameters, and capture page screenshots.
- PostgreSQL / MySQL Servers: Exposes SQL database structures and tables so the AI can write, run, and verify database scripts.
Frequently Asked Questions About Model Context Protocol
- What is MCP in AI?
- MCP stands for Model Context Protocol. It is an open-source standard designed by Anthropic that defines how AI models connect to external tools, database systems, and APIs. It functions like a universal USB adapter for AI systems.
- What is an MCP server?
- An MCP server is a standalone process that connects to a specific data source or tool (like a file directory or database) and exposes its operations as tools, resources, or prompt templates using standard JSON-RPC protocol structures.
- Does MCP only work with Claude models?
- No. Although created by Anthropic, the standard is completely model-agnostic. Any LLM (including GPT-4, Gemini, and Llama) can consume tools from an MCP server as long as the client application (like Cursor or custom code) implements the protocol.
- Why can't I use console.log in my MCP server code?
- In local stdio transport, the server communicates with the client via stdout. Using
console.log()writes standard text to stdout, corrupting the JSON-RPC format and causing the client to crash. Always direct custom debug messages toconsole.error(), which uses stderr.