Skip to main content
Back to blog

What is an MCP server and why should you care?

·12 min readAI

If you have been following the AI tooling space, you have probably seen "MCP" mentioned a lot recently. The Model Context Protocol is one of those things that sounds abstract until you see it in action, and then it clicks immediately.

I have been building with MCP for a few months now, including my own MCP server, and I want to explain what it actually is, how it works under the hood, and why it has become one of the most important pieces of infrastructure in the AI developer tools ecosystem.

The basic idea

MCP is a protocol that lets AI assistants connect to external tools and data sources in a standardized way. An MCP server is a small program that exposes some capability, like reading a database, searching files, calling an API, or interacting with a service. The AI assistant connects to these servers and can use their tools during a conversation.

Think of it like USB for AI tools. Instead of every AI assistant needing custom integrations for every service, MCP provides a common interface that any assistant can use with any tool.

This analogy actually understates the problem MCP solves. Before MCP, if you had 5 AI assistants and 10 external tools, you needed 50 custom integrations. Each assistant had its own way of connecting to each tool. MCP reduces that to 15: each assistant implements the MCP client protocol once, each tool implements the MCP server protocol once, and they all work together.

graph LR
    subgraph Host
        H[AI App e.g. Claude Code] --> MC[MCP Client]
    end
    MC --> S1[MCP Server: DB]
    MC --> S2[MCP Server: GitHub]
    MC --> S3[MCP Server: Filesystem]
    S1 --> T1[(Database)]
    S2 --> T2[GitHub API]
    S3 --> T3[Local Files]

Where MCP came from

MCP was created by David Soria Parra and Justin Spahr-Summers, two engineers at Anthropic. The story is relatable. In mid-2024, Soria Parra was working on internal developer tooling and kept getting frustrated by the same thing I described in my Omnibase post: constantly copying context between Claude Desktop and his IDE. He wanted extensibility, a way for AI assistants to reach out and interact with external systems directly.

He and Spahr-Summers built a prototype, shared it internally, and people started building things with it at an Anthropic hackathon. Anthropic open-sourced it in November 2024 as a public standard, taking explicit inspiration from the Language Server Protocol (LSP). LSP solved the same N-times-M problem for programming language support in IDEs: instead of every IDE implementing every language, LSP gave them a shared protocol. MCP does the same thing for AI-to-tool integration.

The adoption since then has been fast. OpenAI added MCP support to ChatGPT in March 2025. Google DeepMind followed in April. VS Code shipped native MCP support in July 2025. In December 2025, Anthropic donated MCP to the Agentic AI Foundation under the Linux Foundation, with Anthropic, Block, and OpenAI as co-founders. As of early 2026, there are over 5,000 community-built MCP servers.

A practical example

Say you want your AI assistant to be able to query your project's database. Without MCP, you would need to copy-paste query results into the chat. With MCP, you run a database MCP server, connect your assistant to it, and now the assistant can run queries directly as part of the conversation.

But it goes further than one-shot queries. The assistant can discover the database schema, sample some data to understand the shape of it, form a hypothesis about what is going on, write a query, validate it, execute it, analyze the results, and run follow-up queries. That entire exploration loop happens in seconds without you acting as a clipboard. I walk through a real example of this in my Omnibase post if you want to see what it looks like in practice.

The same pattern works for file systems, APIs, documentation sites, and pretty much anything else you can write a thin wrapper around.

How the protocol works

Under the hood, MCP uses JSON-RPC 2.0 for all communication. If you have used LSP or any JSON-RPC based protocol before, the structure will look familiar. Every message is a JSON object with a method name and parameters, and responses come back with results or errors.

There are three participants in any MCP interaction:

The host is the AI application you are using. Claude Desktop, VS Code, Cursor, or whatever client is running the conversation.

The client is a connector inside the host that maintains a dedicated connection to one MCP server. If you have three MCP servers configured, the host creates three separate clients.

The server is the program that provides capabilities. It runs as a separate process and communicates with the client through one of two transport mechanisms.

Transport: how messages move

stdio is the most common transport for local servers. The client launches the server as a subprocess and communicates through stdin/stdout. Messages are newline-delimited JSON-RPC. This is how most MCP servers work today, and it is the simplest to implement. No network configuration, no ports, no authentication. The client starts the process and talks to it directly.

Streamable HTTP is the transport for remote servers. The server runs independently (on a remote machine or as a cloud service) and exposes a single HTTP endpoint. The client sends POST requests with JSON-RPC payloads, and the server responds with either a single JSON response or an SSE stream for operations that produce multiple messages. This transport supports session management, resumability, and multiple concurrent clients. It replaced the older HTTP+SSE transport from the original 2024 spec.

Connection lifecycle

When a client connects to a server, they go through an initialization handshake. The client sends an initialize request with its protocol version and capabilities. The server responds with its own capabilities. This tells both sides what features are supported: does the server offer tools? Resources? Prompts? Does the client support sampling? Only after this handshake completes can normal operations begin.

The three primitives

Everything an MCP server can do falls into three categories, and understanding the distinction between them matters.

Tools (model-controlled)

Tools are functions the AI model can discover and call. They are the most commonly used primitive, and what most people think of when they hear "MCP server." A tool has a name, a description, and an input schema (essentially the function signature). The AI model sees the available tools, decides when to use them based on the conversation, and calls them with appropriate arguments.

Tool: "search_documents"
Description: "Search internal documentation by keyword"
Input: { query: string, limit?: number }
Output: matching document excerpts

The important thing about tools is that the model decides when to call them. You do not explicitly tell the assistant "use the search tool now." It reads the conversation, determines that it needs to search something, and makes the call. This is what makes the experience feel agentic rather than scripted.

Resources (application-controlled)

Resources are read-only data sources that provide context. Think of them as files, documents, or data that the AI might need to reference. Each resource has a URI (like file:///project/schema.sql or a custom scheme like sqlite://schema) and can be text or binary.

The key distinction from tools is who controls them. Resources are managed by the application, not invoked by the model. The host application decides which resources to include in the context. Some clients let users browse available resources and attach them manually.

Resources also support templates with parameterized URIs (using RFC 6570 URI templates). A resource template like weather://forecast/{city} lets the application request specific variations without the server needing to pre-register every possible city.

Prompts (user-controlled)

Prompts are reusable interaction templates. They are the least intuitive of the three primitives, and honestly the least used in my experience. A prompt defines a structured conversation pattern that users can trigger explicitly, often exposed as slash commands in the UI.

For example, a code review MCP server might offer a /review prompt that takes a code snippet as an argument and returns a structured set of messages that guide the assistant through a specific review workflow. Unlike tools, prompts are not called automatically by the model. The user explicitly invokes them.

Why the distinction matters

This separation of control is deliberate. Tools are powerful because they let the model act autonomously. But you do not want everything to be model-controlled. Resources let the application manage what context is available without giving the model a "read anything" tool. Prompts let users trigger complex workflows explicitly rather than hoping the model figures out the right sequence of tool calls.

MCP vs function calling

If you have used function calling with the OpenAI or Anthropic APIs, you might wonder how MCP is different. They actually work at different layers.

Function calling is how an AI model decides to invoke a tool during a conversation. You define tools in the API request, the model generates a function call, your application executes it, and you send the result back. This happens at the API layer between your application and the model provider.

MCP standardizes the layer below that: how your application discovers and communicates with external tool servers. The AI model still uses its native function calling mechanism to decide which tool to invoke. MCP defines how those tools are registered, how the application connects to them, and how results are returned.

The practical difference is reusability. With function calling alone, tool definitions are embedded in your application code. If you build a database query tool for one app, you have to rebuild it for another. With MCP, that tool runs as a separate server that any MCP-compatible application can connect to. Build it once, use it everywhere.

Function callingMCP
Where tools are definedIn the API request payloadIn an external server
Vendor lock-inProvider-specific formatsProvider-agnostic standard
ReusabilitySingle applicationAny MCP client
DiscoveryStatic, defined at request timeDynamic, queried at runtime

For quick prototypes with a couple of tools, function calling is perfectly fine. For production systems where you want tools to work across multiple assistants and projects, MCP is the better foundation.

Who supports MCP

The list of MCP clients has grown quickly:

  • Claude Desktop and Claude Code have the deepest MCP integration. Claude Code has no limit on the number of tools and supports both local and remote servers.
  • ChatGPT added MCP support in March 2025, though currently limited to remote servers with OAuth.
  • VS Code and GitHub Copilot shipped native MCP support in July 2025 with built-in sandboxing and a curated marketplace.
  • Cursor supports MCP with probably the easiest setup (one-click install from their directory).
  • Windsurf, Cline, Continue, Zed, Amazon Q, Gemini and many others have added support.

On the server side, there are official reference servers for common services: filesystem access, GitHub, Git, Brave Search, Google Maps, PostgreSQL, SQLite, Slack, Puppeteer, and more. Companies like Stripe, Sentry, Notion, Linear, Figma, Cloudflare, and Shopify have built and published their own MCP servers. And the community has built thousands more.

Security considerations

Giving an AI model the ability to call external tools is powerful, which means security matters. The MCP spec is explicit about this: hosts should prompt users for confirmation before executing tools, especially any that modify data or interact with external services.

There are real attack vectors to think about. Prompt injection is the biggest one. If an MCP tool processes untrusted data (say, reading GitHub issues or emails), an attacker can embed hidden instructions in that data that trick the model into misusing other tools. There was a real incident in mid-2025 where a vulnerability in the official GitHub MCP server allowed malicious GitHub issues to hijack AI agents.

Tool poisoning is another concern. Since tool descriptions are part of what the model sees, a malicious MCP server could include hidden instructions in its tool descriptions that influence the model's behavior in unintended ways.

For local servers running over stdio, the attack surface is smaller because the server is a local process you launched yourself. For remote servers over HTTP, you need proper authentication (MCP supports OAuth 2.1), origin validation, and rate limiting.

The practical takeaway: vet the MCP servers you install the same way you vet npm packages. Use official and well-maintained servers. Be cautious with servers that request broad permissions. And always review what tools are doing before approving operations that modify data.

Getting started

Most modern AI coding tools already support MCP. If you use Claude Code, the easiest way to try it is:

claude mcp add filesystem -- npx -y @modelcontextprotocol/server-filesystem /path/to/directory

That installs the official filesystem MCP server and gives your AI assistant the ability to read and write files in the specified directory. You can add more servers the same way.

For other clients like Cursor or VS Code, the configuration is typically a JSON file where you list the servers you want to connect to, with the command to launch each one.

Building your own server is straightforward too. The protocol is simple, the SDKs are available in TypeScript, Python, Java, Kotlin, C#, and Go, and a basic server that exposes a couple of tools can be built in an afternoon. I wrote a step-by-step guide to building one in TypeScript if you want to try it.

Sources

Enjoying the blog? Subscribe via RSS to get new posts in your reader.

Subscribe via RSS