The mechanism
Build the smallest useful capability before introducing databases, credentials or model calls. Our lookup accepts an exact incident ID and returns a copied synthetic record. A tool decorator supplies the protocol-facing description, while ordinary Python remains responsible for business validation.
The current official Python tutorial uses MCPServer from mcp.server. This is version-sensitive: older examples often import another server class. Follow the package and runtime prerequisites in the linked current tutorial and record the installed version. This handbook has not installed or executed that SDK example.
A read-only fixture lets you reason about behavior without granting system access. It does not prove authenticated multi-tenant operation. Add that later at the data boundary rather than hiding permission decisions inside the prompt.
Worked example
Optional SDK example; not executed here. Save as parcelops_server.py inside a disposable project after following the official installation instructions. It performs no model calls and has no external backend. Use the current compatible Inspector or your approved host to exercise it; avoid copying legacy connection recipes into the modern path.
from mcp.server import MCPServer
server = MCPServer("parcelops-study")
RECORDS = {"INC-104": {"status": "delayed", "revision": 7}}
def lookup(incident_id: str) -> dict:
if not incident_id.startswith("INC-") or not incident_id[4:].isdigit():
raise ValueError("Expected an incident ID such as INC-104")
record = RECORDS.get(incident_id)
return {"id": incident_id, "found": record is not None,
"record": dict(record) if record else None}
@server.tool()
def lookup_incident(incident_id: str) -> dict:
"""Read one synthetic incident; never modifies incident state."""
return lookup(incident_id)
if __name__ == "__main__":
server.run(transport="stdio")
Practice: predict, inspect, explain
Offline exercise. Extract lookup and RECORDS into a plain Python scratch file. Assert that INC-104 is found, INC-999 is absent and a malformed identifier raises ValueError. Mutate the returned record and verify the fixture stays unchanged. The downloadable capstone repeats these deterministic checks without installing the SDK.
Expected observation: the pure function has a precise contract before a model sees it. Optional SDK testing should separately verify discovery, the generated input schema, tool invocation and clean shutdown. Record those as not run until actually observed.
Troubleshooting and trade-offs
An import error commonly means the tutorial and installed SDK do not match. Check the package version rather than substituting imports blindly. Type hints improve generated schemas but do not establish object permissions. Missing and forbidden objects may need indistinguishable responses in a real service to avoid leaking existence; decide that policy with the data owner.
Interview practice
Why return a copied record?
It prevents a caller from mutating the in-memory fixture through a shared dictionary. Real systems require equivalent protection at their actual persistence boundary.
What remains untested after lookup unit tests?
Protocol handling, SDK schema generation, host compatibility, authentication, authorization, transport behavior and model selection. Each requires separate evidence.
Completion check
Pass existing, missing, malformed and copy-isolation cases, then identify which integration tests remain unrun.
Sources and version notes
This edition targets MCP 2026-07-28, checked 6 October 2026. SDK examples are version-sensitive and labelled when not executed. Synthetic fixtures are learning material, not protocol conformance evidence.
Make the understanding yours.
Use the completion check above. Mark this chapter when you can explain the mechanism and its limits.
Self-assessed reading progress. This does not certify that a lab ran or a system is secure.