Model Context Protocol (MCP): The Standard That Is Reshaping AI Applications

Model Context Protocol (MCP): The Standard That Is Reshaping AI Applications
By Neel Shah · August 5, 2026
If you have shipped anything with large language models in the last two years, you have felt the pain: every model that needs to do something in the real world — read a database, hit an API, open a file, call an internal service — needs a bespoke integration. Rebuild it for the next model. Rebuild it for the next tool. The result is a tangle of one-off connectors that nobody wants to maintain.
The Model Context Protocol (MCP) is the answer the industry has converged on. It is an open standard that defines one way for AI applications to discover and use external tools, data, and services. Introduced by Anthropic in late 2024, MCP moved from an experiment to an industry default within a year, and it now sits at the center of what Microsoft and others call the "agentic web." In December 2025, Anthropic donated MCP to the Agentic AI Foundation, a directed fund under the Linux Foundation co-founded by Anthropic, Block, and OpenAI, with backing from Google, Microsoft, AWS, Cloudflare, and Bloomberg — a strong signal that MCP is vendor-neutral infrastructure, not a single company's product.
This guide is written for engineers who want to actually build with MCP. We will cover what it solves, how the architecture fits together, how to build a working MCP server in Node.js, how enterprises are adopting it, and — critically — the security risks captured in the new OWASP MCP Top 10.
Why MCP matters right now
A few things are true at the same time in 2026:
- AI agents are the dominant application pattern. Copilots, autonomous agents, and assistants that take actions (not just generate text) are what companies are building. Every one of them needs to reach out to tools and data.
- The major platforms have standardized on MCP. Microsoft delivered first-party MCP support across GitHub, Copilot Studio, Dynamics 365, Azure AI Foundry, Semantic Kernel, and Windows 11. AWS built it into Bedrock and its agent tooling. OpenAI and Google support it. When the biggest platforms agree on a wire format, that format wins.
- Adoption has outrun security. The protocol is easy to stand up in ten minutes, and most tutorials stop there. That gap is exactly why OWASP published a dedicated MCP Top 10.
If you build AI assistants, copilots, or agents for clients, MCP is no longer optional context — it is the interface layer your work plugs into.
What MCP solves: the M×N integration problem
Before MCP, connecting AI models to tools was an M×N problem. If you have M AI applications and N tools or data sources, you potentially need M × N custom integrations. Each model provider had its own function-calling format, each tool had its own SDK, and none of it was portable.
MCP turns this into an M+N problem. A tool author writes one MCP server. An application author writes one MCP client. Any client can talk to any server. The analogy that has stuck is that MCP is a "USB-C port for AI" — a universal connector that replaces a drawer full of proprietary cables.
Concretely, MCP standardizes three things:
- Discovery — how an application finds out what a server can do.
- Invocation — how the application asks the server to do it.
- Context exchange — how data and results flow back into the model's working context.
That is the whole value proposition: build once, integrate everywhere.
MCP architecture
MCP is built on JSON-RPC 2.0. That is a deliberately boring, well-understood choice — request/response messages with methods and parameters, carried over a transport. There are three roles in the architecture:
Host — the AI application the user interacts with (Claude Desktop, an IDE like VS Code or Cursor, a custom agent you built). The host manages one or more clients and decides which servers to connect to.
Client — a connector living inside the host. Each client maintains a dedicated, one-to-one connection with a single server. If a host connects to five servers, it runs five clients.
Server — a lightweight program that exposes capabilities (your tools, your data, your service). A server can run locally (spawned as a subprocess by the host) or remotely (reachable over HTTP).
┌─────────────────────────────────────────┐
│ HOST (Claude, IDE, custom agent) │
│ │
│ ┌──────────┐ ┌──────────┐ │
│ │ Client A │ │ Client B │ ... │
│ └────┬─────┘ └────┬─────┘ │
└────────┼──────────────┼──────────────────┘
│ JSON-RPC 2.0 │
┌────▼─────┐ ┌────▼──────┐
│ Server A │ │ Server B │
│ (local) │ │ (remote) │
└────┬─────┘ └────┬──────┘
│ │
local files external API / DB
Transports
Two transports matter in practice:
- stdio — for local servers. The host spawns your server as a child process and communicates over standard input/output. Simple, fast, no networking. Ideal for developer tools and anything running on the user's machine.
- Streamable HTTP — the modern transport for remote servers, and the recommended one. It supports both stateless request/response and stateful sessions with resumability. (An older HTTP+SSE transport still exists but is retained only for backward compatibility — don't build new servers on it.)
Clients, servers, and tools
A server exposes three kinds of primitives. Knowing which to reach for is most of the design work.
Tools
Actions the model can take. A tool has a name, a description, and a typed input schema. When the model decides a tool is relevant, the client calls it and feeds the result back into context. Tools cause computation, side effects, and network calls — search_orders, create_invoice, send_email. This is the primitive you will use most.
Resources
Read-only data the client can surface to the user or model — a file's contents, a database row, a document. Resources are identified by URIs and are meant to be referenced, not to trigger side effects.
Prompts
Reusable templates that help users invoke a server's capabilities consistently — think of them as pre-baked, parameterized instructions a host can offer as slash-commands or menu items.
A useful rule of thumb: if it does something, it's a tool; if it is something, it's a resource; if it guides the interaction, it's a prompt.
Authentication & authorization
This is where a lot of MCP projects get sloppy, and where the security section later becomes very relevant.
Local (stdio) servers usually run with the user's own privileges on their own machine, so there is often no separate auth layer — the operating system is the boundary. The risk here is what the server itself is allowed to touch.
Remote (HTTP) servers are a different story. The MCP authorization model is built on OAuth 2.1, with the MCP server acting as an OAuth resource server:
- The server publishes protected resource metadata so clients can discover which authorization server to use.
- The client obtains an access token through a standard OAuth flow, using the user's existing trusted sign-in.
- Every tool call carries that token, and the server validates it before doing anything.
Two principles are non-negotiable:
- Tokens must be audience-bound. A token issued for your MCP server must not be blindly forwarded to a downstream API. Passing a token through to another service is a classic confused-deputy vulnerability.
- Scopes must be minimal and short-lived. Grant the narrowest permission that works, and prefer short-lived, scoped credentials over long-lived API keys baked into the server.
Microsoft and GitHub joined the MCP Steering Committee to help push an updated authorization specification. Separately, identity vendors have contributed a Cross-App Access extension, so that enterprises can wire agent access to the identity and consent frameworks they already trust. If you are building for enterprise clients, expect identity to be the first question their security team asks.
Building an MCP server with Node.js
Let's build a real one. We'll use the official TypeScript SDK, which is the same package whether you target stdio or HTTP. The example exposes a single get_order tool — the kind of thing you'd hand an e-commerce support agent.
The modern SDK uses
McpServerwithregisterTool()and Zod schemas. Avoid the olderserver.tool()and manualsetRequestHandler()patterns you may still find in stale tutorials.
1. Set up the project
mkdir orders-mcp && cd orders-mcp
npm init -y
npm install @modelcontextprotocol/sdk zod
npm install -D typescript @types/node
In package.json, set "type": "module" so the ESM imports work.
2. A local server over stdio
// src/stdio.ts
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: "orders-mcp",
version: "1.0.0",
});
// Pretend this is a database call.
async function lookupOrder(orderId: string) {
return {
id: orderId,
status: "shipped",
total: 129.0,
currency: "USD",
items: 3,
};
}
server.registerTool(
"get_order",
{
title: "Get order",
description: "Look up an order by its ID and return its current status.",
inputSchema: { orderId: z.string().describe("The order ID, e.g. ORD-1024") },
outputSchema: {
id: z.string(),
status: z.string(),
total: z.number(),
currency: z.string(),
items: z.number(),
},
},
async ({ orderId }) => {
const order = await lookupOrder(orderId);
return {
content: [{ type: "text", text: JSON.stringify(order, null, 2) }],
structuredContent: order, // typed result the client can consume directly
};
}
);
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
}
main();
Compile it, then point a host at it. For a client like Claude Desktop or an IDE, you register the server in a small JSON config:
{
"mcpServers": {
"orders": {
"command": "node",
"args": ["/absolute/path/to/orders-mcp/dist/stdio.js"]
}
}
}
That's the whole local loop: register a typed tool, connect a transport, and the host can now call your tool by name.
3. A remote server over Streamable HTTP (with Express)
For anything client-facing or multi-user, you want a remote server. Here is the stateless pattern — a fresh transport per request, which keeps things simple and horizontally scalable:
// src/http.ts
import express from "express";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
import { z } from "zod";
function buildServer() {
const server = new McpServer({ name: "orders-mcp", version: "1.0.0" });
server.registerTool(
"get_order",
{
title: "Get order",
description: "Look up an order by its ID.",
inputSchema: { orderId: z.string() },
},
async ({ orderId }) => ({
content: [{ type: "text", text: `Order ${orderId}: shipped` }],
})
);
return server;
}
const app = express();
app.use(express.json());
app.post("/mcp", async (req, res) => {
// Stateless: build a new server + transport per request.
const server = buildServer();
const transport = new StreamableHTTPServerTransport({
sessionIdGenerator: undefined,
});
res.on("close", () => {
transport.close();
server.close();
});
await server.connect(transport);
await transport.handleRequest(req, res, req.body);
});
app.listen(3000, () => console.log("MCP server on :3000/mcp"));
In production you would wrap that /mcp route with your OAuth 2.1 middleware, validate the bearer token, and scope each tool to what the authenticated user is allowed to do.
Enterprise adoption patterns
MCP stopped being a hobbyist protocol quickly. A few patterns are now common inside larger organizations:
Platform-native integration. Rather than every team writing glue code, vendors expose their products as MCP servers. Microsoft made core Windows functions and Dynamics 365 ERP addressable over MCP; AWS built it into Bedrock and its agent runtime. The pattern is: wrap the system of record in an MCP server once, and let any internal agent use it.
The agentic web. Microsoft's framing is that MCP is to agents what HTTP was to browsers — the connective tissue. Initiatives like NLWeb let any website expose a natural-language interface that is also an MCP server.
Server registries. As the number of servers exploded (well past ten thousand active servers, with nearly 100 million SDK downloads a month), organizations needed a catalog. MCP now has a registry concept — public or private directories of approved servers.
Governance and allowlists. Mature adopters treat MCP servers as production dependencies: allowlists of approved servers, audit logging on every tool invocation, and identity gateways in front of remote servers. If you are pitching MCP work to an enterprise client, having a governance story is often what closes the deal.
Common security risks: the OWASP MCP Top 10
MCP introduces a genuinely new attack surface. Unlike a traditional API where developers control every call, MCP lets a language model decide which tool to invoke, when, and with what arguments — based on natural language it was fed. That flexibility is the point, and it is also the risk.
The stakes are not hypothetical. Researchers filed dozens of CVEs against MCP servers and tooling in early 2026, and one Palo Alto Networks Unit 42 study measured a 78.3% attack success rate when five MCP servers were connected to a single agent. A real supply-chain incident in 2025 saw a malicious npm package impersonate a legitimate email MCP server through more than a dozen releases before detection.
OWASP responded with the MCP Top 10 — its first framework dedicated to this layer. Here is the full list (MCP01:2025 through MCP10:2025), in plain terms:
- MCP01 — Token Mismanagement & Secret Exposure. Hard-coded credentials, long-lived tokens, and secrets that leak into model memory, logs, or debug traces. Fix: short-lived scoped credentials, secret scanning, never log secrets.
- MCP02 — Privilege Escalation via Scope Creep. Permissions that start narrow and quietly expand until an agent can do far more than intended. Fix: enforce least privilege and re-check scopes at call time.
- MCP03 — Tool Poisoning. An adversary tampers with a tool, its metadata, or its output to manipulate the model. Fix: signed tool manifests, inspect tool descriptions, trust boundaries on outputs.
- MCP04 — Software Supply Chain Attacks & Dependency Tampering. A compromised dependency or fake server package alters agent behavior or plants a backdoor. Fix: pin and verify dependencies, use registries and allowlists.
- MCP05 — Command Injection & Execution. A tool builds shell commands, SQL, or API calls from untrusted input without sanitizing it — the single largest CVE category in early 2026. Fix: parameterize everything; never concatenate untrusted input into a command.
- MCP06 — Prompt Injection via Contextual Payloads. Malicious instructions embedded in data the model processes (documents, web pages, OCR text). Fix: treat all retrieved content as untrusted, isolate instructions from data, constrain tool permissions.
- MCP07 — Insufficient Authentication & Authorization. Servers, tools, or agents that fail to verify identity or enforce access control. Fix: OAuth 2.1, audience-bound tokens, server-side authorization on every call.
- MCP08 — Lack of Audit and Telemetry. Thin logging that makes incidents impossible to investigate. Fix: immutable audit trails of every tool invocation and context change.
- MCP09 — Shadow MCP Servers. Unapproved servers spun up for convenience — the AI equivalent of shadow IT. Fix: registries, allowlists, and governance to detect and block rogue servers.
- MCP10 — Context Injection & Over-Sharing. Shared, persistent, or under-scoped context windows that leak one user's or agent's data into another's. Fix: one session per user, partition context strictly, tag retrieved data with its owner.
The uncomfortable truth in that list: almost none of it is exotic. Scoped credentials, real authentication, input validation, audit logging — this is standard application-security hygiene. The problem is that MCP quick-starts show you how to get a server running in ten minutes and stop, so the security work never gets done. Read the OWASP MCP Top 10 before you ship, not after something breaks.
Key takeaways
- MCP is the standard interface between AI applications and the tools they act on. It turns an M×N integration mess into an M+N one.
- The architecture is hosts, clients, and servers over JSON-RPC 2.0, with stdio for local and Streamable HTTP for remote.
- Servers expose tools (actions), resources (read-only data), and prompts (templates).
- Auth for remote servers is OAuth 2.1 with audience-bound, least-privilege tokens.
- Building a server in Node.js is a few dozen lines with the official SDK and
registerTool(). - Enterprises adopt MCP through platform-native servers, registries, allowlists, and governance.
- Security is the differentiator. The OWASP MCP Top 10 is your checklist; most of it is ordinary hygiene that MCP tutorials skip.
Every company building AI assistants, copilots, or autonomous agents is evaluating MCP right now. Understanding the protocol — and being able to build a secure server on it — is quickly becoming a baseline skill for anyone working at the intersection of full-stack engineering and AI.
Sources & further reading
- OWASP MCP Top 10 — official project page and repository (owasp.org/www-project-mcp-top-10)
- OWASP MCP Security Cheat Sheet
- Model Context Protocol — official specification and TypeScript SDK documentation
- Microsoft Build 2025: "The age of AI agents and building the open agentic web" (Microsoft blog)
- "Securing the Model Context Protocol" (Windows Experience Blog)
- Palo Alto Networks Unit 42 research on MCP attack surface
Neel Shah
Contract full-stack developer building e-commerce and SaaS products with Next.js, Node.js and MongoDB from Ahmedabad, India.
Work with me →// contact
Working on something similar?
Happy to compare notes or help out — say hello.