Brick Work MCP server
Brick Work ships an MCP server, so an AI assistant can read your collection and, if you allow it, change it. The server is a thin layer over the REST API: every tool call is one API request with your token, so scopes, Undo, idempotency and the audit log behave exactly as for any other API client.
Before you start
- A running Brick Work with the API on (see the README).
- An API token. Create one in Tools & Admin → API tokens, or on the server:
sh
brickwork token create --name assistant --scope read
Use --scope read,write only if the assistant may change things. The secret is shown once; keep it in a file only you can read, for example data/mcp-token (mode 600).
Connect an assistant
On the same computer (stdio)
The assistant starts the server itself. With Brick Work installed from source:
brickwork mcp --in-process --token-file data/mcp-token
--in-process uses the local database through the same API routes, with no network. To talk to a running instance instead, give its API address:
brickwork mcp --api-url http://127.0.0.1:3333/api/v2 --token-file data/mcp-token
In an assistant's MCP settings this is one server entry: the command brickwork, the arguments mcp --in-process --token-file /path/to/mcp-token, and the working directory of your Brick Work checkout. With Docker, run the same command through docker compose exec -T brickwork brickwork mcp ....
Over the network (HTTP)
brickwork mcp --transport http --host 127.0.0.1 --port 5000
This serves the MCP endpoint at /mcp next to the app. Each request must carry the caller's own token (Authorization: Bearer ...); the server never falls back to another token. Without a reverse proxy it listens on this computer only; put TLS in front of it before exposing it, and set BW_TRUSTED_PROXIES as described in the README.
Reading and writing
- Read tools are always available.
- Write tools appear only when the token has the
writescope and the server runs with--allow-write(orBW_MCP_WRITE=1). Both are needed: a write token alone does not enable them. - Admin work (settings, source keys, catalogue import, database export, tokens) is never available as a tool. Use the app or the CLI.
- Every write returns an
event_idand, where possible, anundo_url. Theundo_eventtool takes that id back. - A write tool accepts an optional
idempotency_key. Pass the same key when retrying a call, and the first result is returned instead of applying the change twice. archive_*tools archive. Nothing is hard-deleted through MCP, and archived records can be restored in the app.- Renamed after 0.9.0: the wishlist tools
post_wishlists,patch_wishlists_id,delete_wishlists_id,post_wishlists_id_restoreandpost_wishlists_id_transferare nowcreate_wishlist,edit_wishlist,archive_wishlist,restore_wishlistandtransfer_wishes. A client that calls an old name gets unknown tool (ADR 0017, amendment of 8 Nov 2026).
Items go by number
A tool never asks for a Brick Work item id. Ids are per install, and an assistant has no way to know them. It names an item the way you do, by number:
provider:bricklink(the default) orrebrickable. A set has the same number in both.kind:set,part,minifigure,instructions,box,gear,bookorcatalog.no: the number, such as1000-1or3001.
get_item, get_prices, record_price, refresh_price, import_item and set_figure_missing take these three. Before the call, the server looks the number up (lookup_item does the same on its own). A number that names nothing is not_found. A number that names several items is ambiguous, and the answer lists them as candidates; nothing is written, so ask for a more exact number or the other provider.
A tool that adds something (add_copies, add_stock, add_wish, take_for_gap) takes item as {"provider": "bricklink", "kind": "set", "key": "1000-1"}. provider can be left out. In get_prices the provider also says whose colour number color is, and the colour takes part in the lookup: some BrickLink numbers (legs, for example) name a different item in each colour. record_price takes its color the same way, as the provider's colour number, and stores the Brick Work colour it maps to.
A merged item answers a read with moved and its survivor. The tool reports it as an error, so look the number up again.
Copies, stock lines, wishes, wishlists, storages, lots, events, jobs and orders keep their ids. Take them from the list_* tools, which also filter by number and provider (list_copies with number, for example).
Data and privacy
The assistant sees what its token can read: your sets, parts, prices, storage locations and notes. Brick Work itself sends nothing to the assistant's provider. The assistant client does, so choose a client and provider you are comfortable sharing your collection with, and prefer a read-only token.
Tools and resources
The lists below are generated from the server's own tool table when this site is built, so they always match the release.
A resource is a read-only document an assistant can open by its address, for example brickwork://summary or brickwork://items/bricklink/part/3001.
Read tools (40)
| Tool | What it does | Arguments | API call |
|---|---|---|---|
export_wishlist_csv |
Export wishlist as rebrickable csv | id, kind, summary |
GET /api/v2/wishlists/{id}/export.csv |
export_wishlist_xml |
Export wishlist as bricklink wanted list xml | id, kind, summary |
GET /api/v2/wishlists/{id}/export.xml |
get_copy |
One copy. | id |
GET /api/v2/copies/{id} |
get_copy_completeness |
Stored and derived completeness, checked flag, missing and damaged counts. | id |
GET /api/v2/copies/{id}/completeness |
get_item |
The item: its brick work id, kind, name, the bricklink numbers it is known by and its rebrickable key (design 7). a merged id answers 307 to the survivor. | provider, kind, no |
GET /api/v2/items/{id} |
get_lot_candidate_sets |
The sets a lot may have come from, ranked, with reasons and distinctive parts (lot detective). | id, min_score, theme, year_from, year_to, parts_min, parts_max, ignore_common, limit, offset |
GET /api/v2/lots/{id}/candidate-sets |
get_lot_pull_list |
The pull list of a set for a lot (#202, lot detective): the set's lines with what each needs, what the lot holds and what is found so far. | id, provider, kind, no, show, limit, offset |
GET /api/v2/lots/{id}/pull-list/{set_id} |
get_minifigure_by_number |
Find the item for a minifigure number; the same item body as /items/{id} (decision 2). default provider bricklink; provider=rebrickable for rebrickable numbers. several items answer 409 ambiguous with the candidates, none 404. | no, provider, color |
GET /api/v2/minifigures/by-number/{no} |
get_order |
Order with documents and lines. | id |
GET /api/v2/orders/{id} |
get_part_by_number |
Find the item for a part number; the same item body as /items/{id} (decision 2). default provider bricklink; provider=rebrickable for rebrickable numbers. several items answer 409 ambiguous with the candidates, none 404. | no, provider, color |
GET /api/v2/parts/by-number/{no} |
get_planning_build_scout |
Build scout (#9): the catalogue's sets ranked by how much of each the loose stock already makes. | lot, storage, loose, damaged, min_percent, max_missing, theme, year_from, year_to, size_from, size_to, limit, offset, detail |
GET /api/v2/planning/build-scout |
get_planning_ranking |
Owned copies ranked by cost to complete, with the repair settings used. | cursor, limit, sort, q, direction |
GET /api/v2/planning/ranking |
get_planning_set_scores |
The catalogue's sets ranked by how much of a pile of loose parts each explains. | lot, storage, loose, stock, limit, offset, detail |
GET /api/v2/planning/set-scores |
get_prices |
Current prices and recorded observations of one item. | provider, kind, no, color |
GET /api/v2/items/{id}/prices |
get_set_by_number |
Find the item for a set number; the same item body as /items/{id} (decision 2). a set number is the same at both providers. several items answer 409 ambiguous with the candidates, none 404. | no, provider, color |
GET /api/v2/sets/by-number/{no} |
get_settings |
Allowed settings and freshness rules. | none | GET /api/v2/settings |
get_sources |
Sources with key state (configured yes or no), budget, usage today, last success and error. | cursor, limit, direction |
GET /api/v2/sources |
get_statistics |
Counts by completeness, theme, storage, place. | none | GET /api/v2/statistics |
get_sync_status |
Sync status per source: credentials (never their values), link, last pull, last send and what is waiting. | source |
GET /api/v2/sync/{source} |
get_wishlists |
Get wishlists | cursor, limit, archived, direction |
GET /api/v2/wishlists |
list_copies |
Owned set copies. | cursor, limit, number, provider, condition, status, storage, place, flag, lot, problem, duplicates, theme, year, q, sort, archived, direction |
GET /api/v2/copies |
list_copy_figures |
Whole figures of the copy. | id, cursor, limit, direction |
GET /api/v2/copies/{id}/figures |
list_copy_parts |
Part lines of the copy (required, spare, figure components). | id, cursor, limit, spare, parent, problem, direction |
GET /api/v2/copies/{id}/parts |
list_events |
Audit events, newest first. | cursor, limit, entity, field, via, since, undoable, direction |
GET /api/v2/events |
list_flags |
Flags of kind owner, status and tag. | cursor, limit, kind, direction |
GET /api/v2/flags |
list_gaps |
Missing items over all copies and loose figures. | cursor, limit, kind, number, provider, color, copy_id, direction |
GET /api/v2/gaps |
list_instruction_files |
Booklet files and booklet identities with coverage. | cursor, limit, kind, number, provider, has_file, archived, direction |
GET /api/v2/instruction-files |
list_jobs |
Import and refresh jobs with steps. | cursor, limit, state, failed, direction |
GET /api/v2/jobs |
list_lots |
Part lots. | cursor, limit, storage, archived, direction |
GET /api/v2/lots |
list_matches |
Suggestions: loose stock that fills a gap. | cursor, limit, kind, number, provider, color, copy_id, completes, direction |
GET /api/v2/matches |
list_minifigures |
Figures by identity: owned in sets, loose, missing. | cursor, limit, color, provider, problem, theme, year, q, sort, inventory, direction |
GET /api/v2/minifigures |
list_orders |
Orders with line and receipt state. | cursor, limit, bricklink_order_id, status, direction |
GET /api/v2/orders |
list_places |
Purchase locations with counts and totals per currency. | cursor, limit, direction |
GET /api/v2/places |
list_stale_prices |
Items whose price is older than the freshness rule. | cursor, limit, direction |
GET /api/v2/prices/stale |
list_sticker_candidates |
The sets a sticker on a part line of a lot may belong to (sets that hold the part in its colour and a sticker sheet). | id, stock_id, limit, offset |
GET /api/v2/lots/{id}/stock/{stock_id}/stickers |
list_stock |
Loose stock lines (parts, minifigures, booklets, anything). | cursor, limit, kind, number, provider, color, condition, storage, lot, place, flag, problem, theme, year, q, sort, archived, direction |
GET /api/v2/stock |
list_storages |
Active storages with counts, plus the virtual "not stored". | cursor, limit, direction |
GET /api/v2/storages |
list_wishes |
Wishlist rows; under_max filters to rows priced under the wish maximum. | list, cursor, limit, kind, number, provider, color, condition, flag, under_max, q, sort, archived, direction |
GET /api/v2/wishes |
lookup_item |
Find the item for any provider number: provider, kind and key (and a colour in the provider space). same body and errors as the by-number paths. | provider, kind, key, color |
GET /api/v2/lookup |
search_catalogue |
Search the local bricklink catalogue file by type and text. | cursor, limit, kind, q, sort, direction |
GET /api/v2/catalogue/items |
Write tools (33, only with a write token and --allow-write)
| Tool | What it does | Arguments | API call |
|---|---|---|---|
add_copies |
Add owned copies of a set (quantity n makes n copies) and queue its import. | item, quantity, condition, completeness, decision, storage_id, purchase_location_id, purchase_date, purchase_price, purchase_currency, idempotency_key |
POST /api/v2/copies |
add_stock |
Add loose stock; identical lines merge. | item, color, quantity, condition, storage_id, lot_id, note, idempotency_key |
POST /api/v2/stock |
add_wish |
Add a wish (same colour and item adds to the live row on decision=another). | list_id, item, color, quantity, condition, note, max_price, max_price_currency, max_price_boxed, max_price_boxed_currency, decision, idempotency_key |
POST /api/v2/wishes |
apply_sync_pull |
Apply a pull plan: one copy per missing unit (flag imported from <site>, condition and completeness unset) and missing wishes, in one transaction. ticked defaults to the suggested rows; conflicts only when ticked. undo with post /events/{id}/undo. | source, plan_id, ticked, idempotency_key |
POST /api/v2/sync/{source}/pull/apply |
archive_copy |
Archive the copy (the ui calls this deleting a set). | id, if_match, idempotency_key |
DELETE /api/v2/copies/{id} |
archive_wish |
Archive the wish. | id, if_match, idempotency_key |
DELETE /api/v2/wishes/{id} |
archive_wishlist |
Archive a wishlist | id, idempotency_key |
DELETE /api/v2/wishlists/{id} |
clear_sticker |
Not a sticker: remove the sticker flag from a part line and stop counting a confirmed sticker. one undoable event; a line without the flag writes nothing. | id, stock_id, idempotency_key |
DELETE /api/v2/lots/{id}/stock/{stock_id}/sticker |
confirm_sticker |
Confirm the sticker of a part line: the sheet of a set from the candidates ("this one"). one undoable event; choosing what is already chosen writes nothing. | id, stock_id, set_item_id, sheet_item_id, idempotency_key |
POST /api/v2/lots/{id}/stock/{stock_id}/sticker |
create_storage |
Create a storage. | name, type, parent_id, note, idempotency_key |
POST /api/v2/storages |
create_wishlist |
Create a wishlist | name, sort, note, bricklink_id, idempotency_key |
POST /api/v2/wishlists |
edit_wishlist |
Rename a wishlist or change its settings | id, name, sort, note, bricklink_id, idempotency_key |
PATCH /api/v2/wishlists/{id} |
give_from_stock |
Give n from this line to a copy gap or a loose-figure part gap. | id, copy_id, target, target_id, quantity, idempotency_key |
POST /api/v2/stock/{id}/give |
import_item |
Create the item identity and queue the six import steps. | provider, kind, no, steps, idempotency_key |
POST /api/v2/items/{id}/import |
import_order |
Import an order document: pasted email, bricklink xml, or fetch by order number with the user key. | source, text, number, choice, label, idempotency_key |
POST /api/v2/orders/documents |
make_copy_from_lot |
Make it a copy (#202): the found pieces of the pull list move out of the lot into a new copy of the set, the rest recorded as missing on it. one undoable event. | id, provider, kind, no, idempotency_key |
POST /api/v2/lots/{id}/pull-list/{set_id}/make-copy |
move_to_storage |
Move copies, stock and lots into this storage (id "unstored" for none). a lot carries its parts in the same storage. | id, selections, idempotency_key |
POST /api/v2/storages/{id}/contents |
plan_sync_pull |
Fetch the remote collection and compare: add here, only here, differs, conflict (changed in both places), unmatched. writes nothing to the collection; the plan expires after 24 hours. | source, idempotency_key |
POST /api/v2/sync/{source}/pull/plan |
plan_sync_send |
The remote calls a send would make: set counts and wishes; removals are never ticked by default. | source, idempotency_key |
POST /api/v2/sync/{source}/send/plan |
record_price |
Record one manual or valuation observation; undo sets error=undone and recomputes price_current. | provider, kind, no, condition, guide, price, currency, slot, color, observed_at, idempotency_key |
POST /api/v2/items/{id}/prices |
refresh_price |
Queue a market price refresh for one item. | provider, kind, no, idempotency_key |
POST /api/v2/items/{id}/prices/refresh |
restore_wishlist |
Restore an archived wishlist | id, idempotency_key |
POST /api/v2/wishlists/{id}/restore |
retry_job |
Retry failed steps (all, or one step). queues the work and returns the job. | id, step, idempotency_key |
POST /api/v2/jobs/{id}/retry |
set_copy_checked |
Set or clear the "set is checked" flag and recompute derived completeness. | id, checked, idempotency_key |
PUT /api/v2/copies/{id}/checked |
set_figure_missing |
Set the missing count of one whole figure. | id, provider, kind, no, missing, idempotency_key |
PATCH /api/v2/copies/{id}/figures/{item_id} |
set_part_missing |
Set missing, damaged, checked for one line (mark missing or found). | id, part_id, missing, damaged, checked, idempotency_key |
PATCH /api/v2/copies/{id}/parts/{part_id} |
take_for_gap |
Take n of one missing part (with its colour) or whole minifigure from loose stock into the copy; one undo reverses every move. | id, item, color, quantity, idempotency_key |
POST /api/v2/copies/{id}/take |
transfer_wishes |
Move or copy wishes into this wishlist | id, ids, copy, idempotency_key |
POST /api/v2/wishlists/{id}/transfer |
undo_event |
Undo m3 collection or supported standalone core receipts. token, source key and source toggle receipts (alone or inside an api event) require admin; other receipts require write. | id, idempotency_key |
POST /api/v2/events/{id}/undo |
update_copy |
Edit condition, completeness, storage, purchase and estimate fields, note. | id, if_match, fields, idempotency_key |
PATCH /api/v2/copies/{id} |
update_stock |
Edit a stock line (may merge into an existing line; response lists merged ids). | id, if_match, fields, idempotency_key |
PATCH /api/v2/stock/{id} |
update_wish |
Edit quantity, colour, condition, max price, max price with box and their currencies, note. | id, if_match, fields, idempotency_key |
PATCH /api/v2/wishes/{id} |
wish_to_owned |
Turn a wish into owned copies and archive the wish, one transaction. | id, quantity, condition, completeness, idempotency_key |
POST /api/v2/wishes/{id}/to-owned |
Resources (8)
| URI | API operation |
|---|---|
brickwork://summary |
get_statistics |
brickwork://copies/{id} |
get_copies_by_id |
brickwork://wishlist |
get_wishes |
brickwork://storages |
get_storages |
brickwork://sources |
get_sources |
brickwork://events/recent |
get_events |
brickwork://openapi |
get_openapi_yaml |
brickwork://items/{provider}/{kind}/{no} |
get_lookup |
