@reneturcios/saleroom
v0.1.0
Published
Luxury auction results client: query 20 auction tables with filters, sorting and pagination, read market stats and price trends, and run price checks against the altfinance API. One bin serves a small CLI and a stdio MCP server.
Readme
saleroom
What did that watch actually sell for — and what is one worth today? saleroom is a read-only client for the altfinance auction-results service, which tracks realized prices across twenty luxury categories: watches, handbags, jewelry, gems, cars and motorcycles, aircraft, wine and whisky, art, design, fashion, coins and more. You can list the tables, inspect a table's columns, run filtered and sorted queries over the sales history, read summary statistics and price trends, ask for a fair-value range on a single item, search the whole market at once, consult a precomputed brand/model price index, and view price alerts.
Nothing here trades, bids or changes anything: all nine tools only read. Responses come back exactly as the service returned them — nothing is trimmed, renamed or summarised on the way through.
Configuration
Two environment variables control the client:
ALTFINANCE_API_KEY(required) — sent on every request asAuthorization: Bearer <key>. When it is not set, every tool fails withALTFINANCE_API_KEY is not setbefore any request is made.ALTFINANCE_API_URL(optional) — API base URL. Defaults tohttps://api.altfndata.com.
Tools
list_tables— the available auction tables, with live descriptions and column counts. No arguments.get_table_schema— column names and types for one table. Takestable(required).query_table— query a table withfilters,sort,fieldsselection and pagination (limit1–500,offset≥ 0). Takestable(required) plus the optional arguments.market_stats— a realized-price summary for a table or a filtered segment: count, median, percentiles, average, min/max, sale-date span and top vendors. Takestable(required) and optionalfilters.price_trend— how realized prices moved over time, bucketed byyear,quarterormonth. Takestable(required), optionalbucketand optionalfilters.price_check— a fair-value range for a single item from comparable sales, with source links. Takesitem(required) and optionalcategory. Live categories are handbags, watches and cars.search— whole-market keyword search across every category at once, merged by realized price. Takesquery(required) and optionalcategory.market_index— a precomputed model-level price index for a brand or model (handbags, watches, cars). Takesquery(required) and optionalcategory.list_alerts— a read-only view of price alerts, or guidance on enabling them. No arguments.
The twenty tables are: watches, handbags, jewelry,
gems, automobile, motorcycle, aircraft,
wine_whisky, works_of_art, fine_art, design,
fashion, shoes, automobilia, books, coins,
other_automobile, perfume, accessories and
musical_instruments.
A filter is {column, operator, value}. The operators are
eq, neq, gt, gte, lt, lte, like, in,
not_in, is_null and is_not_null. Omit value for
is_null / is_not_null; pass an array for in /
not_in. A sort is {field, direction} with direction
asc or desc.
Validation happens before any request. An unknown operator
fails with unknown filter operator: <op>; a missing value
where one is required fails with filter value is required
for operator <op>; a limit outside 1–500 fails with
limit must be an integer between 1 and 500. An upstream
non-2xx reply fails with altfinance error: HTTP <status>
and an unreachable API with altfinance unreachable.
Endpoint provenance
The original service's project record pins the nine tools, the twenty table names, the filter operators, the sorting, field-selection and pagination rules, the trend buckets and the two environment variables — and that all nine endpoints are read-only. It does not pin the per-tool argument names beyond its prose, the filter/sort JSON shapes, the auth header or the request paths. Those pieces are reconstructions, labelled as such:
Authorization: Bearer <key>header — reconstruction (the record pins API-key authentication only).GET <base>/v1/tables—list_tables.GET <base>/v1/tables/{table}/schema—get_table_schema.POST <base>/v1/tables/{table}/querywith body{filters?, sort?, fields?, limit?, offset?}(unset fields omitted) —query_table.POST <base>/v1/tables/{table}/statswith body{filters?}—market_stats.GET <base>/v1/tables/{table}/trendwithbucketand a JSON-encodedfiltersquery parameter when set —price_trend.POST <base>/v1/price-checkwith body{item, category?}—price_check.GET <base>/v1/search?q=&category=—search.GET <base>/v1/market-index?query=&category=—market_index.GET <base>/v1/alerts—list_alerts.
CLI
Each tool is a subcommand taking one JSON argument string:
npx @reneturcios/saleroom list_tables '{}'
npx @reneturcios/saleroom query_table '{"table":"watches","filters":[{"column":"brand","operator":"eq","value":"Rolex"}],"limit":10}'
npx @reneturcios/saleroom price_check '{"item":"Rolex Submariner 1968","category":"watches"}'
npx @reneturcios/saleroom --versionOutput is the tool's result text (the upstream JSON on
success). Exit codes: 0 on success, 1 on a runtime
error (including a validation or upstream failure), 2 on
a usage error.
MCP server
npx -y @reneturcios/saleroom mcpMCP client config:
{
"mcpServers": {
"saleroom": {
"command": "npx",
"args": ["-y", "@reneturcios/saleroom", "mcp"],
"env": {
"ALTFINANCE_API_KEY": "<your key>"
}
}
}
}Docker
docker run -i ghcr.io/cloudcorprecords/saleroom
docker run --rm ghcr.io/cloudcorprecords/saleroom list_tables '{}'Development
npm install
npm run build # tsc -> dist/
npm test # tsx --test test/*.test.ts (fake fetch only, no network)
npm run dev # run the CLI from sourceLicense
MIT — Copyright (c) 2026 Rene Turcios
