Home · Setup · Claude Code
One price list and one labour rate card, kept where the invoice and the quote can both read them, with the price on a date worked out on the call. You give a product a code, a name, a unit, an optional VAT rate and a price in minor units with the day that price comes into force, and you give a role an hourly rate the same way. Then you hand the catalogue a list of what a customer had, and it hands back the line items already priced. A SKU holds its price ROWS rather than a current price, and the price on a date is the latest valid-from at or before it, worked out on the call, so putting a price up in July does not rewrite what June was quoted at, and sku_get names the row it picked, how many rows it considered and any later row already booked, which turns a question about a figure on an old invoice into one line of one file rather than an argument. A date before every row has no price and that is a refusal naming the earliest row and the day it starts, because filling it with the earliest row reprices history: a job done in December 2024 would be billed at the January 2025 price and would reconcile perfectly against a price list that did not exist yet. One row per currency, tier and valid-from date, and setting that key again REPLACES the row and says what it was and what it became, because two rows on one key make the price that day a coin toss decided by array order. Nothing is invented: no fallback, no profile default rate, no nearest match. An unknown code, or a code with no price in the currency and tier you asked for, is refused by name, because the invented number would be printed on a document a customer pays from. It creates no invoice and no quote of its own: lines_resolve returns the arguments and says posted false, and you run invoice_create in the invoice server or quote_create in the quotes server.
`claude mcp add catalogue` at user scope is the level that matches both the meter and the data: 25 SKUs is a business's catalogue rather than a repository's, and the store is one directory per machine anyway. It also has to sit at the same scope as mcp-invoice and mcp-quotes, because the point of this server is that all three read one price list, and a catalogue added at project scope would price lines nothing else can see.
| You say | Tool |
|---|---|
| Add WEB-AUDIT, a fixed price site audit, 45,000 minor units from 2026-01-01, VAT 23 percent. | sku_set |
| What was WEB-AUDIT priced at on 2026-03-15, and is there a later price already booked? | sku_get |
| Senior developer 8,500 an hour and junior 4,500 from 2026-01-01. Then price three audits, twelve months of HOST-MO, seven and a half senior hours and three and a quarter junior hours as of 2026-03-15. | lines_resolve |
The two servers this catalogue feeds take the same price in different scales, and the gap is exactly 100x. invoice_create's item carries unit_price in MAJOR units, 90 for 90 EUR. quote_create's item carries unit_price_minor in MINOR units, 9000 for 90.00 EUR. Both fields are plain numbers, both are called the unit price, and neither tool can tell that the number it was handed was scaled for the other one: 45000 passed as unit_price is a perfectly valid invoice line for EUR 45,000.00, and it reconciles against itself. The unit suite measures the gap on the worked resolution: the correct payload nets 261,363 minor units, and the quote payload's field fed into the invoice engine nets 26,136,300, asserted as exactly 100x, and 1000x in a 3-decimal currency such as KWD. So the store holds MINOR units, which is the only lossless form, and lines_resolve builds BOTH payloads itself in one call with the scale printed against each. A catalogue that returned the price and let the caller choose the field would be wrong half the time, and wrong by two orders of magnitude when it was.
The file is .mcp.json, and the key inside it is mcpServers.
| Scope | Path |
|---|---|
| local (default) | ~/.claude.json, this project only |
| project | .mcp.json at the repository root |
| user | ~/.claude.json, every project |
claude mcp add catalogue -- npx -y @theluckystrike/mcp-catalogue
claude mcp list # health-check it before the first prompt
# or --scope project, committed to .mcp.json for the team
No restart. The entry is picked up in the next session, and `/mcp` reconnects one on demand.
The npm publish of @theluckystrike/mcp-catalogue is pending; until then use the .mcpb bundle or a clone and build from the latest release.
The same server runs at https://mcp.zovo.one/mcp/https://mcp.zovo.one/mcp/catalogue over MCP streamable HTTP, no install. Mint a free token with curl https://mcp.zovo.one/mcp/token, or use a Pro key. It has no filesystem, so a file comes back as a one-hour download link.
claude mcp add --transport http catalogue https://mcp.zovo.one/mcp/https://mcp.zovo.one/mcp/catalogue \
--header "Authorization: Bearer <token>"
The `--` is load-bearing: it separates Claude Code's own options, such as --transport, --env and --scope, from the command that runs the server. And the default scope is local, private to you and to the directory you ran it in, so adding it in the wrong folder leaves the tools absent with no error at all.
Free: 25 SKUs, the one standard price tier, unlimited rate cards, and every text answer including lines_resolve and price_list_text. A price list nobody can read is not a price list, and withholding lines_resolve would withhold the one thing the sibling servers came here for. sku_delete is free on every tier, and the resolution register is what makes that safe: every resolution updates one row per SKU and role it priced, so the register is bounded by the size of the catalogue rather than by traffic, and a code that has priced a line or that a rate card points at is refused by name with the times it was used and the last resolution id, because a code printed on a document somebody sent is a fact about that document. A byte-identical duplicate is refused before the free cap is even consulted, so a product filed twice names the code already stored rather than being met with an upgrade prompt, and burns neither a slot nor a place in the list. Pro is $19 once, verified offline.
Local, the default, writes ~/.claude.json and is private to you and that directory. --scope project writes .mcp.json at the repository root, shared through version control. --scope user loads it everywhere.
Measured, not documented: of three fresh projects, one first prompt made zero tool calls although initialize answered in 1.05 seconds. Run claude mcp list once first: it prints Connected, and the next run used the tool.
Yes: claude mcp add --transport http https://mcp.zovo.one/mcp/catalogue https://mcp.zovo.one/mcp/https://mcp.zovo.one/mcp/catalogue --header "Authorization: Bearer <token>". Mint a free token at https://mcp.zovo.one/mcp/token or use a Pro key. -t and -H are the short forms.
MCP Catalogue in detail · The same server in Claude Desktop and Cursor · Every server in Claude Code · Guides · Claude Code docs · Buy Pro