Who should read this
Summary: MCP (Model Context Protocol) is the open standard for connecting AI agents to external tools and data. Released by Anthropic in November 2024 and adopted by OpenAI, Google, and the rest of the major vendors, it has become the default answer to “how do I attach tools to an agent?” This article covers the architecture (Host–Client–Server), the three primitives, transport selection, tradeoffs against direct API integration, and the security risks you must address before adopting it — all from a practitioner’s perspective.
This article is written for developers who need to connect internal systems and external services to agents, and technical leads deciding whether to adopt MCP. It is not an SDK tutorial; it focuses on structure and decision criteria.
Why MCP, why now: the N×M integration problem
Agent development in 2023–2024 was integration hell. With N tools and M agents (or LLM apps), you needed N×M integration codebases. You wrapped the Slack API once for the Claude app, again for the internal chatbot, again for the IDE assistant — the same API wrapped slightly differently by every team.
MCP restructures this into “N servers + 1 standard protocol.” A tool provider builds an MCP server once, and every MCP-capable client (Claude, IDEs, your in-house agent runtime) uses it as-is. It standardizes peripheral connections the way USB-C did — which is why the “USB-C of AI” analogy stuck.
Adoption speed is what makes this standard real. After the November 2024 release, OpenAI and Google DeepMind announced support in the first half of 2025, and major IDEs and agent runtimes shipped built-in clients. Public MCP servers now number in the thousands, and an official registry has standardized how servers are distributed and discovered. In 2026, “can my agent use this tool?” effectively means “is there an MCP server for it?”
The architecture: Host, Client, Server
The most common initial confusion is assuming “client = my app.” MCP splits roles across three layers.
- Host: the application facing the user. It owns LLM calls, conversation management, and the policy decision of which servers to attach.
- Client: the protocol layer living inside the Host, maintaining a 1:1 connection with a server. Three servers means three clients.
- Server: the side exposing tools and data. A good server wraps one domain (GitHub, Postgres, your internal CRM) narrowly and deeply.
This split matters in practice because of trust boundaries. The Host trusts the user, the Server trusts the systems behind it — but the Host must not blindly trust the Server. We return to this boundary in the security section.
The three primitives — plus two reverse channels
What a server offers a client falls into three categories.
| What it is | Who controls it | Typical examples | |
|---|---|---|---|
| Tools | Executable functions the model invokes | LLM decides to call (human approval gate recommended) | Create an issue, run a query, send a message |
| Resources | Read-only context data provided to the model | Host/user selects and injects | File contents, DB schemas, documents |
| Prompts | Reusable prompt templates served by the server | User explicitly selects (slash commands, etc.) | Code review templates, structured report formats |
| Sampling (reverse) | Server requests a generation from the client's LLM | Client controls approval and billing | When server-side logic needs LLM inference |
| Elicitation (reverse) | Server requests additional input from the user | Client mediates through its UI | Mid-task confirmations and choice prompts |
One design trap worth naming: do not make everything a tool. A “read the docs” tool forces the model to decide on a call every time, while exposing the same data as a Resource lets the Host preload it into context. Seen through the lens of call-decision cost and context engineering, tool sprawl is an anti-pattern that inflates the agent’s decision burden.
And one more — tool outputs should come back as structured results, not free text; it makes downstream handling dramatically more reliable. We covered this in depth in the structured output guide.
Transports: stdio vs Streamable HTTP
MCP abstracts the transport layer, and the practical choice is binary.
| stdio | Streamable HTTP | |
|---|---|---|
| Execution model | Client launches the server as a local subprocess | Deployed as a standalone HTTP service, accessed remotely |
| Authentication | Inherits process permissions (no separate auth) | OAuth 2.1 based — the spec defines the auth flow |
| Best fit | Dev tools, CLIs, local files and personal environments | Team-shared services, SaaS integrations, multi-tenant |
| Ops burden | No deployment — ship a binary or script | Same as any web service (TLS, scaling, monitoring) |
| Watch out for | Server runs with your full local permissions | Session management, reconnects, legacy HTTP+SSE compatibility |
The decision rule is simple. “Should this server run with my machine’s permissions?” — if yes, stdio; if multiple people or hosts must share it, Streamable HTTP. The real operational cost of going remote is that authentication, authorization, and audit logging become necessary at the same level as any public-facing API service.
Direct API integration vs MCP: which, when
MCP becoming the standard does not mean every integration should be MCP. Defining tools directly through your framework’s function calling remains valid.
Empirically, the best middle ground is that last line. Keep the tool’s actual logic protocol-agnostic as pure functions, and when client count grows, adding an MCP adapter is a matter of days. Bury the logic inside one framework’s tool definitions instead, and the migration cost snowballs.
Security: the other side of convenience
Security research since 2025 keeps surfacing the same three MCP risks.
1. Tool poisoning — planting malicious instructions inside a server’s tool descriptions themselves. The model must read descriptions to use tools, so descriptions become a prompt-injection vector. Attaching a third-party server is equivalent to putting that server author’s text into your model’s context.
2. Prompt injection via data — the classic attack where instructions embedded in tool-returned data (issue bodies, emails, web pages) get followed by the model. MCP did not create this problem, but the easier tool connectivity gets, the wider the exposed surface honestly becomes.
3. Over-privileged tokens and the confused deputy — hand one server a broad token, and when the model gets tricked, the blast radius equals the token’s scope. When several systems’ permissions pool inside one server, “whose authority did this run under?” gets blurry.
Four common mistakes
1. “Every existing API endpoint becomes a tool” — port 30 REST endpoints into 30 tools and the model’s selection accuracy collapses. Redesigning around the agent’s units of work — 5 to 10 task-shaped tools — always wins.
2. Sloppy tool descriptions — a description is not documentation; it is the interface the model reads. When to use it, when not to, and the constraints on each argument: that is the entirety of description quality.
3. Errors without a next action — return a raw “500 Internal Server Error” and the model retries the same call. An error like “auth expired — ask the user to re-login” is what keeps the agent loop alive.
4. Running remote servers with local-stdio instincts — a remote MCP server is a real service that needs auth, sessions, version compatibility, and audit logs. The moment you ship it to a team, treat it as a first-class citizen of your engineering process.
Conclusion: the protocol is settled; the design is not
For “how do I connect tools to an agent?”, protocol uncertainty is effectively gone. MCP is sufficiently adopted, and the spec keeps maturing along the remote, auth, and interaction axes.
What remains is, as always, design. The instinct to group tools by task, the judgment to separate Resources from Tools, the placement of trust boundaries and approval gates — no protocol does these for you. MCP standardized the connection, not the judgment. And the quality of an agent system is, in the end, the sum of those judgments.
Further reading
- Harness Engineering: From Prompts to Runtime Control — the next layer up: designing the entire agent runtime
- LLM Structured Output: JSON Mode vs Function Calling vs Constrained Decoding — turning tool output into trustworthy data
- RAG Pipeline Design: From Chunking to Retrieval Quality Monitoring — designing the retrieval layer you hide behind an MCP server