mcpField
T
Tanpin

Tanpin

本地服务
huggingface.co商业与营销15 周前更新

关于 Tanpin

Tanpin 是面向门店的库存管理服务,提供逐 SKU 需求预测、补货计算、供应商采购订单和交付时间估算。它将 REST API、仪表盘、守护进程和 MCP 服务整合在一个 Node.js 应用中。

主要功能

  1. 01逐 SKU 需求预测
  2. 02补货与安全库存计算
  3. 03ABC 分类和下架标记
  4. 04供应商采购订单与邮件
  5. 05交付时间估算
  6. 06REST API、仪表盘和守护进程

适用场景

  1. 01预测单个商品的需求
  2. 02识别需要补货的商品
  3. 03准备并跟踪供应商订单
  4. 04标记滞销或无需求库存

MCP 相关

stdio MCP 服务连接 Tanpin 的 HTTP API,并向 MCP 客户端提供库存操作工具。可配置 API 地址,并在需要时设置 API 密钥。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"willykeenan-tanpin": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"ghcr.io/willykeenan/tanpin:0.1.0"
]
}
}
}
启动命令docker run -i --rm ghcr.io/willykeenan/tanpin:0.1.0

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
ocighcr.io/willykeenan/tanpin:0.1.0

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

Tanpin

逐项盘点,自动调整库存。 按 SKU 预测需求、自动生成采购订单、供应商邮件和预计送达时间——提供 REST API、MCP 服务、守护进程和仪表板。纯 Node 22 实现,运行时零依赖(仅使用 node:* 内置模块)。

在线演示:huggingface.co/spaces/willykeenan/tanpin(只读,使用预置示例数据)

自动周期运行后的 Tanpin 仪表板:库存价值、未完成采购订单和带预计送达时间的待收货配送

演示版的真实截图;其中的数据为虚构示例数据。

按 SKU 显示的预测,包含星期和趋势因子、安全库存、再订货点以及经理的假设
按 SKU 显示的预测,包含星期和趋势因子、安全库存、再订货点以及经理的假设。
本周期生成的采购订单,按供应商分组
本周期生成的采购订单,按供应商分组。

为什么采用单品管理

单品管理(単品管理,“单品管理”)将每个 SKU 都视为独立的业务。门店经理会针对某件商品明天的需求形成假设——天气、当地活动、星期几——据此下单,再根据实际销量验证结果。周转快的商品受到严格管控并频繁补货。长尾商品采用更简单的规则,也是最先被下架的对象。

Tanpin 将这一循环编码为软件:

  1. 预测每个 SKU,依据近期销量、星期季节性、短期趋势以及经理录入的假设(活动、天气、促销)。
  2. 计算订单——按选定的服务水平计算安全库存、再订货点和 EOQ,并进行包装规格取整,满足最低订购量,同时通过 JIT 限制库存供应天数。
  3. 采购并跟踪——按供应商分组生成采购订单,自动发送邮件,并根据提前期、截单时间和配送时段计算预计送达时间。
  4. 停止备货滞销商品——标记已停止销售和周转缓慢的 SKU,以便下架。

ABC 分类遵循同样的理念:少量 A 类商品贡献了大部分价值,因此采用最新的补货频率;C 类商品则是待下架商品池。

功能

  • 按 SKU 预测——近期数据加权移动平均、星期因子、趋势(±40%)、假设累积
  • 自动补货——安全库存、再订货点、EOQ、包装规格、MOQ、最大库存供应天数
  • ABC 分类 + 下架——按收入贡献分为 A/B/C 类;标记已停止销售(无需求)和周转缓慢(库存供应天数过多)的商品
  • 守护进程——每 N 分钟(默认 15 分钟):重新预测、重新分类、生成采购订单草稿,并可选择发送邮件和自动收货
  • 供应商邮件——设置 SMTP_HOST 时通过隐式 TLS(端口 465)发送;否则在发件箱中生成 .eml 文件
  • 预计送达时间——将提前期对齐到下一个配送时段,并遵循截单时间(当天 UTC)
  • REST API——通过 SKU 定位产品,/openapi.json 提供 OpenAPI 3.1 规范,/llms.txt 提供 Agent 指南
  • MCP 服务——通过 stdio 使用以换行符分隔的 JSON-RPC,支持 Claude Code、Codex、Cursor 和任何 MCP 客户端
  • 仪表板——位于 / 的原生 JavaScript 单页应用(产品、订单、供应商、预测、活动、API、设置)
  • Webhook——使用 HMAC-SHA256 签名的 JSON POST 请求(X-Inventory-Signature)
  • CSV——导入/导出产品;导出商品流转审计记录
  • API 密钥——以 SHA-256 哈希形式存储,完整密钥仅显示一次
  • Idempotency-Key——销售和采购订单写入操作支持 24 小时重放窗口
  • 插件——TANPIN_PLUGIN 可加载额外的 HTTP 路由和用量限制
  • 存储——SQLite(node:sqlite、WAL、增量行写入;data/inventory.sqlite),由服务器和独立守护进程安全共享;设置 TANPIN_STORE=json 时回退到 JSON

60 秒快速开始

需要 Node.js 22 或更高版本。

npx github:willykeenan/tanpin serve

打开 http://localhost:4173,然后点击 加载演示数据。这会加载一份便利店商品目录、约 35 天的销售数据、实时预测和补货建议。

从本仓库的克隆版本开始:

node bin/tanpin serve
Docker

公开演示镜像(Hugging Face Space):

docker build -f space/Dockerfile -t tanpin-demo .
docker run --rm -p 7860:7860 tanpin-demo

打开 http://localhost:7860。该镜像运行 DEMO_MODE=1 PORT=7860 HOST=0.0.0.0 node bin/tanpin serve:读取操作开放,写入操作仅限演示商品目录(销售、调整、采购订单、假设、种子数据、周期),无需密钥;webhook 和 SMTP 已关闭,商品目录每 30 分钟重新初始化一次。

可自托管镜像(根目录中的 Dockerfile / compose.yml):请求通过 Docker 的端口映射到达容器,因此不属于“本机”请求,每次 API 调用都需要密钥。使用主密钥启动,并将该密钥粘贴到仪表板的提示词中:

docker build -t tanpin .
docker run --rm -p 4173:4173 -e TANPIN_ADMIN_KEY="$(openssl rand -hex 24)" -v tanpin-data:/app/data tanpin
# or: echo "TANPIN_ADMIN_KEY=$(openssl rand -hex 24)" > .env && docker compose up

更多详情,包括首次销售和首张采购订单,请参阅:docs/QUICKSTART.md。

API

发送 Authorization: Bearer <key> 或 X-API-Key: <key>。在服务器本机上直接向 localhost 发出的请求默认无需密钥;通过反向代理、容器端口映射或其他浏览器来源发出的请求则需要密钥(参见安全模型)。

涵盖门店操作的五个调用:

# Whole world in one response: KPIs, products with live math, open POs, suppliers
curl http://localhost:4173/api/state

# Record a sale (SKU everywhere; Idempotency-Key for safe retries)
curl -X POST http://localhost:4173/api/sales \
  -H 'Content-Type: application/json' \
  -d '{"sku":"COFFEE-HOT","qty":2}'

# Dry run of the ordering engine, grouped by supplier
curl http://localhost:4173/api/recommendations

# Turn a recommendation into a real PO (and email it)
curl -X POST http://localhost:4173/api/purchase-orders \
  -H 'Content-Type: application/json' \
  -d '{"supplierId":"FreshFoods Distribution","fromRecommendations":true,"autoSend":true}'

# Forward-looking demand bump — forecasts and auto-orders adjust immediately
curl -X POST http://localhost:4173/api/hypotheses \
  -H 'Content-Type: application/json' \
  -d '{"note":"heatwave next week","multiplier":1.4,"category":"beverage"}'

错误格式为 {"error":"<message>","code":"<machine_code>"}。/api/... 和 /api/v1/... 等效。

完整参考:docs/API.md。实时契约:GET /openapi.json。面向 Agent 的指南:GET /llms.txt。

MCP

启动库存服务,然后让 MCP 客户端连接到 tanpin mcp。该进程通过 stdio 使用 JSON-RPC,并调用 HTTP API。

环境变量:INVENTORY_URL(默认值为 http://localhost:4173),以及在服务需要密钥时使用的 INVENTORY_API_KEY。

Claude Code
claude mcp add tanpin --env INVENTORY_URL=http://localhost:4173 -- npx -y github:willykeenan/tanpin mcp

或者使用项目的 .mcp.json:

{
  "mcpServers": {
    "tanpin": {
      "command": "npx",
      "args": ["-y", "github:willykeenan/tanpin", "mcp"],
      "env": {
        "INVENTORY_URL": "http://localhost:4173"
      }
    }
  }
}

从本地检出版本运行时,使用 "command": "node" 和 "args": ["src/mcp.js"](或 ["bin/tanpin", "mcp"])代替 npx。

Codex

在 ~/.codex/config.toml(或项目的 Codex 配置)中:

[mcp_servers.tanpin]
command = "npx"
args = ["-y", "github:willykeenan/tanpin", "mcp"]

[mcp_servers.tanpin.env]
INVENTORY_URL = "http://localhost:4173"
Cursor

.cursor/mcp.json:

{
  "mcpServers": {
    "tanpin": {
      "command": "npx",
      "args": ["-y", "github:willykeenan/tanpin", "mcp"],
      "env": {
        "INVENTORY_URL": "http://localhost:4173"
      }
    }
  }
}

先调用 get_overview。典型流程:get_overview → get_reorder_recommendations → 使用 from_recommendations=true 调用 create_purchase_order。

工具列表和架构:docs/MCP.md。

安全模型

  • 只有直接的本地请求可以不使用密钥。 仅当 TCP 对端是环回地址、Host 标头是环回名称(localhost、127.x、::1),且不存在转发标头(Forwarded、X-Forwarded-*、X-Real-IP、Via……)时,请求才无需密钥。因此,同一主机上的反向代理(nginx、Caddy、cloudflared)不会让互联网变成“localhost”。设置 TANPIN_REQUIRE_API_KEY=1 可要求每个请求都携带密钥。任何需要密钥的地方,控制面板都会提示输入密钥。
  • 跨源浏览器请求(读取和写入,包括 TANPIN_CORS_ORIGINS 中的源)始终需要密钥。
  • 机密信息只写不读。 读取 settings.integrations 时,永远不会返回 Webhook 签名密钥和提供方凭据(而是返回 hasWebhookSecret: true);Webhook 密钥只会在创建时显示一次。
  • API 密钥通过 POST /api/keys 创建。明文密钥只会在该响应中出现一次;存储中保留的是 SHA-256 哈希和可见前缀。通过 Authorization: Bearer <key> 或 X-API-Key: <key> 发送密钥。使用 DELETE /api/keys/{id} 撤销密钥。
  • 主密钥。 TANPIN_ADMIN_KEY 是始终有效的密钥,比较时使用时间安全哈希。将其用于引导初始化,然后签发哈希密钥。
  • Webhook 是使用 X-Inventory-Signature: sha256=<HMAC-SHA256(secret, raw_body)> 签名的 JSON POST 请求。请根据原始字节验证签名。投递采用即发即忘方式(超时为 10 秒),因此失效的接收端不会影响销售或守护进程周期。它们绝不会发送到私有地址、环回地址、链路本地地址、CGNAT 地址或保留地址(会检查实际连接的地址,因此 DNS 重绑定不起作用),绝不跟随重定向,并且在 DEMO_MODE 下会关闭——无论是在服务端还是独立守护进程中。
  • 幂等性。 /api/sales、/api/sales/bulk 和 /api/purchase-orders 上的 POST 请求使用 Idempotency-Key 后,会在 24 小时内重放原始响应。
  • 输入卫生。 JSON 请求体会丢弃 __proto__ / constructor / prototype 键。静态文件仅限于 public/ 目录。
  • 电子邮件。 SMTP 使用 465 端口上的隐式 TLS(SMTP_HOST、SMTP_PORT、SMTP_USER、SMTP_PASS)。未配置 SMTP 时,邮件会以 .eml 文件的形式写入数据目录,并记录在 GET /api/outbox 中。
  • CORS 使用允许列表(TANPIN_CORS_ORIGINS);绝不会发送 *。除非 HOST 另有指定,否则服务会绑定到 127.0.0.1。每个响应都带有不包含内联脚本的 Content-Security-Policy。

开放端口之前,请设置 TANPIN_ADMIN_KEY(或从 localhost 创建密钥)。详情请参阅:docs/SECURITY-MODEL.md。

CLI

tanpin serve    API + dashboard (PORT, HOST, TANPIN_DATA_DIR / TANPIN_DB)
tanpin daemon   auto-management loop against the same data file (same TANPIN_* env as serve)
tanpin mcp      MCP server on stdio (INVENTORY_URL, INVENTORY_API_KEY)
tanpin seed     replace the data file with the demo store

tanpin serve 会在进程内启动守护进程,除非设置了 TANPIN_NO_DAEMON=1。

配置

变量使用方默认值
PORTserve4173
HOSTserve127.0.0.1
TANPIN_DATA_DIRserve, daemon, seed./data
TANPIN_DBserve, daemon, seed$TANPIN_DATA_DIR/inventory.json(存储为 inventory.sqlite)
TANPIN_OUTBOXserve, daemon<dir of TANPIN_DB>/outbox
TANPIN_REQUIRE_API_KEYserve未设置(直接本地请求无需密钥)
TANPIN_ADMIN_KEYserve未设置
TANPIN_NO_DAEMONserve未设置(启用 daemon)
TANPIN_PLUGINserve未设置
TANPIN_CORS_ORIGINSserve未设置(仅同源)
DEMO_MODEserve, daemon未设置;Space 镜像将其设为 1
INVENTORY_URLmcphttp://localhost:4173
INVENTORY_API_KEYmcp未设置
INVENTORY_DBTANPIN_DB 的旧别名未设置
STRIPE_API_KEY / SQUARE_ACCESS_TOKEN销售集成未设置(参见 docs/INTEGRATIONS.md)
SMTP_HOST / SMTP_PORT / SMTP_USER / SMTP_PASS电子邮件如果未设置 SMTP_HOST,则使用发件箱文件

运行时状态存储在 data/ 和 outbox/ 中(已加入 gitignore)。autoManage、autoSend、autoReceive、serviceLevel、timezone 和 daemonIntervalMinutes 等设置会与数据一起存储,并可通过 PUT /api/settings 或 Settings 选项卡进行编辑。

路线图

随 0.1.0 发布

  • 预测、补货计算、daemon、REST、MCP、仪表板、Webhooks、CSV、API 密钥、SMTP/发件箱、插件钩子
  • 安全性 — 默认绑定到 127.0.0.1;CORS 允许列表(TANPIN_CORS_ORIGINS);Origin/Host 检查;识别代理的本地绕过机制;屏蔽机密信息;带 DNS 固定的 webhook SSRF 防护;CSP;公共 Space 使用 DEMO_MODE=1
  • SQLite 存储 — 默认使用 node:sqlite 后端、WAL、增量写入、跨进程库存增量;通过 TANPIN_STORE=json 回退到 JSON
  • 集成 — Stripe Checkout / Shopify / Square 订单入站 webhook(当 webhook 未提供商品明细时,通过服务提供商 API 获取)、CSV 销售数据、额外的电子邮件传输方式
  • 回测 — GET /api/backtest 滚动起点预测评估(MAPE、sMAPE、偏差),在工作线程上运行
  • 时区 — 用于日历日期、预测、交付时段、截止时间和 CSV 日期的 IANA 门店时区(settings.timezone)

开发

npm test          # node --test --test-concurrency=1 test/

参见 CONTRIBUTING.md。MIT 许可证 — LICENSE。

使用 Docker 运行

镜像已发布至 ghcr.io/willykeenan/tanpin,适用于 Apple silicon 和 Intel。

docker run -d --name tanpin -p 4173:4173 -e TANPIN_ADMIN_KEY="REPLACE_WITH_A_LONG_RANDOM_KEY" -v tanpin-data:/app/data ghcr.io/willykeenan/tanpin
claude mcp add tanpin -- docker exec -i tanpin node bin/tanpin mcp

tanpin mcp 通过 HTTP 调用正在运行的服务,因此需要通过 docker exec 在该容器内运行;容器内的请求属于本地请求,无需密钥。单独的 docker run ... tanpin mcp 容器无法通过 localhost:4173 访问该服务。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。