What is an MCP server? A plain-English guide with a real example
What is an MCP server? A plain-English explanation of the Model Context Protocol, how it works, with a real tools/call exchange and the security rules to know.
Piyushh · October 14, 2026 · 8 min read
What is an MCP server? It's a program that gives AI apps tools and data through the Model Context Protocol, an open standard for connecting AI applications to outside systems. Add a server to an MCP client like Claude Code or Cursor and the AI can call that server's tools on its own, such as "search Reddit" or "query this database". Nobody has to write a custom integration for that app.
The rest of this post covers how it works under the hood: a real request and response captured from a live MCP server, the parts of the spec that matter, and the security points the spec itself flags. Everything about the protocol here comes from the official spec at modelcontextprotocol.io, checked on 2026-10-14.
What is an MCP server, in plain English?
The MCP site's own analogy: "Think of MCP like a USB-C port for AI applications." Before USB-C, every device had its own plug. Before MCP, every AI app needed its own integration for every tool, so Slack in Claude was one integration, Slack in Cursor another, and so on. MCP reduces that to one plug on each side. A tool maker builds one MCP server, and any MCP client can use it.
Anthropic introduced MCP on November 25, 2024, describing it as "an open standard that enables developers to build secure, two-way connections" between data sources and AI tools. The official intro now lists support in Claude, ChatGPT, Visual Studio Code and Cursor, among others.
The three roles: host, client, server
The architecture overview names three participants:
- MCP host: "The AI application that coordinates and manages one or multiple MCP clients." Claude Code, Claude Desktop and VS Code are hosts.
- MCP client: "A component that maintains a connection to an MCP server." The host creates one client per server.
- MCP server: "A program that provides context to MCP clients."
If you add three servers to Cursor, Cursor (the host) runs three clients, and each one holds a connection to a single server. "Server" names a role and says nothing about where the program runs. The spec states plainly that an MCP server can run on your laptop or on someone else's infrastructure.
How does an MCP server work?
MCP has two layers. The data layer is a JSON-RPC 2.0 protocol that defines the messages: discovery, tools, resources, prompts and notifications. The transport layer moves those messages between client and server.
Transports: stdio and Streamable HTTP
The transports spec defines two standard transports:
- stdio: "The client launches the MCP server as a subprocess." Messages travel over standard input and output, one JSON-RPC message per line. Most local servers run this way, for example a filesystem server that reads files on your machine.
- Streamable HTTP: the server runs as an independent process with a single endpoint (for example
https://example.com/mcp) that accepts POST requests. Every client message is a new HTTP POST, and the client "MUST include anAcceptheader, listing bothapplication/jsonandtext/event-stream." The server replies with plain JSON or a Server-Sent Events stream.
A local server usually has one client. A remote server on Streamable HTTP usually has many, and authenticates them with bearer tokens, API keys or OAuth.
What servers offer: tools, resources and prompts
The spec defines three core things a server can expose:
| Primitive | What it is | Who controls it | Example |
|---|---|---|---|
| Tools | "Executable functions that AI applications can invoke to perform actions" | The model decides when to call | reddit_search, create_issue, run_query |
| Resources | "Data sources that provide contextual information" | The app decides what to attach | A file's contents, a database schema |
| Prompts | "Reusable templates that help structure interactions" | The user picks one | A "summarize this PR" template |
Each primitive has a */list method for discovery, and tools add tools/call for execution. When people talk about MCP servers, they mostly mean tools. A server can offer any subset of the three, and many API-backed servers offer only tools.
Clients can expose features to servers as well. Elicitation lets a server ask the user for input or confirmation in the middle of a task. As of protocol version 2026-07-28, sampling (a server asking the client's model for a completion), logging and roots are deprecated.
The 2026 change: MCP went stateless
Older tutorials open with an initialize handshake. The current spec, version 2026-07-28, removed it. Its changelog says the protocol is now stateless: "Every request now carries its protocol version and client capabilities in _meta." Servers must implement a new server/discover method that advertises supported versions and capabilities, and protocol-level sessions (the Mcp-Session-Id header) no longer exist.
Because clients and servers negotiate versions, older clients that still send initialize keep working with servers that accept it. The live server below accepts both.
A real MCP server example, request by request
Below is a complete exchange with a live remote MCP server, ChatterAPI's, which gives AI apps Reddit and X data. You can replay it with curl. We used a test key, which returns one recorded real sample per tool at no charge. Swap in your own key as $CHATTERAPI_KEY.
Step 1: discover what the server supports
curl https://api.chatterapi.com/mcp \
-H "Authorization: Bearer $CHATTERAPI_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "MCP-Protocol-Version: 2026-07-28" \
-H "Mcp-Method: server/discover" \
-d '{"jsonrpc":"2.0","id":1,"method":"server/discover","params":{"_meta":{
"io.modelcontextprotocol/protocolVersion":"2026-07-28",
"io.modelcontextprotocol/clientCapabilities":{},
"io.modelcontextprotocol/clientInfo":{"name":"curl","version":"1.0"}}}}'
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"supportedVersions": ["2026-07-28"],
"capabilities": { "tools": { "listChanged": true } },
"instructions": "ChatterAPI gives you live Reddit and X data. Every tool result ends with credits.charged and credits.remaining. Check remaining before long loops. Reddit tools are read-only. ...",
"resultType": "complete",
"ttlMs": 0,
"cacheScope": "private",
"_meta": { "io.modelcontextprotocol/serverInfo": { "name": "chatterapi", "version": "0.1.0" } }
}
}
The server says it supports tools (not resources or prompts) and can notify clients when its tool list changes. The instructions string is guidance the host can pass to the model.
When we left out the MCP-Protocol-Version header, the server rejected the request with error -32020 because "the request headers and body disagree". The 2026-07-28 spec requires the header to match the version in the body, so the server was right to reject it.
Step 2: list the tools
Send {"jsonrpc":"2.0","id":2,"method":"tools/list"} with the same headers. On 2026-10-14 this server returned 36 tools. Here is one of them, trimmed:
{
"name": "reddit_subreddit",
"title": "Subreddit Stats",
"description": "Get one subreddit's profile: title, description, subscriber count, creation date, NSFW flag, full rules, moderators and posting settings ... Costs 2 credits. Tip: read rules before drafting a post; ...",
"inputSchema": {
"type": "object",
"properties": { "name": { "type": "string", "description": "Subreddit name, r/name or URL, e.g. SaaS." } },
"required": ["name"],
"additionalProperties": false
},
"annotations": { "readOnlyHint": true, "destructiveHint": false, "idempotentHint": true, "openWorldHint": true }
}
The model reads this to decide when to call the tool: a name, a description written for a model, and a JSON Schema for the arguments. The annotations are hints that the tool only reads data.
Step 3: call a tool
If you ask "What are the rules in r/SaaS?", the host's model picks reddit_subreddit and the client sends:
curl https://api.chatterapi.com/mcp \
-H "Authorization: Bearer $CHATTERAPI_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "MCP-Protocol-Version: 2026-07-28" \
-H "Mcp-Method: tools/call" \
-H "Mcp-Name: reddit_subreddit" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{
"name":"reddit_subreddit","arguments":{"name":"SaaS"},
"_meta":{"io.modelcontextprotocol/protocolVersion":"2026-07-28",
"io.modelcontextprotocol/clientCapabilities":{}}}}'
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"content": [{ "type": "text", "text": "{\"data\":{\"name\":\"SaaS\",\"title\":\"Software as a Service\", ...}" }],
"structuredContent": {
"data": {
"name": "SaaS",
"title": "Software as a Service",
"subscribers": 820451,
"rules": [{ "title": "No Vendor Spam on posts or comments", "appliesTo": "all" }],
"moderators": [{ "name": "AutoModerator", "since": "2026-04-24T08:36:04.000Z" }],
"posting": { "submissionType": "any", "restrictPosting": true }
},
"credits": { "charged": 0, "remaining": 719 }
},
"resultType": "complete"
}
}
The result comes back twice, as JSON text in content and as an object in structuredContent. That follows the tools spec: "a tool that returns structured content SHOULD also return the serialized JSON in a TextContent block." The host passes the result to the model, which writes your answer. The sample had 11 rules. With a live key this call costs 2 credits.
So the loop is discover, list, call, and the rest of MCP builds on those three steps.
How to use an MCP server
Most people never send these requests by hand. You add the server to a client once, and from then on the client speaks the protocol for you. In Claude Code, adding a remote server looks like this:
claude mcp add --transport http chatterapi https://api.chatterapi.com/mcp \
--header "Authorization: Bearer $CHATTERAPI_KEY"
Configs for Claude Desktop, Cursor, Codex, Windsurf and VS Code are on the MCP server page, and the MCP docs have the details. For a hands-on setup with example prompts and results, see our Reddit MCP server guide. If you're choosing servers for social data, we compared the options in the best MCP servers for Reddit and X.
MCP server vs API: do you even need MCP?
Developers argue about this, and the skeptics have a point. In r/AI_Agents, a thread titled "Why use MCP when Agents can use APIs directly?" drew 170 comments. One commenter, u/AManHere, wrote: "At Google we abandoned MCP internally, too much overhead. We have agents use RPCs and CLIs directly" (comment). In r/mcp, a post summarized Cloudflare's argument that direct tool calling scales badly, because too many tools confuse the model and every intermediate result passes back through it (thread).
The top answer in the r/AI_Agents thread, from u/conurbano, draws the line: "MCPs shouldn't just be API wrappers." A server with one tool per endpoint adds little over the API itself. Another commenter, u/julesbuildstuff, framed it as a token problem: "a raw openapi spec dumped into context costs you thousands of tokens and the model still guesses wrong on the multi-step stuff." A good server offers "a small set of task-shaped tools." u/2BucChuck raised security. An MCP layer can expose only the endpoints you want "without putting the API key into the context flow of the agent."
So if you're writing code, call the API. If you want an AI app you didn't build, like Claude, Cursor or Codex, to use a service, MCP is the plug those apps already accept. That's why the same service often ships both: REST for code and MCP for agents.
MCP server security: what the spec says
An MCP server can read your data and act on your behalf, so adding one deserves the same care as installing software. The spec is firm about this.
- Keep a human in the loop. The tools spec says "there SHOULD always be a human in the loop with the ability to deny tool invocations," and that clients should show which tools are exposed and ask for confirmation on operations.
- Don't trust annotations blindly: "Clients MUST consider tool annotations to be untrusted unless they come from trusted servers." A tool marked read-only is only as honest as whoever wrote it.
- Servers have to validate input and rate-limit. The same spec says servers MUST "validate all tool inputs," "implement proper access controls," "rate limit tool invocations" and "sanitize tool outputs."
- Remote servers have to check origins. For Streamable HTTP, "Servers MUST validate the
Originheader on all incoming connections to prevent DNS rebinding attacks." Local servers should bind to 127.0.0.1 rather than every interface. - A local server runs code on your machine. The security best practices page warns that one-click installs can embed malicious startup commands. It says clients must "Show the exact command that will be executed, without truncation" and require explicit approval.
Tool results can also carry prompt injection, since whatever a tool returns lands in the model's context. In September 2026, a post in r/ClaudeAI with over 2,000 upvotes reported that Notion's official MCP connector told agents "to advertise Notion Business to you mid-task, and instructs it to never explain why" (thread). That is one user's report. Still, it shows how text returned by a server can steer your agent.
Maintenance is the quieter risk. @0xbobaaa scanned 424 MCP servers on GitHub and found "154 OF THEM ARE DEAD," meaning no commit in 90 days, while "they still install fine. your agent still calls them" (post). Before you trust a server because of its star count, look at its last commit and its auth model.
Try it
ChatterAPI runs a hosted MCP server that gives Claude, Cursor, Codex and other clients live Reddit and X data. One key works for both REST and MCP, and you don't apply for a developer account. Sign up with Google to get 100 free credits without a card, then replay the three requests above with your own key. Plans start at $19 a month for 25,000 credits.