Open item database and MCP server for AI agents to list, find, and trade second-hand goods.
Runs on your machine from its package; the steps are below.
Not assessed yet.
Odel charges nothing per call. The publisher may charge for its own service.
Runs locally over stdio
This server isn't hosted — your MCP client launches it from a package registry. Use one of the commands below, or drop the config into your client (e.g. Claude Desktop).
Run
npx -y thingery
MCP client config
{
"mcpServers": {
"thingery": {
"command": "npx",
"args": [
"-y",
"thingery"
]
}
}
}Thingery is the open item database and MCP server for AI agents to list, find, and trade second-hand goods.
Say "sell this" to your AI assistant — it identifies the item, writes the listing, prices it, and publishes it. Say "find me a used camera under €300" — it searches every listing and proposes the best one. Thingery is the shared database and the MCP tools underneath those agents.
Chinese-market name: 物坊 (Wùfāng).
| Tool | Auth | Purpose |
|---|---|---|
describe_category | public | List categories and their expected attribute fields — the self-describing schema for agents |
search_items | public | Hybrid semantic + keyword search with price/category/condition/attribute filters |
get_item | public | Fetch one listing by id |
create_listing | seller | Publish an item — core fields plus a flexible attributes object |
add_item_image | seller | Attach a photo to a listing (base64 in, stored server-side — no URLs needed) |
my_listings | seller | Your listings by status |
update_listing | seller | Mark reserved/sold, adjust price, edit text or attributes |
Sellers authenticate with Authorization: Bearer thg_...; search is anonymous.
/chat.html on any deployment and talk to the Thingery
assistant — describe an item to sell or to find. Searching needs no account; publishing needs a
free one (/login.html, email + password; your MCP API key is shown after signup).
The chat uses an LLM configured on the server (LLM_* env vars) — you bring the key, any
OpenAI-compatible endpoint works; without it, chat is disabled while MCP and signup still work./mcp with your thg_... API
key, or self-host everything (below, or npx thingery over stdio).git clone https://github.com/thingery/thingery
cd thingery
npm install
docker compose up -d db # Postgres 16 + pgvector
cp .env.example .env
npm run db:migrate
npm run db:seed # demo seller + 3 listings; prints an API key
npm run dev # http://localhost:3000
npm run db:migrate needs a Postgres with the vector extension — the schema creates it
unconditionally, even in keyword-only search mode. On macOS, Homebrew's pgvector bottle
supports PostgreSQL 17 and 18 (not 16, the version the Docker setup uses — any of them works
for Thingery):
brew install postgresql@18 pgvector
brew services start postgresql@18
psql postgres -c "CREATE ROLE thingery LOGIN PASSWORD 'thingery';" \
-c "CREATE DATABASE thingery OWNER thingery;"
psql -d thingery -c "CREATE EXTENSION vector;" # run as the Postgres superuser
The default DATABASE_URL in .env.example already matches this setup. On any other
Postgres, run the same two SQL statements as the superuser and point DATABASE_URL at it.
{
"mcpServers": {
"thingery": {
"type": "http",
"url": "http://localhost:3000/mcp",
"headers": { "Authorization": "Bearer thg_YOUR_KEY" }
}
}
}
Omit the Authorization header for buyer-only (public search) usage.
npx)Self-host without any web server — the package runs as a local stdio MCP server against your own Postgres, spawnable by Claude Desktop and similar clients:
{
"mcpServers": {
"thingery": {
"command": "npx",
"args": ["-y", "thingery"],
"env": {
"DATABASE_URL": "postgres://thingery:thingery@localhost:5432/thingery",
"THINGERY_API_KEY": "thg_YOUR_KEY"
}
}
}
}
THINGERY_API_KEY is optional; without it the server runs read-only (search + get).
# List tools (the Accept header is required by the MCP Streamable HTTP transport)
curl -s http://localhost:3000/mcp \
-H 'content-type: application/json' \
-H 'accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
# Search (finds the seeded Nike Air Max: €85 is within the €100 filter)
curl -s http://localhost:3000/mcp \
-H 'content-type: application/json' \
-H 'accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/call",
"params":{"name":"search_items","arguments":{"q":"air max","max_price_cents":10000}}}'
Responses come back as Server-Sent Events; the JSON-RPC result is on the data: line.
Copy .env.example to .env. Key variables:
| Variable | Purpose |
|---|---|
DATABASE_URL | Postgres connection string |
PORT / PUBLIC_BASE_URL | HTTP port and base URL used in item links |
EMBED_API_URL / EMBED_API_KEY / EMBED_MODEL | Any OpenAI-compatible embeddings endpoint; leave the key empty for keyword-only search |
skills/sell-item — the seller pipeline: photos → identified item → priced listingskills/find-item — the buyer pipeline: intent → scored matches → one best proposal12500 = EUR 125.00new, like_new, good, fair, poorlocker (shoebox-sized), parcel (≤30kg), bulky (furniture), local (pickup)llms.txt · agents.jsonNo fixed column set can cover sneakers, cameras and sofas at once, so the Item Graph is a hybrid:
attributes JSONB for category-specific fields (size_eu, colorway, shutter_count, ISBN...), GIN-indexed for containment filters ({"size_eu": 43}) and flattened into the semantic embedding so they're meaning-searchable too.categories registry that declares expected attribute definitions per category. create_listing validates declared keys (types, required, enums) but unknown keys pass through — flexible by design, and federation-friendly since instances can diverge on attributes without breaking sync. Agents self-serve the schema via describe_category.sellers.profile JSONB for user-side flexibility (locale, currency, notification prefs, negotiation mandates) — reserved for upcoming features.Growth path: when an attribute becomes a hot filter, promote it to a Postgres generated column + index — no API change needed.
sold → label issued → in transit → delivered → payout released, driven by carrier + payment webhooks (Stripe Connect / shipping aggregator).Built by an agent team with a human architect — see AGENTS.md for the working
conventions. PRs welcome; CI (typecheck, build, tests) must pass. New here? Start with
docs/community.md — good first issues, dev setup in under 10 minutes,
and where to ask questions.