Model Context Protocol: The USB-C Moment for AI Tooling
For the past two years, every AI integration was bespoke. You wrote a custom function calling schema, you wired up the tool yourself, you handled errors in your own way. Multiply that by every model, every app, every tool, and the fragmentation was brutal.
Model Context Protocol (MCP) is the attempt to fix that — a standard interface so that any AI client can talk to any tool server without custom glue code on either side. Think of it as USB-C for AI tooling.
What MCP actually is
MCP is a JSON-RPC protocol that defines how an AI host (like Claude Desktop, Cursor, or your own app) connects to tool servers. The server exposes:
- Tools — actions the model can call (search, write file, query database)
- Resources — data sources the model can read (files, API responses, database rows)
- Prompts — reusable prompt templates the host can inject
The key insight: the server doesn't know which model is calling it. The client doesn't know how the server works internally. Both just speak MCP.
Building a minimal MCP server
Here's a TypeScript server that exposes a single tool — fetching a GitHub issue:
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
const server = new McpServer({
name: "github-tools",
version: "1.0.0",
});
server.tool(
"get_issue",
"Fetch a GitHub issue by repo and number",
{
owner: z.string().describe("Repository owner"),
repo: z.string().describe("Repository name"),
issue_number: z.number().describe("Issue number"),
},
async ({ owner, repo, issue_number }) => {
const res = await fetch(
`https://api.github.com/repos/${owner}/${repo}/issues/${issue_number}`,
{ headers: { Authorization: `Bearer ${process.env.GITHUB_TOKEN}` } }
);
const issue = await res.json();
return {
content: [
{
type: "text",
text: `#${issue.number}: ${issue.title}\n\n${issue.body}`,
},
],
};
}
);
const transport = new StdioServerTransport();
await server.connect(transport);
That's a complete, functional MCP server. Any MCP-compatible client can now call get_issue without knowing anything about GitHub's API.
Why this matters for developers
Before MCP, if you wanted Claude to access your database, you had to:
- Write a tool definition in Claude's format
- Handle the tool call in your application
- Repeat for every other model or app
With MCP:
- Write one MCP server for your database
- Any MCP client — Claude Desktop, Cursor, your custom app — can use it immediately
The ecosystem is already real. There are MCP servers for Postgres, Slack, Linear, GitHub, Figma, Notion, and dozens more. You can compose them: give your AI agent access to a GitHub server and a Postgres server and it can write code, check issues, and query your database in a single workflow.
The transport question
MCP supports two transports:
- stdio — the server runs as a child process, communicates over stdin/stdout. Good for local tools, simple to set up.
- HTTP + SSE — the server runs as a network service. Required for remote tools, multi-tenant deployments, or anything that can't run locally.
For developer tools, start with stdio. For anything you want to share or run in production, HTTP is the right answer.
What to watch out for
MCP is young. A few things to know:
- Authentication is not standardized yet. Each server handles it differently.
- Capability negotiation between client and server can be fiddly on first connection.
- Large resource responses can overwhelm model context. Cap your output sizes explicitly.
The protocol is also evolving. Anthropic has been iterating on the spec, and things that work today may need updates after a major version bump.
MCP won't eliminate all integration work, but it eliminates the most tedious parts. The ecosystem of composable tool servers is going to matter a lot as agents become more capable. Getting familiar with MCP now is the right call.