Lab 04 — Wire up your first MCP tool
Lesson 04 · MCP Servers · Lab Guide
Goal: end the lab with the pkb server running, connected to Claude
Desktop, and successfully calling pkb.echo once.
Prereqs
- Plan A's Lesson 03 lab is complete (PKB skeleton installed via
pip install -e .). mcp[cli]is installed in your active virtualenv.- Claude Desktop is installed and has been launched at least once (so the config directory exists).
Step 1 — Update pkb/server.py
Replace the L03 placeholder body with the FastMCP version. Open
mcp-servers/sample-server/python/pkb/server.py and make it look like this:
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("pkb", version="0.1.0")
@mcp.tool()
def echo(message: str) -> str:
"""Echo the message back."""
return message
def main() -> None:
mcp.run()
if __name__ == "__main__":
main()
What changed, line by line, vs the L03 raise SystemExit(...) placeholder:
- Import. Pull in
FastMCPfrommcp.server.fastmcp— the high-level wrapper that builds schemas from your function signatures. - Instantiate.
mcp = FastMCP("pkb", version="0.1.0")creates the server object. The first argument is the server name advertised over the wire; the version is what Claude Desktop's UI displays. - Decorate
echo.@mcp.tool()reads the signature (message: str), the docstring ("Echo the message back."), and the return type (str), and registers a complete schema-checked tool with no extra boilerplate. - Replace
main(). The L03 placeholder raisedSystemExit; the L04 body callsmcp.run(), which starts the stdio JSON-RPC loop that Claude Desktop speaks to. - Module-level symbol. L03 exposed a low-level
serverobject built frommcp.server.Server. L04 exposesmcp(aFastMCPinstance) instead. The[project.scripts]entry inpyproject.tomlstill points atpkb.server:main, so thepkbshim keeps working without any package metadata change.
Step 2 — Reinstall in editable mode
cd mcp-servers/sample-server/python
pip install -e .
Because you installed in editable mode in L03, the pkb shim already follows your edits
to server.py. Reinstalling is harmless when only the script body changes (no
[project.scripts] change), but it is a safe habit — it catches any drift in
pyproject.toml immediately and confirms the environment is still healthy.
Step 3 — Smoke-test with mcp dev
mcp dev pkb/server.py
This launches your server under the MCP Inspector. Open the URL it prints (a local
http://127.0.0.1:… address). In the Inspector UI:
- Connect to the server (it should auto-connect via stdio).
- Open the Tools tab —
echonow appears in the list. - Click
echo. The form on the right is generated from the JSON Schema FastMCP built from your signature. - Enter
{"message": "hi"}and send the call. - Expected: the response panel shows a
TextContentblock containing the string"hi".
If you see that, the protocol layer works end to end. Stop the Inspector (Ctrl-C) before moving on.
Step 4 — Wire to Claude Desktop
Open claude_desktop_config.json:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%/Claude/claude_desktop_config.json
Add the PKB entry alongside any existing servers from L01:
{
"mcpServers": {
"pkb": { "command": "pkb" }
}
}
If the file already has other entries under mcpServers, merge the "pkb" key
into the existing object rather than overwriting it. Save the file, then fully quit
Claude Desktop (Cmd-Q / right-click → Quit — closing the window is not enough) and reopen it.
The PKB server should appear in the tool tray with one tool, echo.
Step 5 — Call from Claude
In a fresh Claude Desktop chat, ask:
"use the pkb echo tool with message hello from PKB"
Watch the tool call appear in the chat. Claude Desktop may show a permission prompt the first time —
approve it. You should then see the echoed response ("hello from PKB") returned as the
tool result, with Claude composing a short natural-language reply around it.
What you should leave with
- A running PKB server with one registered tool (
echo). - The tool successfully called from both the MCP Inspector (Step 3) and Claude Desktop (Step 5).
- A working mental model of the path: edit
server.py→ reinstall → smoke-test in Inspector → restart Claude Desktop → call from chat.
Troubleshooting
pkb: command not found— runpip install -e .again frommcp-servers/sample-server/python. If that does not help, deactivate and reactivate your virtualenv so the shell picks up the newPATHentry.- Tool not appearing in Claude Desktop — the config is read once at startup. Fully Quit Claude Desktop (not just close the window) and reopen. On macOS, use Cmd-Q or right-click the dock icon → Quit.
- Inspector says capability error — your
mcp[cli]version is likely out of date. Upgrade withpip install --upgrade 'mcp[cli]'and rerunmcp dev pkb/server.py.