TL;DR: Model Context Protocol (MCP) is an open standard introduced by Anthropic that solves the $N \times M$ integration bottleneck between large language models and external data systems. Instead of writing custom connectors for every model and interface, MCP provides a unified Client-Server architecture built around three core primitives: Resources (data reading), Prompts (reusable templates), and Tools (action execution).
The $N \times M$ Integration Bottleneck in AI
Before MCP, connecting language models to external data sources (databases, Git repositories, third-party APIs, local filesystems) suffered from a fundamental architectural flaw:
If you had $N$ AI applications (such as Claude, Cursor, or custom internal agents) and $M$ data sources (PostgreSQL, GitHub, Slack, Jira, Notion), you had to build and maintain $N \times M$ custom integrations.
WITHOUT MCP:
[Claude Desktop] ─── (Custom Code) ───> [PostgreSQL]
[Cursor IDE] ─── (Custom Code) ───> [PostgreSQL]
[Claude Desktop] ─── (Custom Code) ───> [GitHub API]
[Cursor IDE] ─── (Custom Code) ───> [GitHub API]
WITH MCP:
[Claude Desktop] ──┐
[Cursor IDE] ──┼──> [ MCP Protocol ] ──┬──> [MCP Server PostgreSQL]
[Claude Code] ──┘ └──> [MCP Server GitHub]
MCP eliminates this friction. By establishing an open specification built on JSON-RPC 2.0, any MCP-compliant client application can instantly interface with any existing MCP server.
MCP Architecture: Host, Client, and Server
MCP relies on a cleanly decoupled multi-tier architecture:
- MCP Host: The user-facing application orchestrating the AI interaction (e.g., Claude, Cursor, or Claude Code).
- MCP Client: The internal component inside the Host that maintains a 1:1 connection with an MCP server, handles capability negotiation, and manages JSON-RPC message passing.
- MCP Server: An independent process (local or remote) exposing resources, prompts, and tools through the MCP specification.
┌─────────────────────────────────────────────────────────┐
│ MCP HOST │
│ ┌─────────────────┐ ┌─────────────────────┐ │
│ │ UI / Chat │ ◄───────► │ LLM Engine │ │
│ └────────┬────────┘ └──────────┬──────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌───────────────────────────────────────────────────┐ │
│ │ MCP CLIENT │ │
│ └────────────────────────┬──────────────────────────┘ │
└───────────────────────────┼─────────────────────────────┘
│ (JSON-RPC 2.0 via stdio/SSE)
▼
┌─────────────────────────────────────────────────────────┐
│ MCP SERVER │
│ ┌──────────────┐ ┌──────────────┐ ┌───────────┐ │
│ │ Resources │ │ Prompts │ │ Tools │ │
│ └──────────────┘ └──────────────┘ └───────────┘ │
└───────────────────────────┴──────────────┴───────────┘
Communication Transports
MCP supports two standardized transport channels:
- stdio (Standard I/O): The Host spawns the MCP server as a local child process, communicating over
stdinandstdout. Ideal for local file access, system tools, and developer workflows. Sub-millisecond (<1ms) latency. - SSE (Server-Sent Events) over HTTP: Used for cloud-hosted or remote MCP servers. The client receives push notifications via SSE and sends RPC commands using HTTP POST requests.
The Three Core Primitives of MCP
MCP organizes all interaction patterns between the LLM and the external world into three core primitives:
1. Resources (Passive Context Reading)
Resources allow the server to expose passive data feeds to the model (logs, source files, database schemas, diagnostic reports). Resources are read by the client and injected into the prompt context.
- Addressed via unique URIs (e.g.,
postgres://database/users/schemaorfile:///var/logs/app.log). - Supports raw text or Base64-encoded binary content.
- Supports real-time subscriptions (
resources/subscribe): whenever a resource updates on the server, the client receives a notification to refresh the model context.
2. Prompts (Parameterized Templates)
Prompts enable servers to offer reusable, structured prompt workflows designed specifically for the domain logic managed by the server.
- Example: A GitHub MCP server can provide a
review-pull-requestprompt accepting apr_idparameter and generating targeted code review instructions for the LLM.
3. Tools (Executable Actions)
Tools represent stateful functions, computation routines, or API actions that the LLM can decide to execute.
- Each tool defines a name, detailed description, and a schema for input arguments defined via JSON Schema.
- When the LLM decides to call a tool, the MCP Client prompts the user for authorization (if configured) and executes the call on the MCP server, returning the output payload back to the model context.
Step-by-Step Guide: Building a Custom MCP Server in TypeScript
Here is a complete, production-grade TypeScript MCP server using @modelcontextprotocol/sdk on Node.js. This server exposes a tool for executing safe, read-only SQL queries on a local SQLite database.
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
CallToolRequestSchema,
ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
import Database from "better-sqlite3";
const db = new Database("app.db", { readonly: true });
// Initialize MCP Server instance
const server = new Server(
{
name: "sqlite-readonly-mcp",
version: "1.0.0",
},
{
capabilities: {
tools: {},
},
}
);
// Expose available tools
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: "execute_readonly_query",
description: "Executes a read-only SELECT query against the local SQLite database.",
inputSchema: {
type: "object",
properties: {
sql: {
type: "string",
description: "The SELECT SQL query string to run.",
},
},
required: ["sql"],
},
},
],
};
});
// Handle tool execution requests
server.setRequestHandler(CallToolRequestSchema, async (request) => {
if (request.params.name !== "execute_readonly_query") {
throw new Error(`Unknown tool: ${request.params.name}`);
}
const sql = String(request.params.arguments?.sql);
// Enforce read-only constraint
if (!sql.trim().toUpperCase().startsWith("SELECT")) {
return {
content: [
{
type: "text",
text: "ERROR: Only SELECT queries are permitted for security reasons.",
},
],
isError: true,
};
}
try {
const stmt = db.prepare(sql);
const rows = stmt.all();
return {
content: [
{
type: "text",
text: JSON.stringify(rows, null, 2),
},
],
};
} catch (error: any) {
return {
content: [
{
type: "text",
text: `SQL Execution Error: ${error.message}`,
},
],
isError: true,
};
}
});
// Connect transport over stdio
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("SQLite MCP Server running on stdio");
}
main().catch(console.error);
Client Configuration (e.g., Claude Desktop or Cursor)
To connect this server to Cursor or Claude Desktop, register it in your claude_desktop_config.json file:
{
"mcpServers": {
"sqlite-local": {
"command": "node",
"args": ["/path/to/dist/index.js"],
"env": {
"NODE_ENV": "production"
}
}
}
}
Security Model and Best Practices
MCP mitigates common AI agent risks, such as indirect prompt injection and unauthorized command execution:
- Process Isolation:
stdioservers run as child processes under local OS permissions, limiting unauthorized network calls unless explicitly authorized. - Human-in-the-Loop Safeguards: Protocol rules demand host applications prompt for explicit user approval before performing side-effect operations (
Tools). - Principle of Least Privilege: Deploy specialized, single-purpose servers (e.g., a read-only log tailing server vs. an infrastructure deployment server) rather than a single monolithic root-access server.
Technical Matrix: MCP vs Custom Tool Calling vs REST APIs
| Feature | MCP (Model Context Protocol) | Custom Tool Calling (OpenAI/Anthropic APIs) | Traditional REST APIs |
|---|---|---|---|
| Architecture | Open Client-Server (JSON-RPC 2.0) | Tightly coupled inside client code | Standard Web Client-Server |
| Reusability | High (one server works across IDEs and host apps) | Zero (code repeated per app) | High across web clients |
| Context Resources | Native (push-based resource subscriptions) | Manual (manually formatted text prompts) | Requires polling or Webhooks |
| Context Management | Standardized by Host application | Manual implementation by dev | N/A |
| Execution Mode | Local (stdio) or Remote (SSE) | Remote (backend API endpoints) | Remote |
The MCP Landscape in 2026
Model Context Protocol has become the default integration layer across modern software engineering workflows. It is supported out-of-the-box in:
- IDEs & Dev Tools: Cursor, Claude Code, VS Code extensions, Windsurf.
- Desktop Clients: Claude Desktop, Ollama Desktop interfaces.
- Production Connectors: Validated MCP servers for PostgreSQL, GitHub, GitLab, Brave Search, Puppeteer, Docker, Slack, Google Drive, and Sentry.
By standardizing context delivery and execution boundaries, MCP powers the next generation of interoperable, autonomous AI agents.