Claude Academy
Sign in

Vault / course/courses/introduction-to-mcp.md

updated 2026-06-25

Course: Introduction to Model Context Protocol

Mirrors: Anthropic Academy — Introduction to Model Context Protocol · https://anthropic.skilljar.com/introduction-to-model-context-protocol Audience: Developers. Comfortable with Python and JSON. · Time: ~75 min + project Prereqs: Python 3.10+, API basics, a terminal. · Backing notes: mcp-overview, mcp-tools, mcp-resources, mcp-prompts, mcp-server-python, mcp-transports Project: p12-build-an-mcp-server

MCP is the open standard that lets Claude plug into your systems — files, databases, APIs, internal tools — without you re-implementing tool plumbing for every app. By the end you can explain why MCP exists, name its three primitives and who controls each, and build and wire up a working Python server.

Learning objectives

After this course you can:

  • Explain the M×N integration problem MCP solves (the "USB-C for AI tools" pitch).
  • Diagram the architecture: host, client, server, and the JSON-RPC connection between them.
  • Distinguish the three server primitives — tools, resources, prompts — by who controls each.
  • Pick the right transport (stdio vs Streamable HTTP) for a deployment.
  • Build a server in Python with FastMCP exposing one tool, one resource, and one prompt.
  • Wire that server into Claude Code via a .mcp.json file and call it.

Module 1 — Why MCP exists

🎞 Frame 1 · The M×N integration problem · ⏱ ~3 min

🎬 Scene — A grid fills the screen: M AI apps down the side, N tools across the top. Every cell is a custom integration someone has to write and maintain.

🧠 Concept — Before MCP, every AI application wired up every tool with bespoke glue code. M apps × N tools = M×N integrations. MCP turns that into M + N: each app speaks MCP once, each tool exposes MCP once, and they all interoperate.

🖼 On screen

Without MCP:  Claude Desktop ──┐
              Cursor ──────────┼── each writes its own
              your app ────────┘   Slack + GitHub + Postgres + ... glue

With MCP:     any MCP host ──→ [MCP] ──→ any MCP server
              write the connector ONCE on each side

Checkpoint — Why is "M + N" dramatically better than "M × N" as the tool ecosystem grows?

🎞 Frame 2 · USB-C for AI tools · ⏱ ~2 min

🎬 Scene — A laptop with one USB-C port; monitors, drives, and chargers all plug into the same connector.

🧠 Concept — MCP is a standard connector, not a tool. Standardize the plug and any compliant tool plugs into any compliant client. Anthropic released MCP as an open protocol in late 2024; it's now adopted broadly. (Deeper: mcp-overview.)

🖼 On screen

AspectRaw API tool useMCP
Where the tool livesIn your app codeIn a separate server
ReusabilityPer-appAny MCP-aware client
DiscoveryHardcodedServer advertises capabilities
EcosystemNoneGrowing registry (Slack, Linear, Postgres…)

Checkpoint — In one sentence, what does standardizing the "connector" buy a tool author?

🎞 Frame 3 · Two layers: data and transport · ⏱ ~2 min

🎬 Scene — A diagram splits into an inner ring ("what is said") and an outer ring ("how it travels").

🧠 Concept — MCP separates what from how. The data layer is JSON-RPC 2.0 (lifecycle, primitives, notifications). The transport layer (stdio or Streamable HTTP) just carries those messages. Same message format on every transport.

🖼 On screen

Data layer      → JSON-RPC 2.0: initialize, tools/call, resources/read, prompts/get …
Transport layer → stdio (local subprocess)  |  Streamable HTTP (remote service)

Checkpoint — If you switch a server from stdio to Streamable HTTP, do the JSON-RPC messages change? (No — only the transport.)


Module 2 — Architecture and the three primitives

🎞 Frame 4 · Host, client, server · ⏱ ~3 min

🎬 Scene — A host application (Claude Code) holds several "client" sockets, each running a dedicated wire to a different server.

🧠 Concept — Three roles: the host is the AI app, it spins up one client per connection, and each client talks to exactly one server. A host can run many clients at once. (Deeper: mcp-overview.)

🖼 On screen

flowchart TB
    subgraph Host["MCP Host (e.g. Claude Code)"]
        C1[MCP Client 1]
        C2[MCP Client 2]
    end
    SA["Server A (local, stdio)<br/>Filesystem"]
    SB["Server B (remote, HTTP)<br/>GitHub"]
    C1 -- dedicated connection --> SA
    C2 -- dedicated connection --> SB

Checkpoint — How many servers does a single MCP client connect to? (Exactly one — the host runs one client per server.)

🎞 Frame 5 · Tools — model-controlled · ⏱ ~3 min

🎬 Scene — Mid-conversation, Claude decides on its own to call search_tickets and shows the result inline.

🧠 ConceptTools are actions the model chooses to invoke. They can have side effects. Each has a name, a description that teaches when to use it, and a JSON input schema. (Deeper: mcp-tools.)

🖼 On screen

Tool(
    name="search_tickets",
    description="Search Linear tickets by query. Use when the user asks about tickets, issues, or bugs.",
    inputSchema={
        "type": "object",
        "properties": {"query": {"type": "string"}},
        "required": ["query"],
    },
)

⚠️ Gotcha — A vague description makes the model pick the wrong tool. Say when to use it and when not to.

Checkpoint — Who decides a tool runs — the user, the host, or the model? (The model.)

🎞 Frame 6 · Resources — application-controlled · ⏱ ~3 min

🎬 Scene — A picker UI lists "Users table", "design.md", "current screenshot"; the user attaches one as context.

🧠 ConceptResources are read-only data identified by a URI (file://…, postgres://…). Claude doesn't "call" a resource; the host application surfaces them and the user/app attaches them to context. No side effects. (Deeper: mcp-resources.)

🖼 On screen

Resource(
    uri="postgres://main/users",
    name="Users table",
    description="Production users; PII redacted on read.",
    mimeType="application/json",
)

Checkpoint — "Get me X, no decision required" → resource or tool? (Resource.)

🎞 Frame 7 · Prompts — user-controlled · ⏱ ~2 min

🎬 Scene — The user types /review_pr and a slash-command menu pops up offering a pr_url argument.

🧠 ConceptPrompts are parameterized message templates the user invokes, usually as slash commands. The server returns ready-to-send messages, often pre-filled with data (e.g., the PR diff). (Deeper: mcp-prompts.)

🖼 On screen

PrimitiveDecided bySurfaced as
ToolsModelTool calls in conversation
ResourcesApplication / hostAttached context, picker UI
PromptsUserSlash command menu

Checkpoint — Without looking, match each primitive to who controls it. (Tools→model, Resources→app, Prompts→user.)


Module 3 — Transports

🎞 Frame 8 · stdio: the local default · ⏱ ~2 min

🎬 Scene — The host launches the server as a subprocess; messages flow over stdin/stdout.

🧠 Conceptstdio is for servers that run as a local subprocess of the client (Claude Code, Claude Desktop). No ports, no auth — easiest dev experience. (Deeper: mcp-transports.)

⚠️ Gotcha — With stdio, stdout is the wire. Never print() from the server; log to stderr or you corrupt the protocol.

Checkpoint — Why must a stdio server avoid printing to stdout?

🎞 Frame 9 · Streamable HTTP: the remote standard · ⏱ ~2 min

🎬 Scene — A cloud-hosted server serves a fleet of users behind one HTTP endpoint.

🧠 ConceptStreamable HTTP is the current standard for remote servers. A single HTTP endpoint; requests are POSTed, responses can be JSON or an SSE stream. Supports sessions and OAuth. (SSE is the legacy variant it supersedes.)

🖼 On screen

TransportLocalRemoteMulti-clientAuth
stdioNo
Streamable HTTP⚠️Yes

Checkpoint — You must expose an internal server to many users without each installing it. Which transport? (Streamable HTTP, with OAuth.)

🎞 Frame 10 · Local vs remote is about transport · ⏱ ~2 min

🎬 Scene — Two servers, same code; one labeled "local", one "remote" — the only difference is how they're connected.

🧠 Concept — "Local" vs "remote" is decided by transport, not where the code physically runs. stdio ⇒ local subprocess; Streamable HTTP ⇒ remote service.

Checkpoint — What single property determines whether an MCP server is "local" or "remote"? (Its transport.)


Module 4 — Build and wire up a server

🎞 Frame 11 · FastMCP: server in 15 lines · ⏱ ~3 min

🎬 Scenepip install mcp, a handful of decorators, and a working server appears.

🧠 Concept — The high-level FastMCP API hides the JSON-RPC boilerplate. A decorated function's name + docstring become the primitive's name + description; type hints become the JSON schema. (Deeper: mcp-server-python.)

🖼 On screen

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("hello-mcp")

@mcp.tool()
def echo(text: str) -> str:
    """Echo a string back. Use to verify the server is reachable."""
    return text

@mcp.resource("file://greeting")
def greeting() -> str:
    """A static greeting."""
    return "Hello, world!"

@mcp.prompt()
def summarize(text: str) -> str:
    """Produce a summary prompt."""
    return f"Summarize:\n\n{text}"

if __name__ == "__main__":
    mcp.run()

Checkpoint — Where does FastMCP get a tool's description from? (The function's docstring.)

🎞 Frame 12 · One tool, one resource, one prompt · ⏱ ~3 min

🎬 Scene — The three decorators above are highlighted in turn, each labeled with who controls it.

🧠 Concept — A complete starter server exposes exactly one of each primitive so you internalize the difference: @mcp.tool() (model-controlled action), @mcp.resource() (app-controlled read), @mcp.prompt() (user-controlled template).

🖼 On screen

@mcp.tool()      → model invokes        → can have side effects
@mcp.resource()  → user/app attaches    → read-only, URI-addressed
@mcp.prompt()    → user runs (slash)    → returns seed messages

Checkpoint — Which of the three would you reach for to let Claude write a row to a database? (A tool.)

🎞 Frame 13 · Wire it into Claude Code with .mcp.json · ⏱ ~3 min

🎬 Scene — A .mcp.json file at the repo root; Claude Code restarts and the new tools appear.

🧠 Concept — Claude Code reads a .mcp.json at the project root listing servers under mcpServers. For a local stdio server you give the command and args to launch it; project-scoped config is committed so the whole team gets the server.

🖼 On screen

{
  "mcpServers": {
    "hello": {
      "command": "python",
      "args": ["server.py"]
    }
  }
}

🛠 Try it now — Add the block above, run claude, and ask Claude to call the echo tool. Use npx @modelcontextprotocol/inspector python server.py to poke the server directly if it doesn't show up.

Checkpoint — What file tells Claude Code which MCP servers to launch, and what's the top-level key? (.mcp.json, key mcpServers.)


🛠 Project

Complete p12-build-an-mcp-server — Build Your First MCP Server. You'll write a FastMCP server in Python exposing one tool, one resource, and one prompt; register it in a project .mcp.json; and verify each primitive from both the MCP Inspector and Claude Code.

🧪 Self-check quiz

  1. State the integration problem MCP solves, in "M×N → M+N" terms.
  2. Name the three roles in MCP architecture.
  3. For each of tools / resources / prompts, who controls invocation?
  4. Which transport is the standard for remote servers? Which for local subprocesses?
  5. Why must a stdio server never write to stdout?
  6. In FastMCP, where does a tool get its name and description?
  7. What file wires a server into Claude Code, and what is its top-level key?
  8. "User wants to attach the latest churn report as context." Which primitive?
<details><summary>Answers</summary>
  1. Every app re-implements every tool (M×N); MCP standardizes the connector so each side implements it once (M+N). 2. Host, client, server. 3. Tools→model, resources→application/host, prompts→user. 4. Streamable HTTP for remote; stdio for local. 5. stdout is the JSON-RPC wire; printing corrupts it — log to stderr. 6. The function's name and docstring (type hints become the schema). 7. .mcp.json, key mcpServers. 8. A resource.
</details>

🎓 Certificate criteria

You've "passed" Introduction to MCP when you can:

  • Explain the M×N problem and the host/client/server architecture without notes.
  • State who controls each of the three primitives.
  • Choose stdio vs Streamable HTTP for a given deployment and justify it.
  • Complete p12-build-an-mcp-server with one working tool, resource, and prompt wired into Claude Code via .mcp.json.

Tick this course off in progress and record the date you earned Anthropic's official certificate.

🔗 Sources & deeper notes