Objective
What you're building
Nothing new gets written today — you configure Claude Desktop to run a reference filesystem MCP server (shipped by the MCP project itself), verify it works, and read the actual JSON-RPC traffic between Claude and the server. Lesson 2 is where you write your first tool.
The three-way architecture, and why it exists
MCP has three parties: a host (Claude Desktop, or Claude Code, or Cursor — the application the user is in), a client inside that host (one per server connection, handling the protocol), and a server (the thing you build, exposing tools/resources/prompts). Before MCP, if you wanted Claude to use your database, you wrote a tool schema and a handler directly into your own application's API calls — fine for one app, but that tool schema didn't transfer to Cursor, or to a teammate's Claude Desktop, or to next year's version of your own app.
MCP standardizes the wire format, not your logic
Your tool's Python code doesn't change based on who's calling it. What MCP standardizes is the JSON-RPC envelope around it — how tools are listed, how they're called, how results and errors come back — so any MCP-aware host can talk to any MCP server without custom integration code. This is the same value proposition USB had over a decade of proprietary connectors: one interface, many devices.
Two transports, and which one you'll use
MCP servers talk over stdio (the server is a local subprocess, communicating over stdin/stdout — what Claude Desktop uses for local servers) or SSE/HTTP (the server is a long-running network service, for when you want to deploy it somewhere and let multiple clients connect remotely). This course builds a stdio server throughout, because that's what Claude Desktop expects for local tools and it's the simpler mental model to start with — Section 6 briefly covers what changes if you later deploy the same server over SSE.
{
"mcpServers": {
"reference-filesystem": {
"command": "uvx",
"args": ["mcp-server-filesystem", "/Users/you/Documents"]
}
}
}
This goes in claude_desktop_config.json. Restart Claude Desktop after editing it, and you should see a small hammer/tools icon appear in the chat input — that's Claude telling you it sees at least one MCP server's tools. If it doesn't appear, the two most common causes are a relative path where an absolute one is required, or a typo in the command Claude Desktop tries to spawn as a subprocess.
The #1 failure mode: "0 tools" with no error message
Claude Desktop is not verbose about MCP failures — a bad config often just shows the server as connected but exposing zero tools, with the actual reason buried in a log file (~/Library/Logs/Claude/mcp*.log on macOS, %APPDATA%\Claude\logs on Windows). The single highest-value habit this lesson teaches: whenever something doesn't show up as expected, go read that log file before assuming your code is broken. Almost every "0 tools" report traces back to either a relative path in the config or the wrong Python/uv executable being on the PATH Claude Desktop's subprocess sees (which is not necessarily your shell's PATH).
Tools, resources, prompts — the three primitives
MCP defines three kinds of things a server can expose: tools (the model can call these to take an action — the equivalent of the tool-use pattern), resources (read-only data the host can attach to context, like a file or a data view — the model doesn't "call" these, the host fetches and includes them), and prompts (reusable prompt templates the user can invoke, parameterized). Most tutorials only cover tools — this course builds all three, because knowing when a resource is the right primitive instead of a tool is a real design decision, not a footnote.
You want to give Claude read access to your project's changelog file so it always has that context available without you pasting it in every conversation. Should this be a tool or a resource?
Resources are for exactly this case: standing data that should be available as context, not an action the model takes. Modeling it as a tool would work mechanically, but it puts the burden on the model to remember to call it every time, when the actual intent is "this should just be there." Section 4 builds a real resource so you can feel this distinction rather than just read about it.
Read the logs
Install uv if you don't have it, run the reference filesystem server config above, restart Claude Desktop, and open the MCP log file. You'll see the actual initialize, tools/list, and tools/call JSON-RPC messages — the exact protocol Lesson 2's server will need to implement (mostly handled for you by the SDK, but seeing it once matters).