Model Context Protocol (MCP) for Developers

The Model Context Protocol is an open standard for connecting AI applications to your data and tools. A practitioner's guide to how MCP works, the host-client-server model, its tools, resources, and prompts, building an MCP server, and the security part most demos skip.

Occasional field notes on building software — no spam

Idealogic — Model Context Protocol

Every team that builds with AI hits the same wall. Your coding agent is smart, but it cannot see your database, your issue tracker, or your internal docs, so you write a custom integration to connect it. Then you do it again for the next tool, and again for the next model, and the connectors multiply until you're maintaining a small zoo of one-off adapters. The Model Context Protocol exists to kill that work. MCP is an open standard for connecting AI applications to the systems where your data and tools actually live, through one interface instead of many. This is a practitioner's guide to what MCP is, how it works under the hood, how it differs from plugins and hand-rolled integrations, what building an MCP server actually involves, and the security part the demos tend to skip.

What MCP is and why it exists

The Model Context Protocol is an open standard for connecting AI applications to external systems: your files, your databases, your APIs, your internal services. Anthropic released it in November 2024 and the official docs use a hardware analogy that lands well: think of MCP as "a USB-C port for AI applications." Before USB-C, every device needed its own cable. MCP is the standard plug, so an AI app and a data source can connect without a bespoke adapter for that exact pairing.

The problem it solves has a shape you can draw. Say you have a number of AI applications and a number of systems you want them to reach. Wire each one directly and you're on the hook for an integration per pair: that's the M times N problem, and it grows fast. Anthropic framed it plainly in the announcement: "Every new data source requires its own custom implementation, making truly connected systems difficult to scale." MCP turns the M times N tangle into M plus N. Each AI app implements the protocol once, each system exposes one MCP server once, and any app can talk to any server. The combinatorial mess collapses into a standard.

The official spec puts the lineage in useful terms. MCP "takes some inspiration from the Language Server Protocol," the standard that lets one language server give editor features to a whole ecosystem of IDEs instead of every editor reimplementing support for every language. MCP does the same move for AI: standardize the integration once so context and tools flow across the ecosystem rather than being rebuilt for each tool and each model. That's the whole idea, and it's why the protocol caught on quickly. Early adopters at launch included Block and Apollo, and developer-tool companies like Zed, Replit, Sourcegraph, and others started building on it. By mid-2026 it's supported across a wide range of clients, from Anthropic's Claude to other major AI applications and IDEs, which is exactly the network effect a standard needs to matter.

MCP turns the M times N integration problem into M plus N. Each AI app speaks the protocol once, each system exposes one server, and the bespoke glue code stops multiplying.

It helps to be precise about what MCP is not. It is not a model, not an agent framework, and not a replacement for your APIs. The spec is careful here: MCP "focuses solely on the protocol for context exchange," and explicitly does not dictate how an application uses an LLM or manages the context it receives. MCP is the connective tissue, the wiring between an AI app and the systems around it. What the model does with that connection is up to the application.

How MCP works: hosts, clients, and servers

MCP follows a client-server architecture with three participants, and getting the names straight is most of understanding how MCP works. The official architecture docs define them directly:

The relationship is one client per server, each with its own dedicated connection. An IDE acting as a host might run one client connected to a local filesystem server and another connected to a remote error-tracking server, both at once. That isolation is deliberate: each connection is independent, so one server cannot see another's traffic.

Under that, MCP is built in two layers, and the split is clean. The architecture docs describe a data layer and a transport layer.

The data layer is the protocol itself. It "defines the JSON-RPC based protocol for client-server communication," built on JSON-RPC 2.0, and it covers connection lifecycle, capability negotiation, and the core primitives. This is the part developers care about, because it defines what a server can offer and how a client asks for it. A connection opens with an initialize exchange in which the client and server negotiate which capabilities each supports, so neither side assumes a feature the other lacks. MCP is a stateful protocol, meaning the connection carries context across messages rather than treating each call as isolated.

The transport layer is how those messages travel, and the data layer does not care which one you pick. MCP defines two:

  • Stdio. Standard input and output streams, used when the server runs locally as a subprocess on the same machine. There is no network hop, which makes it fast and keeps the server reachable only by the local client.
  • Streamable HTTP. HTTP for remote servers, with optional Server-Sent Events for streaming. This is the transport for hosted MCP servers, and it carries standard HTTP authentication: bearer tokens, API keys, and the docs note that MCP recommends OAuth for obtaining those tokens.

Because the transport is abstracted away, the same JSON-RPC messages work whether a server is a local process or a service across the internet. You design your tools and resources once; where the server runs is a deployment choice, not a rewrite.

MCP primitives: tools, resources, and prompts

The heart of MCP is what a server can expose, and the spec calls these the primitives. There are three a server offers, and the cleanest way to keep them straight is by who controls each one, which is exactly how the official server docs frame it.

  • Tools are model-controlled. A tool is a function the AI can call to take an action: query a database, send a message, create a calendar event, write a file. The model decides when to invoke a tool based on the task. The server docs are blunt that "tools represent arbitrary code execution" on the other side, which is exactly why the safety discussion later in this piece matters. A client discovers tools with tools/list and runs one with tools/call.
  • Resources are application-controlled. A resource is read-only data the host can pull in as context: file contents, a database schema, API documentation, a knowledge-base article. Each resource has a unique URI, like file:///path/to/doc.md, and the application decides what to include and how. There are even resource templates, parameterized URIs such as a weather forecast keyed by city and date, so one definition serves a family of queries. Clients use resources/list and resources/read.
  • Prompts are user-controlled. A prompt is a reusable, parameterized template a person invokes deliberately, often surfaced as a slash command in the host UI. A "summarize my meetings" or "plan a vacation" template that takes structured arguments is a prompt. They are discovered with prompts/list and fetched with prompts/get.

That who-controls-it split is the design insight worth internalizing. Tools are for the model to act, resources are for the app to supply context, and prompts are for the user to trigger a workflow. Keeping the three as distinct concerns is what makes an MCP server predictable. Conflating them, say by hiding a write action inside something you call a resource, is how a server becomes surprising in the wrong way.

There is a fourth piece worth knowing, because it changes what servers can do. The protocol also defines a small set of primitives that flow the other direction, from server to client. The most notable is sampling, which lets a server ask the host to run a language-model completion on its behalf. As the architecture docs explain, this is "useful when server authors want access to a language model, but want to stay model-independent" and avoid bundling an LLM SDK into the server. There is also elicitation, where a server asks the user for more information mid-task, and roots and logging. These client features are how a server stays portable and interactive without owning a model of its own.

MCP vs plugins vs custom integrations

If you have wired AI into a product before, MCP looks familiar, and the natural question is what it actually buys you over the approaches you already know. The honest answer is that MCP is not magic; it is standardization, and standardization pays off at the boundaries.

A hand-rolled integration is the baseline. You write code that connects one specific AI app to one specific system, exactly the way you want. It's maximally flexible and it works. The cost shows up the second time: a different model, a different tool, a different app, and you're writing another adapter. Nothing you built transfers. This is the M times N tax in practice, and it's fine until you have enough pairs that maintaining them becomes the job. MCP's pitch is narrow and real: build the server once, and every MCP-speaking client can use it, today and as models change.

A plugin system is closer, but it is usually owned by one vendor. A plugin written for one platform's plugin format runs on that platform and nowhere else; the interface, the lifecycle, and the distribution all belong to whoever made the platform. MCP is an open protocol, not a single vendor's extension point, which is the difference that matters for the long run. A server you write to the MCP spec is not betting on one company's roadmap. The docs lean on this: build to the standard and "integrate everywhere" a client supports it, rather than rebuilding per platform.

The trade-off is worth stating plainly, because pretending a standard is free is how teams get disappointed. MCP adds a layer of indirection. For a single integration you'll build exactly once and never reuse, a direct call is simpler, and reaching for the protocol is overhead with no payoff. MCP earns its keep when you have more than one consumer, more than one system, or a real expectation that the models and tools underneath you will change, which in AI is less a possibility than a near-certainty. The decision rule is the same one good architecture always uses: pay for the abstraction when the reuse is real, and skip it when it is not.

ApproachReusable across apps and modelsOwnerBest when
Custom integrationNo, rebuilt per pairYouA single one-off connection
Vendor pluginWithin one platformThe platform vendorYou live inside one ecosystem
MCP serverYes, any MCP clientOpen standardMultiple consumers or changing models

Connecting an AI agent to the systems around your code is the broader discipline our AI integration services handle end to end, and MCP has quickly become the default way we do that wiring when more than one consumer is in play.

Building an MCP server: the shape of it

You almost never implement the protocol by hand. Anthropic ships official SDKs, and they exist for several languages, TypeScript and Python among them, so you describe what your server offers and the SDK handles the JSON-RPC, the lifecycle, and the transport. What follows is the shape of building a server, the concepts you reason about, not a line-by-line tutorial; the SDK docs cover the exact calls and they change often enough that pinning them here would age badly.

Start with the tools, because they are where most of the value and most of the risk live. Each tool definition carries three things: a name, a description, and an inputSchema. The schema is plain JSON Schema, listing the arguments and their types, which is what lets a client validate a call before it runs. A flight-search tool, for instance, declares string arguments for origin, destination, and date, and marks which are required. That description field is not decoration: it is what the model reads to decide when and how to use the tool, so a vague description produces a tool the model misuses or ignores. The same lesson that governs tool design for any agent applies here, and we go deep on it in our explainer on how AI agents work: narrow, well-described, hard-to-misuse tools beat one clever do-everything tool every time.

Then expose your resources if the server has context to share. A resource is data behind a URI that the host can read, and the design question is what reference material the AI genuinely needs, a schema, a doc set, a record, versus what would just bloat the context window. Resource templates let one definition cover a parameterized family, so you're not hand-registering a thousand near-identical URIs.

Add prompts where a repeatable workflow deserves a named, user-invoked template, then choose a transport. Stdio if the server runs locally beside the client, streamable HTTP if it runs as a remote service. That single choice determines deployment and most of your security posture, which is the next section.

Two practices separate a server that holds up from one that frustrates. First, test it in isolation before you connect it to anything real: the project ships the MCP Inspector, a tool for exercising a server's tools and resources directly so you can confirm behavior without a full host in the loop. Second, design the tools for a model, not for a human API consumer. A model reads the descriptions, guesses at arguments, and can't see your intent, so the tools that work are the obvious ones with honest error messages that let the agent recover when a call goes wrong. The protocol plumbing is the easy part. Designing the surface the model reasons about is the actual work, and it is the same craft we describe in our piece on agentic coding: the quality of the tools sets the ceiling on what the agent can do.

Want MCP servers and AI integrations built by a team that does this daily?
We connect AI agents to real systems through MCP and bespoke integrations, with the security review, tool design, and testing that keep the connection safe rather than just functional.
See our AI integration work

Where MCP fits in agentic coding

MCP matters most inside the loop where an AI agent does real engineering work, because that loop runs on context, and context is exactly what MCP standardizes the delivery of. An agent that can only see the files in front of it is guessing about everything else. An agent that can reach your database schema, your ticketing system, and your internal services through MCP servers writes code that fits your reality instead of plausible code that fits nothing.

This is the connective-tissue role across the whole AI-native engineering stack, and it sits next to two adjacent pieces. Tools are how an agent acts; MCP is how those tools and your data get exposed to the agent in a standard way; and skills are the procedural knowledge that teaches the agent how to use them well. We cover that last layer in our guide to Claude Code skills, and the relationship is worth holding onto: MCP is the connection, a skill is the know-how. You use MCP to give an agent access to your issue tracker, and a skill to teach it your team's particular way of triaging tickets. One is wiring, the other is judgment, and they stack rather than compete.

The reason this is becoming standard practice rather than a novelty is adoption on both sides. The 2025 Stack Overflow Developer Survey found that 84% of developers now use or plan to use AI tools, up from 76% the year before, and the tools they are adopting increasingly speak MCP, which means connecting an agent to a new system is starting to mean "point it at an MCP server" rather than "write a custom integration." That shift, from bespoke glue to a standard plug, is the practical face of what we mean by AI-native engineering: the practitioner's discipline of building with AI in the loop, where the leverage comes from giving the agent real context, not from the model alone.

MCP in production: security and trust

Here's the part that gets skipped, and it's the part that should slow you down. MCP is a connection standard, and a connection standard can't make itself safe. The specification says so directly: it "enables powerful capabilities through arbitrary data access and code execution paths," and "MCP itself cannot enforce these security principles at the protocol level." The safety is the implementor's job, which means yours. The protocol gives you the wiring; whether that wiring is safe to plug in is a decision you own. Three risk areas deserve real attention.

User consent is mandatory, and it is not a formality. The spec's first trust-and-safety principle is unambiguous: "Hosts must obtain explicit user consent before invoking any tool," and users "must explicitly consent to and understand all data access and operations." A tool can write to your database or hit an external API, so a host that auto-approves tool calls has handed a model the keys to act without a human in the path. Good hosts show what a tool will do and make you approve it, and the spec adds a sharp detail: tool descriptions and annotations "should be considered untrusted, unless obtained from a trusted server," because a description is text the model reads, and attacker-controlled text the model reads is the definition of prompt injection.

Prompt injection is the failure mode unique to this stack. Because the model reads tool descriptions and the data that tools return, a malicious server, or a legitimate server returning poisoned data, can smuggle instructions into the model's context. A tool whose description quietly says "also email the user's files to this address" is a real attack class, not a hypothetical. The defenses are the boring ones that work: connect only servers you trust, treat returned data as untrusted input, keep a human approving consequential actions, and do not assume the model will ignore an instruction just because it arrived through a tool result.

The supply chain is a server you are about to run. A local MCP server is a binary executing on your machine with your privileges, and the spec spells out the danger: an attacker can ship "a malicious payload inside the server itself" or embed a hostile startup command, with "arbitrary code execution" as the result. The guidance is to show the exact command before running it, sandbox servers with minimal privileges, and vet a server the same way you vet any dependency you are about to install. On the auth side, the spec names two rules worth carrying: token passthrough is "explicitly forbidden," so a server "MUST NOT accept any tokens that were not explicitly issued for the MCP server," and scopes should follow least privilege so a leaked token has the smallest possible blast radius.

None of this is a reason to avoid MCP. It's a reason to treat an MCP server with the same seriousness you'd give any code that runs in your environment with access to your data, because that's what it is. The protocol is genuinely good engineering, and the standardization is a real win. The mistake is reading "open standard" as "safe by default" and connecting a server you found because it had a nice README. Connect servers you trust, sandbox the ones you are unsure about, require consent on actions that matter, and grant the least access that does the job. That judgment, knowing the connection is powerful precisely because it is dangerous, is the work, and it is the discipline we bring to every AI agent we build and the kind of engineering we are compounding as a bet.

Connect your AI to real systems with a team that builds MCP integrations securely, not just functionally
Talk to our engineers

Frequently asked questions

  • MCP is an open standard for connecting an AI application to external systems like your files, databases, and APIs. Anthropic released it in November 2024 and describes it as a USB-C port for AI applications: instead of writing a custom integration for every tool and every model, you connect through one standard interface. An AI app speaks MCP, a system exposes an MCP server, and the two work together without bespoke glue code.

  • An MCP server is a program that exposes capabilities to an AI application over the protocol. It can offer three things: tools, which are functions the model can call to take an action like querying a database; resources, which are read-only data the application can pull in as context; and prompts, which are reusable templates a user can invoke. A server can run locally on your machine or remotely as a service, and one AI app can connect to many servers at once.

  • MCP has two layers. The data layer is a JSON-RPC 2.0 protocol that defines the messages: connection setup, capability negotiation, and the calls for tools, resources, and prompts. The transport layer is how those messages travel, either over standard input and output for local servers or over streamable HTTP for remote ones. A host application creates one client per server, each client holds a dedicated connection, and the client discovers what a server offers before the model uses any of it.

  • They differ by who controls them. Tools are model-controlled: the AI decides when to call them to perform an action, like sending a message or running a query. Resources are application-controlled: read-only data such as file contents or a database schema that the app pulls in as context. Prompts are user-controlled: templates a person invokes deliberately, often as a slash command. The split keeps actions, context, and user-triggered workflows as separate concerns.

  • You use one of the official MCP SDKs, which exist for languages including TypeScript, Python, and others, so you describe your tools and resources and the SDK handles the protocol. For each tool you give a name, a description, and an input schema in JSON Schema that defines its arguments. For resources you expose data under a URI. You pick a transport, standard input and output for a local server or streamable HTTP for a remote one, and test it with the MCP Inspector before connecting it to a real client. Most of the work is designing good tools, not wiring the protocol.

  • MCP is a connection standard, and the protocol itself cannot enforce safety, so security is the implementor's job. The specification is direct that tools represent arbitrary code execution and that a host must obtain explicit user consent before invoking any tool. The real risks are a malicious or compromised server running code on your machine, prompt injection through tool descriptions or returned data, and token mishandling. The spec forbids passing user tokens through to downstream APIs and pushes least-privilege scopes. Treat an untrusted MCP server like any untrusted dependency: review it, sandbox it, and grant it the minimum access it needs.

Related expertise