内容
# sapo-mcp
[](https://www.npmjs.com/package/sapo-mcp)
[](LICENSE)
[](https://nodejs.org)
适用于 [Sapo.vn](https://www.sapo.vn) POS 和电子商务平台的模型上下文协议服务器。
## 功能
- **4 种模式,105 种独特工具:** `pos-online`(51),`web`(31),`pos-counter`(15),`analytics`(10)— 2 种读取工具在 `pos-online` 和 `web` 之间共享
- **两种传输方式:** stdio(Claude Desktop,Cursor)和 Streamable HTTP(Docker,GoClaw)
- **默认安全:** 通过 `SAPO_ALLOW_OPS`(默认为无)控制破坏性操作;所有破坏性调用也需要 `confirm: true`
- **单租户:** 通过私有应用凭证,每个服务器实例一个商店
- **预 1.0:** 工具名称和模式可能会在小幅度调整。参见 [1.0 后路线图](#post-10-roadmap)。
## 安装
需要 **Node.js 20 或更新版本**。使用 `node --version` 验证。
### 选项 A — npx(无需安装)
推荐用于 MCP 客户端(Claude Desktop,Cursor)。始终拉取最新发布的版本:
```bash
npx -y sapo-mcp@latest --version
```
### 选项 B — 全局安装
```bash
npm install -g sapo-mcp
sapo-mcp --version
sapo-mcp --help
```
### 选项 C — 本地项目依赖
```bash
npm install sapo-mcp
npx sapo-mcp --mode=pos-online
```
## 快速入门
### 1. 获取凭证
在 [developers.sapo.vn](https://developers.sapo.vn) 上创建一个私有应用:
- 店名:`mystorename` → `mystorename.mysapo.net`
- API 密钥 + 密钥
### 2. 配置您的 MCP 客户端
#### Claude Desktop
编辑 `~/Library/Application Support/Claude/claude_desktop_config.json`(macOS)或 `%APPDATA%/Claude/claude_desktop_config.json`(Windows):
```json
{
"mcpServers": {
"sapo": {
"command": "npx",
"args": ["-y", "sapo-mcp", "--mode=pos-online,web,analytics"],
"env": {
"SAPO_STORE": "mystorename",
"SAPO_API_KEY": "xxx",
"SAPO_API_SECRET": "yyy"
}
}
}
}
```
重启 Claude Desktop。工具将出现在 🔌 插件图标下。
#### Cursor
编辑 `~/.cursor/mcp.json` 或每个工作区的 `.cursor/mcp.json`:
```json
{
"mcpServers": {
"sapo": {
"command": "npx",
"args": ["-y", "sapo-mcp", "--mode=pos-online,web"],
"env": {
"SAPO_STORE": "mystorename",
"SAPO_API_KEY": "xxx",
"SAPO_API_SECRET": "yyy"
}
}
}
}
```
#### MCP Inspector(测试/调试)
```bash
npx @modelcontextprotocol/inspector \
-e SAPO_STORE=mystorename \
-e SAPO_API_KEY=xxx \
-e SAPO_API_SECRET=yyy \
npx -y sapo-mcp --mode=pos-online
```
在浏览器中打开打印的 URL 以检查/调用已注册的工具。
使用 `--mode=pos-online,web,analytics` 注册多个模式(工具的并集;共享工具仅注册一次)。
### 3. CLI 标志
| 标志 | 默认值 | 描述 |
|------|---------|-------------|
| `--mode=<modes>` | `pos-online` | 要激活的模式的逗号分隔列表 |
| `--transport=<t>` | `stdio` | 传输类型(`stdio` 或 `http`) |
| `--port=<port>` | `3333` | HTTP 端口(stdio 忽略) |
| `--help` | — | 打印用法并退出 |
| `--version` | — | 打印版本并退出 |
## 环境变量
| 变量 | 必需 | 默认值 | 描述 |
|----------|----------|---------|-------------|
| `SAPO_STORE` | 是 | — | 商店子域名 |
| `SAPO_API_KEY` | 是 | — | 私有应用 API 密钥 |
| `SAPO_API_SECRET` | 是* | — | 私有应用 API 密钥 |
| `SAPO_API_SECRET_FILE` | 是* | — | 包含密钥的文件路径(优先) |
| `SAPO_ALLOW_OPS` | 否 | `""` | 允许的破坏性类别的 CSV |
| `SAPO_MAX_AUTO_PAGES` | 否 | `10` | 最大自动分页页面 |
| `SAPO_RETRY_MAX` | 否 | `3` | HTTP 重试次数 |
| `SAPO_LOG_LEVEL` | 否 | `info` | 日志级别(error/warn/info/debug/trace) |
| `SAPO_HTTP_HOST` | 否† | `127.0.0.1` | HTTP 绑定主机(默认循环) |
| `SAPO_HTTP_PORT` | 否 | `3333` | HTTP 端口 |
| `SAPO_HTTP_MAX_SESSIONS` | 否 | `100` | 最大并发 MCP 会话 |
| `SAPO_HTTP_SESSION_IDLE_MS` | 否 | `1800000` | 空闲会话 GC 阈值(30 分钟) |
| `SAPO_MCP_AUTH_TOKEN` | 否† | — | 承载令牌。**如果主机是非循环的,则需要** |
| `SAPO_HTTP_CORS_ORIGINS` | 否 | — | 允许的 CORS 来源的 CSV(默认:禁用) |
*`SAPO_API_SECRET` 和 `SAPO_API_SECRET_FILE` 之一是必需的。
†仅 HTTP。令牌在 `SAPO_HTTP_HOST` 不是 `127.0.0.1`/`localhost`/`::1` 时强制执行。
## 模式
| 模式 | 状态 | 描述 |
|------|--------|-------------|
| `pos-online` | 0.5.0 | 在线订单,客户,履约(51 种工具) |
| `web` | 0.5.0 | 店面,集合,文章,SEO(31 种工具) |
| `pos-counter` | 0.5.0 | POS 柜台:地点,库存写入,供应商,班次,库存转移(15 种工具) |
| `analytics` | 0.5.0 | 组成报告:收入,热门产品/客户,LTV,税,渠道分解,折扣使用,班次报告(10 种工具) |
> **注意:** `pos-counter` 排除 5 个仅限内部的端点(`purchase_orders`,`purchase_returns`,`stock_adjustments`,`cash_transactions`,`cashbook`)— 这些端点返回 HTTP 403 私有应用凭证,需要 OAuth 合作伙伴应用(1.0 后路线图)。
>
> 分析工具自动分页至 `SAPO_MAX_AUTO_PAGES`;当达到上限时,结果带有 `truncated: true`。
## 工具验证状态
105 种独特工具的验证级别(最后更新:2026-04-30):
| 符号 | 级别 | 含义 |
|---|---|---|
| ✅ | **Canary 监控** | 端点 + 模式验证实时;通过 `.github/workflows/canary.yml` 进行每日夜间探测 |
| 🟢 | **实时验证** | 开发过程中点击端点,模式捕获到固定装置,不在每日 Canary 中 |
| 🟡 | **仅文档** | 模式来自 `docs/sapo-api-reference.md`(Sapo 官方);仅模拟测试,无实时探测 |
| 🔵 | **组成** | 不是 Sapo 端点 — 内部聚合逻辑,通过单元测试逻辑测试 |
| 🚨 | **损坏** | 已知非功能性,参见注释 |
### Canary 监控端点(24 小时内检测到漂移)
| 资源 | 模式(s) | 端点 |
|---|---|---|
| store | all | `/admin/store.json` |
| products (读取) | pos-online, pos-counter | `/admin/products.json` |
| orders | pos-online, pos-counter | `/admin/orders.json` |
| customers | pos-online, pos-counter | `/admin/customers.json` |
| inventory_levels | pos-online, pos-counter | `/admin/inventory_levels.json` |
| locations | pos-counter | `/admin/locations.json` |
| draft_orders | pos-online | `/admin/draft_orders.json` |
| price_rules | pos-online | `/admin/price_rules.json` |
| pages | web | `/admin/pages.json` |
| suppliers | pos-counter | `/admin/suppliers.json` |
| stock_transfers | pos-counter | `/admin/stock_transfers.json` |
| payment_methods | pos-counter | `/admin/payment_methods.json` |
### 🚨 损坏 — 需要调查
| 工具 | 资源 | 问题 |
|---|---|---|
| `list_pos_shifts` | pos_shifts | `/admin/pos_shifts.json` 返回 `Content-Type: text/html`(Sapo POS 网页 shell),而不是 JSON。 |
| `get_pos_shift` | pos_shifts | 与上述相同。JSON API 端点尚未找到。 |
这 2 个工具可能会在运行时失败。POS 班次管理目前需要管理员 UI。
### 每个工具的状态
点击每个部分以展开完整的工具列表和状态图标。
<details>
<summary><b>pos-online — 51 种工具(使用 `SAPO_ALLOW_OPS=*`)</b></summary>
**客户** (7)
- ✅ `list_customers`,`get_customer`,`search_customers`,`count_customers`,`list_customer_orders`
- 🟢 `create_customer`,`update_customer`
**客户地址** (4)
- 🟡 `list_customer_addresses`,`add_customer_address`,`update_customer_address`,`set_default_customer_address`
**产品(读取)** (4)
- ✅ `list_products`,`get_product`,`search_products`,`count_products`
**变体(读取)** (2)
- 🟡 `list_variants_for_product`,`get_variant`
**库存(读取)** (1)
- ✅ `get_inventory_levels`
**订单** (4)
- ✅ `list_orders`,`get_order`,`count_orders`,`search_orders`
**订单交易** (2)
- 🟢 `list_order_transactions`,`create_order_transaction`
**履约** (4)
- 🟢 `list_fulfillments_for_order`,`get_fulfillment`
- 🟡 `create_fulfillment`,`update_fulfillment_tracking`
**退款** (3)
- 🟢 `list_refunds`,`get_refund`,`create_refund` *(create_refund 破坏性:`SAPO_ALLOW_OPS=refund`)*
**草稿订单** (7)
- ✅ `list_draft_orders`,`get_draft_order`
- 🟡 `create_draft_order`,`update_draft_order`,`complete_draft_order`,`send_draft_order_invoice`,`delete_draft_order` *(破坏性:`delete`)*
**价格规则** (5)
- ✅ `list_price_rules`,`get_price_rule`
- 🟡 `create_price_rule`,`update_price_rule`,`delete_price_rule` *(破坏性:`delete`)*
**折扣代码** (3)
- 🟡 `list_discount_codes`,`create_discount_code`,`delete_discount_code` *(破坏性:`delete`)*
**破坏性(取消/删除-严格)** (4)
- 🟡 `cancel_order`,`close_order`,`cancel_fulfillment` *(破坏性:`cancel`)*
- 🟡 `delete_customer`,`delete_variant` *(破坏性:`delete_strict`)*
</details>
<details>
<summary><b>web — 31 种工具</b></summary>
**商店** (1)
- ✅ `get_store_info`
**文章** (5)
- 🟡 `list_articles`,`get_article`,`create_article`,`update_article`,`delete_article` *(破坏性:`delete`)*
**博客** (5)
- 🟡 `list_blogs`,`get_blog`,`create_blog`,`update_blog`,`delete_blog` *(破坏性:`delete`)*
**页面** (4)
- ✅ `list_pages`,`get_page`
- 🟡 `update_page_seo`,`delete_page` *(破坏性:`delete`)*
**集合** (10)
- 🟡 `list_custom_collections`,`get_custom_collection`,`create_custom_collection`,`update_custom_collection`,`delete_custom_collection` *(破坏性:`delete`)*
- 🟡 `list_smart_collections`,`get_smart_collection`
- 🟡 `list_collects`,`create_collect`,`delete_collect` *(破坏性:`delete`)*
**脚本标签** (3)
- 🟡 `list_script_tags`,`create_script_tag`,`delete_script_tag` *(破坏性:`delete`)*
**产品 SEO** (1)
- 🟡 `update_product_seo`
**变体(读取,共用)** (2)
- 🟡 `list_variants_for_product`,`get_variant`
</details>
<details>
<summary><b>pos-counter — 15 种工具</b></summary>
**地点** (2)
- ✅ `list_locations`,`get_location`
**支付方式** (1)
- ✅ `list_payment_methods`
**库存(写入)** (3)
- 🟡 `adjust_inventory_level`,`connect_inventory_level`
- 🟡 `set_inventory_level` *(破坏性:`inventory_set`)*
**变体(写入)** (1)
- 🟡 `update_variant`
**POS 订单** (2)
- ✅ `list_pos_orders`,`get_pos_order` *(使用 `/admin/orders?source_name=pos`)*
**供应商** (2)
- ✅ `list_suppliers`,`get_supplier`
**库存转移** (2)
- ✅ `list_stock_transfers`,`get_stock_transfer`
**POS 班次** (2)
- 🚨 `list_pos_shifts`,`get_pos_shift` *(参见上面的损坏部分 — 端点返回 HTML)*
</details>
<details>
<summary><b>analytics — 10 种工具</b></summary>
所有 10 个都是 🔵 组成的(聚合多个 Sapo 端点,无单个端点验证):
`revenue_summary`,`top_products`,`top_customers`,`customer_ltv`,`tax_summary`,`online_vs_counter_breakdown`,`discount_usage_report`,`shift_report`,`inventory_low_stock`,`inventory_value`
</details>
## 破坏性操作
默认情况下,破坏性工具(取消,删除,批量删除)被阻止。要启用特定类别:
```bash
# 仅允许订单取消和标准删除
SAPO_ALLOW_OPS=cancel,delete npx sapo-mcp --mode=pos-online
```
支持的类别:`cancel`,`delete`,`delete_strict`,`inventory_set`,`refund`,`shift_close`,`cashbook_write`.
所有破坏性工具调用也需要 `confirm: true` 在工具参数中 — 防止在 LLM 调用工具时意外执行。
## 安全
ENV 凭证对其他进程可见 `ps` / `/proc/<pid>/environ` 在共享主机上。使用 `SAPO_API_SECRET_FILE` 通过文件传递密钥而不是 env 变量。
注意:完整的密钥文件隔离(仅在启动时读取密钥,然后清除)是 1.0 后路线图跟踪。
## 探测
验证哪些 Sapo API 端点在您的商店配置之前可用:
```bash
# 只读探测 — 对任何商店安全运行(仅 GET)
SAPO_STORE=mystore SAPO_API_KEY=xxx SAPO_API_SECRET=yyy npm run probe
# 模式漂移检查 — 同上探测 + Zod 验证固定装置
npm run canary
```
写入探测(`npm run probe:write`)除非 `SAPO_STORE` 包含 `test`、`dev` 或 `sandbox` — 永远不要生产。
## HTTP 传输(远程 / Docker)
作为 HTTP 服务器运行远程 MCP 客户端(例如 GoClaw)或自托管 Docker:
```bash
```bash
# 本地仅限(无需身份验证)
sapo-mcp --mode=pos-online --transport=http --port=3333
# 公开绑定(需要身份令牌)
SAPO_HTTP_HOST=0.0.0.0 \
SAPO_MCP_AUTH_TOKEN=$(openssl rand -hex 32) \
sapo-mcp --mode=pos-online --transport=http
```
端点:
| 方法 | 路径 | 描述 |
|--------|------|-------------|
| `GET` | `/health` | 活动探测 — 返回 `{ status, version, modes, sessions }` |
| `POST` | `/mcp` | 流式 HTTP 上的 JSON-RPC(在 `initialize` 上创建会话) |
| `GET` | `/mcp` | 现有会话的 SSE 长轮询(`mcp-session-id` 头) |
| `DELETE` | `/mcp` | 终止会话 |
**会话模型:** 每个 MCP 客户端获得一个 UUID 会话,由一个 `McpServer` 实例隔离。空闲会话(`SAPO_HTTP_SESSION_IDLE_MS`)会自动被驱逐。并发会话上限为 `SAPO_HTTP_MAX_SESSIONS`(满时返回 503)。
**安全性:**
- 默认绑定到 `127.0.0.1` — 仅限循环。令牌可选。
- 设置 `SAPO_HTTP_HOST=0.0.0.0`(或任何非循环地址) **需要** `SAPO_MCP_AUTH_TOKEN`。否则服务器将拒绝启动。
- CORS 默认情况下 **关闭**。通过 `SAPO_HTTP_CORS_ORIGINS` 启用每个来源(CSV 来源,或 `*` 表示所有)。仅在为基于浏览器的代理提供服务时启用。
### Docker
参见 [`examples/Dockerfile`](examples/Dockerfile) 和
[`examples/docker-compose.yml`](examples/docker-compose.yml)。
```bash
docker build -f examples/Dockerfile -t sapo-mcp:local .
docker run --rm -p 3333:3333 \
-e SAPO_STORE=mystore \
-e SAPO_API_KEY=xxx -e SAPO_API_SECRET=yyy \
-e SAPO_HTTP_HOST=0.0.0.0 \
-e SAPO_MCP_AUTH_TOKEN=$(openssl rand -hex 32) \
sapo-mcp:local
```
## 开发
```bash
npm install
npm run typecheck # 类型检查
npm run lint # 校验
npm run test # 运行测试
npm run build # 构建发布
```
## 1.0 后路线图
1.0.0 稳定版本截止点取决于以下事项,已从此版本推迟:
- **MCP 资源** — `sapo://shop/info`,`sapo://orders/today`,`sapo://orders/pending`,`sapo://inventory/low-stock`。大量数据通过资源比重复工具调用更高效。
- **MCP 提示** — 模板化工作流(`respond_to_complaint`,`weekly_report`,`seo_optimize_product`,`customer_followup`)。
- **Webhooks 接收器** — 子包显示 Sapo webhooks 为 MCP 事件。
- **OAuth 2.0 合作伙伴应用** — 多租户 SaaS 部署。解锁 5 个仅限内部的端点和 4 个延迟的财务/PO 报告(`cashflow_summary`,`pnl_summary`,`supplier_purchase_summary`,`daily_pos_report`)。
- **Storefront GraphQL 模块** — 验证私有应用访问;如果可用,则作用域工具。
## 变更日志
参见 [CHANGELOG.md](CHANGELOG.md) 了解每个版本的更新历史。
## 许可证
MIT — 参见 [LICENSE](LICENSE)
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器