Chapter 2 · Part 1

A server in 15 lines

Enough theory — let's build one. The SDK's FastMCP does all the protocol work; you write plain Python functions and decorate them. Create server.py:

server.py
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("Demo")


@mcp.tool()
def add(a: int, b: int) -> int:
  """Add two numbers."""
  return a + b


if __name__ == "__main__":
  mcp.run(transport="streamable-http")

That is a complete, working MCP server. Look at what you didn't write: no JSON Schema, no request parsing, no validation, no protocol handling. The type hints a: int, b: int are the schema, and the docstring is the tool's description that the AI reads.

Run it

Terminal
python server.py

The server starts listening (by default on http://localhost:8000/mcp). It's not talking to any AI yet — it's just waiting for a client to connect.

Poke at it in the Inspector

Before wiring it to Claude, test it directly with the MCP Inspector, a browser tool that acts as a client. In a second terminal:

Terminal 2
npx -y @modelcontextprotocol/inspector

It opens a UI; connect it to http://localhost:8000/mcp. You'll see your add tool listed — call it with a=1, b=2 and you get 3 back.

💡The Inspector is your best friend

Every time you add a tool, resource or prompt, the Inspector shows it immediately and lets you call it by hand — no AI, no cost, no guessing. Debug here first, connect to Claude once it works.

You have a real server exposing one tool. Next, we make the tools actually useful.