关于 thingery
Thingery 是面向二手商品交易的开放物品数据库和 MCP 服务,供 Agent 与买卖双方使用。它整合可搜索的商品信息、卖家及订单流程和买家提醒,并支持托管服务或自托管。
主要功能
- 01语义与关键词混合搜索
- 02创建和管理带图片的商品信息
- 03订单、支付与配送跟踪
- 04保存买家意向并接收匹配提醒
- 05托管或自托管部署
适用场景
- 01按关键词和筛选条件寻找二手商品
- 02添加图片并发布待售商品
- 03跟踪订单配送进度
- 04保存搜索条件以接收新匹配商品
MCP 相关
Thingery 将商品搜索、发布、订单和提醒功能作为 MCP 工具提供。MCP 客户端可通过 HTTP 或本地 stdio 服务连接;公开搜索无需认证,卖家操作需要授权。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
Thingery
Thingery 是面向 AI Agent 的开放商品数据库和 MCP 服务,可用于发布、查找和交易二手商品。
对 AI 助手说 “卖掉这个” ——它会识别商品、撰写商品信息、定价并发布。说 “帮我找一台 300 欧元以内的二手相机” ——它会搜索所有商品信息,并推荐最合适的一件。Thingery 是这些 Agent 共用的数据库和底层 MCP 工具。
- 免费 供所有人使用。不抽成,不受平台锁定。
- 开源(Apache-2.0)。可自托管整个服务,也可以使用旗舰实例。
- 面向 Agent:所有功能都是 MCP 工具;任何大模型都能驱动它。
- 可自托管:Postgres + pgvector + Node 20。
在中国市场的名称:物坊(Wùfāng)。
MCP 工具
| 工具 | 身份验证 | 用途 |
|---|---|---|
describe_category | 公开 | 列出类别及其声明的属性字段——为 Agent 提供自描述模式。创建时会验证已声明的字段;未声明的键也允许使用、可供搜索,其实际用途会通过 undeclared_in_use 展示 |
search_items | 公开 | 混合语义搜索与关键词搜索,并支持价格、类别、商品状况和属性筛选(可使用任意属性键,无论是否已声明) |
get_item | 公开 | 按 ID 获取一条商品信息。待处理(无照片)的商品也会返回,并带有 needs_photo: true |
create_listing | 卖家 | 发布商品——包括核心字段和灵活的 attributes 对象(会验证已声明的键,其余键会保留并可供搜索)。商品至少有一张照片前不会显示在搜索结果中:创建时即使没有图片也会成功,但商品会保持待处理状态(结果中包含 visible: false 和 next_steps),直到添加照片 |
add_item_image | 卖家 | 为商品添加照片(传入 base64,存储在服务端——无需 URL;解码后最大为 5 MB)。添加第一张照片后,待处理的商品就会发布——结果中的 visible 会显示状态。图片在接收时会重新编码:剥除元数据(EXIF/GPS/XMP)、缩小至 ≤ 2000 px,动画 GIF 会保存为静态图片;较大的 PNG 可能会被拒绝,建议优先使用 JPEG |
my_listings | 卖家 | 按状态查看你的商品 |
update_listing | 卖家 | 将商品标记为已预留或已售出、调整价格,以及编辑文本或属性 |
订单流程
| 工具 | 身份验证 | 用途 |
|---|---|---|
get_payout_setup | 卖家 | Stripe Express 入驻网址和状态——可选,启用平台付款 |
create_order | 账户 | 订购商品——返回 Stripe Checkout 网址(stripe 模式),或跟踪平台外订单 |
get_order | 账户 | 查询你的某个订单(买家或卖家视角):状态、物流跟踪、截止时间 |
cancel_order | 账户 | 在可取消时取消;已付款的订单则退款 |
record_tracking | 卖家 | 记录承运商和跟踪代码;配置 EasyPost 后会自动跟踪承运商物流 |
confirm_payment | 卖家 | 确认平台外付款(pending → sold) |
confirm_receipt | 买家 | 确认送达——争议期开始 |
open_dispute | 买家 | 对已送达的订单提出争议;卖家款项将被暂扣 |
release_funds | 买家 | 放弃争议期,立即向卖家放款 |
订单可在平台内完成交易。部署配置了 Stripe 且卖家完成收款入驻时,系统会运行 Stripe 模式(买家保护:平台向买家收款、暂存款项,并在送达和争议期结束后向卖家付款);否则订单将采用平台外模式——Thingery 跟踪状态和截止时间,交易双方自行结算。状态为:pending → sold → label_issued → in_transit → delivered → payout_pending → paid_out,并可转入 disputed/cancelled/refunded 等结束状态;服务器端定时任务会强制执行截止时间(未付款 24 小时后取消、争议期 48 小时、从未发货的订单 72 小时后自动退款——均为默认值,可通过环境变量调整)。设计记录:ADR 0003。
卖家通过 OAuth(可从任意 MCP 主机一键登录——见下文)或 thg_... API 密钥(Authorization: Bearer)进行身份验证;搜索无需身份验证。
买家提醒
| 工具 | 身份验证 | 用途 |
|---|---|---|
save_intent | 卖家 | 保存买家提醒——用自由文本查询和/或结构化筛选条件(类别、成色、价格范围、配送等级、属性)描述你要找的商品。最多保存 25 条意向,每天最多保存 50 次 |
my_intents | 卖家 | 查看已保存的提醒,按最新优先;每条提醒均显示未读匹配数和静音状态 |
update_intent | 卖家 | 将某条提醒设为静音或取消静音——静音提醒将不再收集新的匹配结果 |
delete_intent | 卖家 | 删除提醒及其匹配记录 |
已保存的意向会用于买家提醒:发布符合某条意向的新商品后,相应匹配结果会显示在 my_intents 的未读计数中(专用的 my_matches 视图即将推出)。
发布商品须包含照片
新商品必须至少有一张照片才能对买家可见——浏览、search_items 和类别计数均会排除没有照片的商品(由单个派生谓词控制;设计记录:ADR 0005)。具体来说:
- 使用零张图片调用
create_listing仍会成功——商品会创建,但处于待发布状态:不会显示在信息流中,商品页面会显示占位图片并设为noindex。结果中会包含photo_required、visible: false和指向add_item_image的next_steps(或指向商品页面,所有者可在两次点击内拍摄照片)。 - 添加第一张照片即可发布——无需再次调用其他工具。
add_item_image会返回visible: true;待发布商品在所有返回商品的地方(get_item、my_listings等)都会带有needs_photo: true。 - 删除最后一张照片后,商品会恢复为待发布状态(再次隐藏);上线前创建的商品不受影响,即使没有照片也会保持上线状态——在 thingery.dev 上,这指 2026-10-27 之前创建的商品;自托管实例则会将首次部署此版本时已有的商品视为不受影响。
- 所有者可通过文档所述的会话 Cookie 路由,在商品页面管理照片(上传、删除、重新排序):docs/item-images.md。
两种使用方式
- **零配置(所有人):**在任何部署环境中打开
/chat.html,与 Thingery 助手对话——描述要出售或查找的物品。搜索无需账户;发布需要一个免费账户(/login.html,电子邮件 + 密码;注册后会显示 MCP API 密钥)。 聊天使用服务器上配置的大模型(LLM_*环境变量)——你需要提供密钥,任何兼容 OpenAI 的端点都可使用;如果没有配置,聊天会被禁用,但 MCP 和注册仍可使用。 - 使用自己的 Agent(高级用户):让任意 MCP 客户端连接到
/mcp并通过 OAuth 登录——Claude Desktop、ChatGPT 连接器、VS Code 和 Inspector 会自动发现登录 流程(RFC 9728 资源元数据 + RFC 7591 动态客户端注册);你只需在同意页面批准一次,宿主端就会获得一个轮换的thgo_令牌,可随时在/apps撤销。想用密钥?手动创建的thg_...API 密钥仍可使用,自托管方式见下文(通过 stdio 运行npx thingery)。
快速入门
先选择模式——托管和自托管模式提供相同的 MCP 工具,但数据并不相同:你在托管服务上创建的列表对所有人可见;自托管实例上的列表仅存储在你自己的数据库中。
| 模式 | 端点 | 数据 | 最适合 |
|---|---|---|---|
| 托管 | https://thingery.dev/mcp | 共享的公开市场 | 一分钟内快速上手——无需安装 |
| 自托管 | 你自己的 /mcp,或 stdio | 你的 Postgres、你的数据 | 私有部署、完全掌控、参与开发 |
模式 A — 托管:一分钟内开始搜索
无需安装。在 MCP 客户端中将 https://thingery.dev/mcp 添加为远程 HTTP 服务
(Claude Desktop、ChatGPT 连接器、VS Code、Inspector——参见下文的连接 MCP 客户端),然后通过 OAuth 登录;或者在 /login.html
获取 API 密钥(免费账户;注册后会显示 thg_... 密钥)。搜索完全无需账户——
使用 curl 验证传输格式:
curl -s https://thingery.dev/mcp \
-H 'content-type: application/json' \
-H 'accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call",
"params":{"name":"search_items","arguments":{"q":"Air Max"}}}'
响应以 Server-Sent Events 格式返回;JSON-RPC 结果位于 data: 行。
模式 B — 自托管:npm 包
thingery npm 包可基于你自己的 Postgres 运行完整服务。无需克隆 git 仓库:
mkdir my-thingery && cd my-thingery
npm install thingery
# 1. a Postgres with the pgvector extension (Docker: `docker run -d -p 5432:5432 \
# -e POSTGRES_PASSWORD=thingery pgvector/pgvector:pg16`; Homebrew: see below)
# 2. apply the shipped schema (idempotent, safe to re-run):
psql "postgres://postgres:thingery@localhost:5432/postgres" \
-f node_modules/thingery/db/schema.sql
# 3. run it (DATABASE_URL is the only required env var):
DATABASE_URL="postgres://postgres:thingery@localhost:5432/postgres" \
PORT=3000 node node_modules/thingery/dist/index.js
服务会在 http://localhost:3000 启动,提供 /mcp、/browse、/healthz 和 HTTP
API。打开 /login.html 创建账户——
注册后会立即显示你的 thg_... MCP 密钥。(在修复前发布的 0.1.2 版本中,该页面会返回 404——这是后来修复的打包疏漏;你仍可通过 API 创建账户——密钥只会返回一次,包含在注册响应中:)
curl -s -X POST http://localhost:3000/api/signup \
-H 'content-type: application/json' \
-d '{"email":"[email protected]","password":"at-least-8-chars"}'
# → {"seller":{"name":"you","email":"…","api_key":"thg_…"}}
然后让任意 MCP 客户端连接到 http://localhost:3000/mcp,并使用
Authorization: Bearer thg_...;或者使用下面的 npx 配置通过 stdio 启动服务。
注意:npm 包按发布节奏更新,可能会比 thingery.dev 上的
main落后几天——/healthz会报告正在运行的版本。如果需要使用今天推出的功能,请改为从源码自托管:
从源码自托管(开发)
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
没有 Docker?使用本地 Postgres
npm run db:migrate 需要带有 vector 扩展的 Postgres——即使在仅使用关键词的搜索模式下,架构也会无条件创建该扩展。在 macOS 上,Homebrew 的 pgvector bottle 支持 PostgreSQL 17 和 18(不支持 Docker 配置使用的 16 版——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
.env.example 中的默认 DATABASE_URL 已适用于此配置。对于其他 Postgres,以超级用户身份运行相同的两条 SQL 语句,并将 DATABASE_URL 指向该实例。
连接 MCP 客户端
大多数宿主(Claude Desktop、ChatGPT connectors、VS Code、Inspector)都支持通过 OAuth 登录:
只需将 https://thingery.dev/mcp(或你的自托管 URL)添加为远程 HTTP 服务即可——宿主会自动发现登录流程,你只需授权一次,令牌便会自动轮换。在 thingery.dev
上,你可以通过 /apps 查看并撤销已连接的应用。
不支持 OAuth 的宿主则使用 thg_... API 密钥(可从 /login.html 获取)作为静态 bearer
令牌:
{
"mcpServers": {
"thingery": {
"type": "http",
"url": "http://localhost:3000/mcp",
"headers": { "Authorization": "Bearer thg_YOUR_KEY" }
}
}
}
仅买家(公共搜索)场景可省略 Authorization 标头——公共只读工具始终允许匿名访问。设计说明:OAuth 流程的决策记录见
docs/adr/0002-mcp-oauth-onboarding.md;设置
OAUTH_DISABLED=1 可完全关闭 OAuth 路由(此时宿主会改用密钥)。
通过 stdio 在本地运行(npx)
无需任何 Web 服务即可自托管——该软件包是 npm 上的 thingery,
可作为本地 stdio MCP 服务连接你自己的 Postgres,并可由 Claude Desktop 和
类似客户端启动:
{
"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 是可选的;不设置时,服务将以只读模式运行(搜索 + 获取)。stdio 服务需要与模式 B 相同的前置条件:已应用架构的 Postgres(psql -f node_modules/thingery/db/schema.sql),以及用于写入工具、存在于
该数据库中的密钥(从该部署的 /login.html 或 /api/signup 获取)。
故障排除
| 症状 | 原因 | 解决方法 |
|---|---|---|
search_items 搜索常见词(如 "sneakers")时返回 0 条结果 | thingery.dev 仅运行关键词搜索(未配置嵌入):它会匹配标题/描述中的字面词语——但没有在线商品包含 "sneakers" 一词 | 搜索品牌/商品词语("Air Max"、"Samba"),或改用 category 筛选 |
create_listing 返回 visible: false | 发布要求提供照片:没有图片的商品会保持待处理状态并隐藏 | 调用 add_item_image——添加第一张照片后,商品就会发布 |
HTTP 401 authentication required | 调用受保护工具时未提供凭据 | 使用 OAuth 登录,或发送 Authorization: Bearer thg_... |
/mcp 返回 HTTP 406 | MCP Streamable HTTP 传输要求提供 SSE Accept 标头 | 发送 accept: application/json, text/event-stream |
在已安装的软件包中运行 npm run db:migrate 失败 | scripts/ 未发布——架构文件随包提供,路径为 db/schema.sql | psql "$DATABASE_URL" -f node_modules/thingery/db/schema.sql |
stdio 警告:THINGERY_API_KEY set but not found in the database | 该密钥属于另一个部署的数据库 | 从此部署获取密钥(/login.html 或 /api/signup) |
| 自托管版本的行为与 thingery.dev 不同 | npm 发布版本可能落后于 main(例如照片门控功能) | 比较 /healthz 中的版本;要使用今天的 main,请从源代码自托管 |
使用 curl 试用
# 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}}}'
响应以 Server-Sent Events 的形式返回;JSON-RPC 结果位于 data: 行。
使用 Agent 框架(LangChain、LlamaIndex、Composio)
框架工具包通过可流式 HTTP 访问同一个 /mcp 端点——带有经过端到端工具调用验证的即用型快速入门指南位于
examples/integrations/。
配置
将 .env.example 复制为 .env。主要变量:
| 变量 | 用途 |
|---|---|
DATABASE_URL | Postgres 连接字符串 |
PORT / PUBLIC_BASE_URL | HTTP 端口和商品链接使用的基础 URL |
EMBED_API_URL / EMBED_API_KEY / EMBED_MODEL | 任意兼容 OpenAI 的嵌入端点;若只使用关键词搜索,请将密钥留空 |
STRIPE_SECRET_KEY / STRIPE_WEBHOOK_SECRET | 订单流程付款(Stripe Connect)。密钥为空 = 关闭平台付款(订单在平台外进行);配置了密钥但未配置 webhook 密钥 = 付款会保持待处理状态,直到配置 webhook(默认拒绝) |
EASYPOST_API_KEY / EASYPOST_WEBHOOK_SECRET | 可选的自动承运商追踪;未配置时,买家/卖家需手动确认送达 |
ADMIN_API_KEY | 管理员争议解决路由;仅当长度 ≥32 个字符时启用 |
订单流程的时间窗口和防滥用上限(PAYMENT_DEADLINE_HOURS、DISPUTE_WINDOW_HOURS、
PICKUP_AUTOCONFIRM_DAYS、MAX_PENDING_ORDERS_PER_BUYER,……)及其默认值均在
.env.example 中内联说明。
Agent 技能
skills/sell-item— 卖家流程:照片 → 已识别商品 → 定价商品信息skills/find-item— 买家流程:意向 → 评分匹配项 → 一个最佳推荐
数据约定
- 价格使用整数分:
12500= EUR 125.00 - 成色:
new、like_new、good、fair、poor - 配送等级:
locker(鞋盒大小)、parcel(≤30kg)、bulky(家具)、local(自取) - 机器发现:
llms.txt·agents.json
灵活的架构
固定的列集合无法同时涵盖运动鞋、相机和沙发,因此 Item Graph 采用混合结构:
- 刚性核心列涵盖每件商品共有的信息:身份、价格、成色、状态、类别、配送估算和嵌入向量。这些信息用于索引和业务逻辑。
attributes JSONB存放类别专属字段(size_eu、colorway、shutter_count、ISBN……),通过 GIN 索引支持包含过滤({"size_eu": 43}),并展平到语义嵌入中,因此也可用于语义搜索。categories注册表声明每个类别预期的属性定义。create_listing会验证已声明的键(类型、必填项、枚举),但未知键会直接放行——这是有意设计的灵活性,也便于联邦化,因为不同实例可使用不同属性而不会破坏同步。Agent 可通过describe_category自行获取架构。sellers.profile JSONB为用户侧灵活性预留(区域设置、货币、通知偏好、议价授权)——供后续功能使用。
扩展路径:当某个属性成为常用过滤条件时,可将其提升为 Postgres 生成列并添加索引——无需更改 API。
哪些未声明的键实际正在使用也可以发现:describe_category 会返回 undeclared_in_use——即多个卖家的活跃商品信息中出现的未声明属性键,以及商品数和不同卖家数。这些键不会经过验证(会原样放行),因此应将其视为搜索提示,而非契约——它们表明买家目前可以按什么条件筛选。
Agent 读取 undeclared_in_use 时:
- 最多列出 20 个键,且每个键必须出现在至少 2 个活跃商品信息中,并涉及至少 2 个不同卖家。没有符合条件的键时,整个字段会省略。
- 值为自由格式:同一个未声明键在不同商品信息中可以对应不同值(甚至不同类型)。可在
search_items属性过滤器中使用该键——过滤器适用于任意键,无论是否已声明——但切勿将某个商品信息的值视为该类别的契约。 create_listing和update_listing写入时会限制数据结构:最多 64 个属性条目,键最长 128 个字符,字符串值最长 500 个字符。超出上限时,调用会以invalid_attributes失败。
路线图
订单状态机— 已上线:支持 Stripe Connect 付款、承运商 Webhook、争议处理和期限扫描的订单(ADR 0003)。下一步:在法律和服务条款审核通过后启用 Stripe 实时模式。- 卖家技能升级 — 照片采集已上线:轻松采集商品页面照片、占位图,以及以照片为发布门槛(ADR 0005)。基于同类商品的定价将推迟到商品列表足够多、能够形成真正的可比商品时再实施。
- 买家提醒 — 下一步:“有符合你意向的新商品”事件流。
- 联邦协议 — 实例之间同步,让任何人都能托管 Item Graph 节点。已推迟。
- Agent 间协商 — 买家 Agent 与卖家 Agent 在限定授权范围内协商。已推迟。
当项目真正获得发展势头时,我们会重新考虑联邦和协商功能:连续 2 周每周新增商品列表超过 10 条,或有可自托管用户明确提出需求。
安全
已验证和未验证的内容:docs/security-note.md。如需私下报告漏洞,请参阅 SECURITY.md。
贡献
由 Agent 团队与一位人类架构师共同构建 — 工作约定请参阅 AGENTS.md。欢迎提交 PR;CI(类型检查、构建、测试)必须通过。新加入?从 docs/community.md 开始 — 了解适合新手的问题、如何在 10 分钟内完成开发环境配置,以及在哪里提问。
许可证
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。