This tutorial covers the reference Python stack: FastAPI, Pydantic models for tool contracts, and the Atlas tracker SDK. We focus on the sales comps tool so you can see inputs, outputs, budgets, and consent checks in action.
Project setup
Create a virtualenv and install FastAPI plus the Atlas SDK. Define Pydantic models for Tool, InputField, OutputField, and ConsentScope.
uv venv venv && source venv/bin/activate
pip install fastapi uvicorn atlas-mcp-sdkDescribe the tool contract
Declare the GenerateSalesComps tool with the contract fields from lib/constants/knowledge. Include cost and latency hints so clients can budget.
class GenerateSalesComps(Tool):
name: str = "generate_sales_comps_pdf"
version: str = "1.0.0"
inputs: list[InputField] = [
InputField(key="subject_address", type="string", required=True),
InputField(key="beds", type="int", required=True),
InputField(key="baths", type="int", required=True),
InputField(key="sqft", type="int", required=True),
InputField(key="radius_miles", type="float", required=True),
InputField(key="max_closed_months", type="int", required=True),
]
outputs: list[OutputField] = [
OutputField(key="artifact_uri", type="string"),
OutputField(key="summary", type="string"),
]
consent_scopes: list[str] = ["mls.read", "atlas.data"]
cost_hint_usd: float = 0.75
latency_hint_ms: int = 2500Wire tracker & guard
Use the Atlas tracker client to run preflight checks before calling downstream vendors. If the call passes, execute your business logic, then send a signed usage event with costs, tokens, and artifact URIs.
tracker = TrackerClient(api_key=os.environ["ATLAS_TRACKER_KEY"])
@app.post("/tools/generate_sales_comps_pdf")
async def generate_sales_comps(request: ToolRequest):
preflight = tracker.preflight(tool_name="generate_sales_comps_pdf", actor=request.actor, inputs=request.inputs)
if not preflight.allowed:
raise HTTPException(status_code=429, detail=preflight.reason)
result = await run_comp_job(request.inputs)
tracker.postflight(
event_id=preflight.event_id,
tool_name="generate_sales_comps_pdf",
actor=request.actor,
outputs=result.outputs,
vendor_name="atlas_default",
total_cost_usd=result.cost,
artifact_uri=result.artifact_uri,
)
return resultExpose discovery endpoints
Implement GET /catalog and GET /prompts endpoints so clients can list the available tools. Use caching headers since these responses rarely change.
Test with Atlas clients
Point VS Code or the Atlas Bot at your local server URL. Watch the tracker dashboard to confirm preflight and postflight events land with the correct consent scopes.