ALT/FNDATA in Claude: the developer docs
Connect the ALT/FNDATA connector to Claude, then ask questions of verified secondary-market and private-sale transaction data across luxury and collectible assets. This page documents the connector exactly as it ships: three read-only tools, the datasets and fields they reach, how keys and access work, and where the limits are.
What is MCP
The Model Context Protocol (MCP) is an open standard that lets Claude call external tools and data sources during a conversation. Instead of pasting a spreadsheet into the chat, you connect a data source once, and Claude can query it live when a question needs it. It reads the tool descriptions, decides which to call, fills in the parameters, and folds the result into its answer.
The ALT/FNDATA connector exposes our transaction database to Claude through three read-only tools. Nothing is ever written or modified. Claude discovers the available tables, reads their schema, and runs filtered queries on your behalf, so you can research auction and private-sale pricing in plain language.
Quickstart
Two ways to connect. The remote connector needs no install and works in Claude on the web and desktop. The local server is a small Python package for Claude Desktop and Claude Code. Both authenticate with the same ALT/FNDATA API key.
-
Get an API key
Sign in at the ALT/FNDATA portal (or app.altfndata.com) and copy your key. It looks like
afi_live_.... Data-API access is gated to a paid plan; see Membership. Keep the key secret, it carries your entitlements. -
Connect it to Claude
Remote connector (Claude web and desktop). In Claude, open Settings, then Connectors, then Add custom connector, and enter the server URL:
https://mcp.altfndata.com/mcpWhen Claude connects, it runs a secure OAuth handshake and shows an ALT/FNDATA login screen. Paste your
afi_live_...key there once. Claude stores the session, not the raw key.Local server (Claude Desktop). Install the package and add it to your Desktop config:
# install the local MCP serverpip install altfinance-mcp// claude_desktop_config.json// macOS: ~/Library/Application Support/Claude/ // Windows: %APPDATA%\Claude\ { "mcpServers": { "altfinance": { "command": "altfinance-mcp", "env": { "ALTFINANCE_API_KEY": "afi_live_your_key" } } } }Restart Claude Desktop. Claude Code users can add the same local server from a terminal:
# local (stdio) serverexport ALTFINANCE_API_KEY="afi_live_your_key" claude mcp add altfinance -- altfinance-mcp -
Ask your first question
Once connected, try a prompt that names the data and a category:
Using ALT/FNDATA, show the ten highest prices for Patek Philippe watches sold in 2024. Include the lot title, the auction house, the sale date, and the price in USD.Claude will read the schema, then call
query_tableon the watches table with the right filters and sort. The next section shows exactly what that looks like.
Tool reference
The connector registers three tools. All are read-only (annotated readOnlyHint) and return Markdown-formatted text that Claude reads back to you. Column names are validated live against each table's real schema, so start with get_table_schema before filtering on a field you are unsure of.
list_tables
Lists the tables your key can reach, with a one-line description and column count for each. No parameters.
| Parameter | Type | Notes |
|---|---|---|
| None. | ||
Returns: one line per table, for example - watches (78 columns): Luxury watch auction results.
get_table_schema
Returns the column names and types for one table. Use it before query_table so you filter and sort on fields that exist.
| Parameter | Type | Notes |
|---|---|---|
table | string | Table alias, for example watches, handbags, jewelry. See the dataset reference below. |
Returns: a header line with the underlying table name, then one line per column as `column_name` (type). Internal pipeline columns are stripped and never appear.
query_table
The workhorse. Filters, sorts, selects fields, and paginates. Returns matching rows.
| Parameter | Type | Default | Notes |
|---|---|---|---|
table | string | required | Table alias to query. |
fields | list of strings | all columns | Column names to return, for example ["item_title","vendor","usd_price_decimal","sale_date"]. |
filters | list of objects | none | Each filter is {"field": ..., "op": ..., "value": ...}. Operators below. |
sort_field | string | none | Column to sort by, for example usd_price_decimal or sale_date. |
sort_direction | string | desc | asc or desc. |
limit | integer | 20 | Rows to return. Clamped to a maximum of 500 per call. |
offset | integer | 0 | Rows to skip, for pagination. |
Filter operators
| Operator | Meaning | Example value |
|---|---|---|
eq / neq | Equals / not equals | "Rolex" |
gt / gte | Greater than / or equal | 50000 |
lt / lte | Less than / or equal | 1000 |
like | Contains (substring match) | "Daytona" |
in / not_in | In / not in a list | ["Christie's","Sotheby's"] |
is_null / is_not_null | Field is empty / present | (no value) |
Worked example
From the quickstart prompt, Claude issues one call. This is the tool input:
# query_table input
{
"table": "watches",
"fields": ["item_title", "vendor", "sale_date", "usd_price_decimal"],
"filters": [
{"field": "designer", "op": "eq", "value": "Patek Philippe"},
{"field": "status", "op": "eq", "value": "sold"},
{"field": "sale_date", "op": "gte", "value": "2024-01-01"},
{"field": "sale_date", "op": "lte", "value": "2024-12-31"}
],
"sort_field": "usd_price_decimal",
"sort_direction": "desc",
"limit": 10
}
The tool returns numbered rows, each listing the requested fields (illustrative shape):
**10 results** from `watches` (query: 840ms, offset: 0) 1. item_title: Patek Philippe, Ref. 1518 pink gold perpetual calendar chronograph vendor: Christie's sale_date: 2024-11-05 usd_price_decimal: 3860000.0
aggregations and group_by directly.Dataset & field reference
Every category shares one wide schema, so the same fields and the same query work across tables. Swap the table alias to move a question from watches to handbags to fine art. The backend registers these aliases; which ones your key can query depends on your plan, so run list_tables to see your set.
| Alias | Underlying table | Coverage |
|---|---|---|
watches | all_watches_data | Luxury watch auction results |
handbags | all_handbags_data | Luxury handbag auction results |
jewelry | all_jewels_gems_data | Jewelry and gemstone auction results |
gems | all_gems_data | Loose gemstone auction results |
automobile | all_automobile_data | Collector car auction results |
motorcycle | all_motorcycle_data | Collector motorcycle auction results |
aircraft | all_aircraft_data | Aircraft auction results |
wine_whisky | all_wine_whisky_data | Wine and whisky auction results |
works_of_art | all_works_of_art_data | Works of art with stone or jewelry relevance |
fine_art | all_fine_art_data | Fine art across movements and periods |
The connector's built-in guidance highlights watches, handbags, and jewelry as the primary set; the other aliases are available where your plan includes them.
Documented fields
These are the fields we document and support across the category tables. Read the full column list for any table with get_table_schema. Do not rely on columns that are not listed here or returned by the schema call.
| Field | What it holds | Use it for |
|---|---|---|
designer | Brand or maker, for example Rolex or Hermes | The main brand filter |
model | Model line, for example Daytona | Narrowing within a brand |
item_title | Full lot title and description | Free-text matching with like |
sale_date | Date the lot was offered or sold | Any time-based question; always point-in-time |
usd_price_decimal | Realized price in USD | Prices; populated when status = sold |
sale_estimates_high_usd_price | Pre-sale high estimate in USD | A forecast, not a paid price |
status | sold or unsold | Filter to sold before reading a price |
vendor | Auction house or marketplace | Grouping and source checks |
stock_ticker | Ticker of the brand's public parent, for example CFR.SW | Linking a brand to a listed company |
jewelry and gems aliases scope to their category, and works_of_art is restricted to stone or jewelry-relevant lots. Internal pipeline columns (image paths, vision-model fields, screenshots, and similar) are removed from every schema and cannot be queried.Auth & API keys
Every request carries your key. The local server sends it as the X-API-Key header; the remote connector wraps the same key in an OAuth session after you paste it once at the login screen. Keys are entitlement-scoped per table, so a call to a table your plan does not include returns a clear error rather than data.
Plan limits
| Tier | Requests / minute | Rows / day | Max rows / request |
|---|---|---|---|
| Standard | 30 | 10,000 | 100 |
| Premium | 60 | 50,000 | 500 |
| Unlimited (internal) | 1,000 | 10,000,000 | 10,000 |
Limits apply per table subscription. The MCP query_table tool additionally clamps any single call to 500 rows.
Rotation
Rotate a key from the portal, or programmatically via POST /v1/auth/key/rotate. Rotation issues a fresh key with the same access and deactivates the old one immediately, so update your Claude Desktop config or re-paste the new key in the connector login.
Errors you may see
| Code | Meaning |
|---|---|
400 | Bad request, usually an unknown field or malformed filter |
402 | No paid entitlement; upgrade the plan to reach the data API |
403 | Valid key, but no access to the requested table |
429 | Rate limit or daily row quota exceeded; resets at midnight UTC |
Limits & caveats
The data is honest about what it is. Carry these when you read an answer, and see the coverage and methodology page for the full treatment.
- Secondary market plus private sales. Coverage is auction results and private-sale transactions, not retail list prices or dealer asking prices.
- The newest one to two quarters undercount. Recent sales are still being ingested, so the latest periods look thinner than they are. Treat very recent volume and counts as provisional, not as a market decline.
- Read prices only on sold lots.
usd_price_decimalis populated whenstatus = sold. Estimates are forecasts, not amounts paid. - Prices are USD-normalized using nearest-date exchange rates, so a converted figure can differ slightly from a same-day conversion.
- Rows, not aggregates, over the wire. Aggregations Claude reports are computed over the returned rows (up to 500 per call). For population-level statistics, page through results or use the REST API's aggregation support.
- Not investment advice. The data is for research and reference.