Brick Work

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

  1. A running Brick Work with the API on (see the README).
  2. 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

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:

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