ClaudeMap

·MCP Servers

A 2026 walkthrough of the Model Context Protocol (MCP) — what it solves, the Host/Client/Server triangle, the three primitives (tools/resources/prompts), stdio vs Streamable HTTP transports, the 2026 ecosystem in three layers (hosts, servers, directories), and five common misconceptions debunked.

What Is the Model Context Protocol? From Concept to Your First MCP Server (2026)

The Model Context Protocol (MCP) is a JSON-RPC 2.0 protocol between AI assistants and external tools that Anthropic open-sourced in November 2024 and that became the de-facto Claude ecosystem standard through 2025–2026. Through a uniform client-server architecture, any LLM Host (Claude Desktop / Claude Code / Cursor / Zed) can discover and call any MCP Server — databases, filesystems, browsers, Slack, GitHub — without rewriting integration code per tool. This guide, current as of the MCP 2025-11-25 spec, covers the protocol architecture, the boundary with function calling, the local-to-production migration path, and a working TypeScript server walkthrough.

TL;DR

  • MCP is a client-server JSON-RPC 2.0 protocol — the Host is the client, external tool processes are the server
  • Three primitives: tools (callable functions) / resources (readable data) / prompts (reusable templates)
  • Two transports: stdio (local process, OS boundary as trust) + Streamable HTTP (remote, OAuth 2.1 required)
  • Difference from function calling: MCP is a protocol layer, not an SDK — one server, many Hosts
  • 2026 status: MCP is the de-facto Claude ecosystem standard; claudemap.org indexes 80+ servers

The problem MCP solves

Before MCP, giving an assistant access to the outside world meant writing bespoke glue code. Every model vendor had a slightly different function-calling format. Every tool you wanted to expose — a database, a file system, a SaaS API — had to be packaged separately for each client that might call it. A filesystem tool built for one assistant would not work in another without a rewrite.

MCP defines a single, client-agnostic protocol for that integration. Write a tool once as an MCP server; any MCP-compatible client (Claude Desktop, Claude Code, Cursor, an in-house agent) can call it. The same is true in reverse: an agent that speaks MCP can reach any MCP server without caring how the tool was implemented inside.

You can think of it as "USB-C for AI tooling" — a standard plug that decouples the tool from the model.

The core vocabulary

MCP has a small set of nouns. Getting them straight makes everything downstream click into place.

  • Host — the application the user interacts with. Claude Desktop, Claude Code, and an IDE extension are all hosts. The host owns the conversation and the security boundary.
  • Client — a protocol object that lives inside the host and maintains a 1:1 connection with one server. A host that talks to five servers runs five clients.
  • Server — a small program that exposes capabilities to the client over the protocol. Servers are typically lightweight and focused: "filesystem", "github", "postgres".
  • Tool — a function the model can decide to call, with a name, a JSON-schema description of its inputs, and a handler that returns content back to the model. Tools are how MCP servers let the model act.
  • Resource — structured data the model can read, addressed by a URI. A log file, a database row, a configuration document. Resources are how MCP servers let the model read.
  • Prompt — a reusable, parameterized prompt template the server publishes. Clients can surface these in a UI (for example, a slash-command picker).

A server can expose any combination of tools, resources, and prompts. Most real servers lead with tools.

Underneath these nouns, MCP is just JSON-RPC 2.0 messages flowing over a transport. The two transports you will meet in practice are stdio (the host spawns the server as a subprocess and talks over stdin/stdout) and HTTP + Server-Sent Events (the server runs as a remote process). Local development almost always uses stdio.

MCP vs function calling

MCP is not a competitor to function calling — the two operate at different layers.

Function calling is a model capability: the model emits a structured request to invoke a named function, and the caller executes it and returns the result. It is defined per model vendor.

MCP is an integration protocol: it standardizes how a host discovers the available functions, how a server describes them, and how the result flows back. When an MCP host like Claude decides to call a tool, it still uses function calling internally — MCP just gave it a uniform way to learn the tool exists and to reach the server that implements it.

In short: function calling is the mechanism the model uses; MCP is the plumbing that connects many servers to many hosts without bespoke glue.

Build your first MCP server

Let's build a minimal but real server. We will expose one tool, add, that sums two numbers, plus a second tool, echo, that returns whatever string you send. It uses the official TypeScript SDK and the stdio transport.

1. Scaffold the project

mkdir mcp-demo && cd mcp-demo
npm init -y
npm install @modelcontextprotocol/sdk zod
npm pkg set type="module"

We set "type": "module" because the SDK ships as ESM, and we add zod because the high-level server API uses Zod schemas to describe tool inputs.

2. Write the server

Create index.js:

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: "demo-server",
  version: "1.0.0",
});

// A tool that adds two numbers. The third argument is a Zod schema
// describing the inputs; the SDK derives the JSON schema from it.
server.tool(
  "add",
  { a: z.number(), b: z.number() },
  async ({ a, b }) => ({
    content: [{ type: "text", text: String(a + b) }],
  }),
);

// A tool that echoes a string back, with an optional description field.
server.tool(
  "echo",
  { message: z.string() },
  async ({ message }) => ({
    content: [{ type: "text", text: message }],
  }),
);

const transport = new StdioServerTransport();
await server.connect(transport);

A few things worth noticing:

  • new McpServer({ name, version }) registers the server's identity, which the host displays to the user.
  • server.tool(name, schema, handler) is the high-level helper. The handler receives validated arguments and must return { content: [...] }, where each content item has a type (commonly "text").
  • StdioServerTransport wires the server to stdin/stdout so a host can spawn it as a subprocess.

3. Test it without a host

The SDK ships an interactive MCP Inspector that lets you call tools from a browser UI before any host is involved:

npx @modelcontextprotocol/inspector node index.js

Open the printed URL, click through to the add tool, and call it with a: 2, b: 3. If you see 5 come back, your server works.

Connect it to Claude Desktop

Claude Desktop discovers servers through a config file. On macOS it lives at ~/Library/Application Support/Claude/claude_desktop_config.json (on Windows, %APPDATA%\Claude\claude_desktop_config.json). Add an entry under mcpServers that points at your server's absolute path:

{
  "mcpServers": {
    "demo": {
      "command": "node",
      "args": ["/absolute/path/to/mcp-demo/index.js"]
    }
  }
}

Restart Claude Desktop, open a chat, and ask: "Use the add tool to sum 7 and 35." Claude will decide to call your add tool, execute it, and reply with 42. The hammer icon in the composer lets you confirm the tools your server exposes are loaded.

The same server, with no code changes, will also work in any other MCP-compatible host — Claude Code (via .mcp.json), Cursor, and others. That portability is the whole payoff.

Going further

Once the basics click, the natural next steps are:

  • Add resources with server.resource(...) to expose readable data such as a changelog or a directory listing.
  • Add prompt templates with server.prompt(...) to publish reusable, slash-command-style templates.
  • Switch the transport to HTTP + SSE so the server can run remotely instead of being spawned for every session.
  • Browse the ecosystem — ClaudeMap indexes dozens of MCP servers (filesystem, GitHub, Postgres, browser, and more) you can install and study as reference implementations.

Start with one tool, confirm the round-trip works in the Inspector, then wire it to a Host. MCP is deliberately narrow, so the gap between "hello world" and a working server is short.

Protocol architecture: the Host / Client / Server triangle

The key to understanding how MCP "works" is to see the three roles defined in the MCP architecture spec. This triangle is not the "one-to-one pairing" many developers assume:

| Role | What it is | Examples | |---|---|---| | Host | The LLM application itself — runs the UI, model inference, and LLM API calls | Claude Desktop, Claude Code, Cursor, Zed, Cline | | MCP Client | Protocol client embedded in the Host; one instance per Server | Claude Desktop forks a client per configured server | | MCP Server | External process that exposes tools / resources / prompts | filesystem server, Postgres server, Slack server |

Key fact: Host-to-Server is a many-to-many relationship. A single Claude Desktop instance can connect to 20+ MCP servers simultaneously (filesystem + database + Slack + GitHub + browser); the same GitHub MCP server can be called by Claude Desktop, Claude Code, and Cursor concurrently. This is the largest difference from traditional function calling — the latter is "custom tool code per LLM app", the former is "write the server once, every Host can use it."

The 2025-11-25 spec introduced the MCP Server Registry as a discovery layer (see concepts/transports): clients can look up stable URLs instead of relying on manual configuration. This is the key step that took MCP from "early adoption" to "production-grade."

Three primitives: tools / resources / prompts

MCP splits what a server exposes into three primitives, each with its own semantics, invocation pattern, and safety model (per concepts/architecture). This contradicts the common "one universal function" misconception:

Tools (most common) — Functions the model can actively call. A tool has three core fields: name / description / inputSchema; the call returns a structured result. Example: query_database(sql: string) or send_email(to: string, body: string).

Resources (data exposure) — Read-only data blocks the model can read but not "call." A resource is read-only, URI-addressed, and mime-typed. Examples: file:///logs/app.log or postgres://tables/users.

Prompts (user-triggered templates) — Not chosen by the model, but explicitly invoked by the user through /-prefixed commands. Pre-built prompt templates. Example: /review-pr expands into a full PR review template.

| Primitive | Triggered by | Side effects | Typical use | |---|---|---|---| | Tools | Model auto (matches description) | Usually side-effectful (writes DB, sends email) | Business logic calls | | Resources | Model auto (matches URI) | Read-only, no side effects | File reads, query snapshots | | Prompts | User explicit (/ command) | No side effects, pure template | Reusable workflows |

Common mistake: turning "read config" into a tool instead of a resource. Tools imply "can be called repeatedly, may have side effects" — resources signal "read data." Demoting a pure read-and-cacheable tool to a resource lets the Host batch-prefetch it.

From local to production: the transport layer and trust boundary

concepts/transports defines MCP's two transports — choosing a transport is choosing a trust model.

stdio (local default): The Host runs the server as a child process. The OS process boundary is the trust boundary — the server can access the Host user's full permissions. Zero friction for local development, no network attack surface.

Streamable HTTP (remote deployment): The server runs on a separate machine and talks to the client over HTTP POST + SSE (Server-Sent Events). Trust shifts from the OS boundary to OAuth 2.1 + Bearer Token — the server is on a public network and must explicitly authorize every call (see spec authorization and RFC 8707 Resource Indicators).

| Dimension | stdio | Streamable HTTP | |---|---|---| | Auth | None (OS process boundary) | OAuth 2.1 + Bearer | | Deployment | Must share Host's machine | Any machine, HTTPS | | Session state | In-process variables | Mcp-Session-Id header | | Performance | Fork + JSON-RPC parse | Network round-trip + TLS handshake | | Use case | Single-user local tool | Team / SaaS deployment |

Decision rule:

  • Personal / CLI / internal: stdio
  • Team-shared / SaaS / multi-Host reuse: Streamable HTTP
  • Cross-domain federation / public catalog: Streamable HTTP + MCP Registry (modelcontextprotocol/registry)

Moving stdio → HTTP is not "change the port" — it's redesigning the trust boundary. Any stdio server's "works locally" tends to fall over on OAuth, session handling, and Origin checking once remote — these are the core topics in security best practices.

The MCP ecosystem at a glance: hosts, servers, and directories (2026)

Once the protocol makes sense, step back and look at the shape of the whole ecosystem — it has three layers:

The host layer. MCP is host-agnostic: any application that speaks the protocol can call the same server. By 2026 mainstream hosts cover three forms — general chat (Claude Desktop), coding tools (Claude Code, Cursor, Zed, and more), and custom agents that embed an MCP client through the official SDKs. The same filesystem server works across all three — that is the essential difference from any single app's private plugin system.

The server layer. Most servers cluster in a few high-frequency categories: databases and data platforms, development tooling (GitHub, Sentry, project management), browser automation, cloud services and observability, plus general-purpose capabilities like filesystem access and search. The official reference implementations (modelcontextprotocol/servers) cover the basics; community servers outnumber them many times over. The first criterion for choosing a server is not feature count but least privilege — connect only the categories the current task needs, for the trust-boundary reasons covered above.

The directory and discovery layer. With thousands of servers, "where do I find one, and can I trust it" became the next problem. The official registry provides listing and discovery; third-party directories (Smithery, for example) add indexing and one-click configs. This site's resource library maintains an annotated directory across these categories, with every URL checked for availability and upstream moves before inclusion.

Five common misconceptions

Misconception 1: "an MCP server is a Claude Desktop plugin". Reality: the protocol is host-agnostic (see the ecosystem above). The same server can be called by chat apps, IDEs, CLIs, and your own programs. Designing a server "for one host" is the classic short-sighted move.

Misconception 2: "resources are for the model to read". Reality: tools are model-controlled (the model decides when to call them) while resources are application-controlled (the host decides what to inject into context). Shipping data as a tool that should be a resource flips the permission direction from "the user provides" to "the model asks".

Misconception 3: "one server equals one tool". Reality: a server can aggregate many tools, resources, and prompts — the GitHub server ships dozens, from reading issues to opening PRs. Granularity should follow deployment and permission boundaries, not tool counts.

Misconception 4: "with MCP, integrations are secure". Reality: MCP standardizes communication, not authorization. What credentials the server holds and which data it can reach still need least-privilege configuration, and remote servers add a whole OAuth checklist (see the authorization guide).

Misconception 5: "servers must be written in TypeScript". Reality: official SDKs cover TypeScript, Python, Go, Kotlin, Rust, C#, Swift, and Java. Use whichever stack your team knows best — the protocol is language-agnostic JSON-RPC.

Frequently asked questions

Is the Model Context Protocol free to use?

Yes. MCP is an open standard released by Anthropic under a permissive license. The specification and the official TypeScript and Python SDKs are open source, and anyone can build MCP-compatible servers or clients without paying a fee.

Do I have to use Claude to call an MCP server?

No. MCP is client-agnostic. Any host that speaks the protocol — Claude Desktop, Claude Code, Cursor, Zed, or a custom agent you build with the SDKs — can call the same MCP server without changes to the server code.

What is the difference between MCP and function calling?

Function calling is a model capability for emitting structured requests; MCP is an integration protocol that standardizes how hosts discover servers, how servers describe their tools, and how results flow back. When Claude calls an MCP tool it still uses function calling internally — MCP provides the plumbing that connects many servers to many hosts.

How is data sent between the host and an MCP server?

MCP uses JSON-RPC 2.0 messages carried over a transport. The two common transports are stdio, where the host spawns the server as a subprocess and communicates over stdin/stdout, and HTTP with Server-Sent Events, used when the server runs remotely. Local development almost always uses stdio.

Can MCP resources be non-text (images, PDFs, audio)?

Yes. The mimeType field on a resource accepts standard MIME values like image/png, image/jpeg, application/pdf, text/* and more. After resources/read, the client renders base64 contents. Multimodal content (screenshots, scans) can also flow back through tool return content arrays. Key constraint: JSON-RPC 2.0 caps a single message at a reasonable size (typically tens of MB), so for PDFs and images, upload via the Files API and pass a file_id rather than embedding base64 directly.

Can a single project mix stdio and HTTP MCP servers?

Yes. A Host config can mix transports: filesystem on stdio, Slack on remote HTTP. The client is unaware of the transport — it sees a uniform JSON-RPC interface. Caveat: each server has an independent session and they don't interfere. But watch the total token budget — the tools/list of 20+ servers occupies a few thousand tokens in the system prompt; once it exceeds the Host's listing budget, low-priority entries get folded or truncated.

Official references

This article is current as of the MCP 2025-11-25 specification (August 2026). The spec evolves; check the version number every six months.