ClaudeMap

·MCP Servers

A practical walkthrough of the Model Context Protocol (MCP) — what it solves, how it is structured, and how to build a working MCP server in TypeScript that Claude can call.

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

The Model Context Protocol (MCP) is an open standard that Anthropic open-sourced in November 2024 for connecting AI assistants to external tools, data sources, and services. If you have ever wired a tool into a chatbot by hand and then re-wired the same tool into a different chatbot, you already understand the problem MCP exists to solve. This guide explains the protocol, walks through its vocabulary, compares it to function calling, and ends with a working TypeScript server you can run locally and connect to Claude Desktop.

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 prompts with server.prompt(...) to ship reusable slash-command-style templates.
  • Switch transports to HTTP+SSE when you want the server to run remotely instead of being spawned per session.
  • Browse the ecosystem — ClaudeMap charts dozens of MCP servers (filesystem, GitHub, Postgres, browsers, and more) that you can install and study as reference implementations.

Start small with one tool, confirm it round-trips through the Inspector, then connect it to a host. The protocol is intentionally narrow, so the distance from "hello world" to "useful server" is short.

This article is based on publicly available information as of July 2026; the relevant APIs may evolve.