CHAPTER 10 · Skills, MCP, and Deterministic Computation · 6 / 8
Code MVP: skills and a mini MCP
"""
chapter 10: skills, MCP, and deterministic computation.
SkillLoader: progressive disclosure (descriptions up front, body on demand).
MiniMCPClient: list tools from a server and register them (deferred schemas).
A deterministic 'compare' tool shows the anti-hallucination contract.
"""
import os, re
# ---------- Skills ----------
class SkillLoader:
def __init__(self, skills_dir: str):
self.dir = skills_dir
self.index = {} # name -> (description, path)
self._scan()
def _scan(self):
if not os.path.isdir(self.dir):
return
for fn in os.listdir(self.dir):
if fn.endswith(".md"):
path = os.path.join(self.dir, fn)
text = open(path, encoding="utf-8").read()
name = re.search(r"name:\s*(.+)", text)
desc = re.search(r"description:\s*(.+)", text)
key = (name.group(1).strip() if name else fn)
self.index[key] = (desc.group(1).strip() if desc else "", path)
def summary(self) -> str:
"""Cheap: only names + descriptions go into the prompt at startup."""
return "\n".join(f"- {n}: {d}" for n, (d, _) in self.index.items())
def load_body(self, name: str) -> str:
"""Expensive: the full skill body, fetched ONLY when invoked."""
_, path = self.index[name]
return open(path, encoding="utf-8").read()
# ---------- A tiny MCP-style server/client ----------
class MiniMCPServer:
"""Pretend external server exposing tools (e.g. a data service)."""
def list_tools(self):
return [{"name": "compare_data",
"description": "Exactly diff two lists of numbers",
"parameters": {"type": "object",
"properties": {"a": {"type": "array"},
"b": {"type": "array"}},
"required": ["a", "b"]}}]
def call(self, name, **args):
if name == "compare_data":
# DETERMINISTIC: code computes the truth; the model never guesses it.
a, b = args["a"], args["b"]
diffs = [{"index": i, "a": x, "b": y, "delta": y - x}
for i, (x, y) in enumerate(zip(a, b)) if x != y]
return {"differences": diffs, "count": len(diffs)}
class MiniMCPClient:
def __init__(self, server): self.server = server
def register_into(self, registry, Tool):
for spec in self.server.list_tools(): # discover (deferred schema)
registry.register(Tool(
name=f"mcp__data__{spec['name']}",
description=spec["description"],
parameters=spec["parameters"],
handler=lambda _n=spec["name"], **a: self.server.call(_n, **a)))
if __name__ == "__main__":
os.makedirs("/tmp/skills", exist_ok=True)
open("/tmp/skills/investigate.md", "w").write(
"---\nname: investigate\ndescription: Trace a value across backends\n---\n"
"## Steps\n1. Run fetch_data.py\n2. Run compare_data.py\n3. Write a report\n")
sl = SkillLoader("/tmp/skills")
print("startup (cheap):", sl.summary())
print("on demand (full body):\n", sl.load_body("investigate")[:80], "...")
# MCP: register a deterministic tool and call it.
server = MiniMCPServer()
print("\ndeterministic compare:",
server.call("compare_data", a=[1, 2, 3], b=[1, 9, 3]))
Run it: at startup you pay only for the one-line skill description; the full body loads only when asked. The MCP server's compare_data computes the exact diff in code, so the model interprets {"differences": [...], "count": 1} instead of squinting at raw numbers and possibly inventing one. That is the anti-hallucination contract in working form.