Stop 2 of 10 · Weekly
The account registry and its MCP server
One file that knows what every account is, wrapped in a read-only MCP server so every Project and every agent reads the same truth.
The file the whole agency argues about
Ask five people at Nour's agency for A14's GA4 property id and you get three answers, a screenshot and a Slack thread from March. Every system in this course needs the same facts, so they live in one place: accounts.yaml, in the repository, with a schema test.
| Field group | What it holds |
|---|---|
| Identity | Account code, client name, industry, owner, start date |
| Platform ids | Google Ads customer id, Meta ad account id, GA4 property id |
| Policy | Monthly budget cap, maximum change per run, terms this client never bids on |
No spend. No margin. No retainer. Those live in the finance system, and stop nine reads them there. The registry answers what an account is, not what it earns.
Why a server rather than a file
Rafik can read the file. Claude cannot, unless you upload it into every chat and keep uploading it every time it changes. An MCP server solves that once: it is a small program that offers a named set of tools, and Claude calls them when it needs a fact. The protocol and the server SDKs are documented at modelcontextprotocol.io, and the ways to connect one to Claude, as a custom connector or through Claude Code, are at docs.claude.com. Read both before you write, because the transport options and the connector settings move faster than any course.
Four tools, all read-only:
- list_accounts, returning code, client name, industry and owner
- get_account, taking a code and returning the identity and policy fields
- get_platform_ids, taking a code and returning the three ids
- find_accounts, taking an industry or an owner and returning matching codes
Write an MCP server in Python over accounts.yaml for our paid media agency. Follow the current server SDK documented at modelcontextprotocol.io and tell me which version you used. Expose exactly four tools: list_accounts, get_account(code), get_platform_ids(code) and find_accounts(industry=None, owner=None). Every response is built from an explicit field allowlist defined in one constant at the top of the file. There is no tool that writes, no tool that runs a query I supply, and no path that reads a file other than accounts.yaml. Also write accounts.yaml with a schema comment and one fixture account, A00, whose values are obviously fake. Then write test_registry.py: every tool returns only allowlisted fields, no tool response contains a key matching spend, margin, retainer or cost, get_account raises a clean error for an unknown code, and the module exposes no function that opens a file for writing. Run the tests.
Connecting it
Once it runs, the same server serves the Project chats, Claude Code and every agent in the stops that follow. That is the point: the audit assistant in stop four and the report writer in stop three both ask the registry rather than carrying their own copy of the ids.
Using the account registry tools, give me everything you know about A00, then list every account owned by Nour, then tell me which of the four tools you called and which fields came back. If any tool returns a field I did not ask for, say so.
Write test_registry_schema.py, run in CI on every commit. Assert that accounts.yaml parses, that every account has all identity, platform id and policy fields, that codes match the pattern A followed by two digits and are unique, that budget cap and maximum change per run are positive numbers, and that no key anywhere in the file matches spend, margin, retainer or fee. Show me the failure message for an account missing a GA4 property id, since that is the mistake I will actually make.