Model Context Protocol server cho nền tảng POS & e-commerce Sapo.vn. Single-tenant, stdio + Streamable HTTP, destructive ops gated bởi env flags. Dưới đây là toàn bộ những gì bộ MCP này phơi ra cho LLM.
Ba cách dùng: npx (khuyến nghị cho MCP client), global, hoặc local dependency. Yêu cầu Node 20+.
# Pull latest, no install
npx -y sapo-mcp@latest --version
npm install -g sapo-mcp sapo-mcp --help
npm install sapo-mcp npx sapo-mcp --mode=pos-online
{
"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"
}
}
}
}
Dùng được cả Cursor (~/.cursor/mcp.json) và MCP Inspector. Tools xuất hiện dưới biểu tượng plug 🔌 sau khi restart client.
Mỗi mode = một tập tools rời nhau (trừ 2 read-only variant tools dùng chung giữa pos-online và web). Bật nhiều mode bằng CSV: --mode=pos-online,web,analytics.
Online orders, customers, fulfillment, refunds, draft orders, price rules, discount codes.
Storefront content: blogs, articles, pages, collections, SEO, script tags.
Quầy POS vật lý: locations, inventory write, suppliers, stock transfers, shifts.
?source_name=pos), suppliers, stock transfersComposed reports — không phải endpoint Sapo gốc, mà aggregate từ nhiều endpoint với auto-pagination.
pos-counter exclude 5 endpoint internal-only (purchase_orders, purchase_returns, stock_adjustments, cash_transactions, cashbook) — Private App trả 403, cần OAuth Partner App (post-1.0). Analytics auto-paginate đến SAPO_MAX_AUTO_PAGES; vượt ngưỡng → truncated: true.
Ký hiệu trạng thái: ● canary-monitored, ● live-verified, ● docs-only, ● composed, ● broken. Tool có nhãn destructive yêu cầu cả SAPO_ALLOW_OPS phù hợp lẫn confirm: true trong args.
5 cấp độ verification phản ánh độ chắc chắn schema khớp Sapo API. Canary nightly probe phát hiện drift trong 24h.
.github/workflows/canary.ymldocs/sapo-api-reference.md chính thức, mock test, chưa probe livelist_pos_shifts, get_pos_shift trả HTML thay vì JSON| Resource | Mode(s) | Endpoint |
|---|---|---|
| store | all | /admin/store.json |
| products (read) | 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 và get_pos_shift hit /admin/pos_shifts.json nhưng nhận về Content-Type: text/html (Sapo POS web app shell). JSON API endpoint chưa tìm được. POS shift management hiện cần admin UI.
Mặc định mọi tool destructive (cancel, delete, set inventory, refund) đều bị block. Bật từng category qua SAPO_ALLOW_OPS, đồng thời mỗi call vẫn cần confirm: true trong args để tránh LLM nhỡ tay.
| Category | Tools | Phạm vi |
|---|---|---|
cancel | cancel_order, close_order, cancel_fulfillment | Hủy đơn / fulfillment |
delete | delete_article, delete_blog, delete_page, delete_*_collection, delete_collect, delete_script_tag, delete_draft_order, delete_price_rule, delete_discount_code | Xóa content / metadata |
delete_strict | delete_customer, delete_variant | Xóa entity quan trọng (data loss) |
inventory_set | set_inventory_level | Ghi đè tuyệt đối tồn kho (mutate vs adjust) |
refund | create_refund | Hoàn tiền — tài chính |
shift_close | (reserved) | Đóng ca POS — chưa active |
cashbook_write | (reserved) | Sổ quỹ — chưa active (post-1.0) |
# Allow order cancel + standard deletes SAPO_ALLOW_OPS=cancel,delete npx sapo-mcp --mode=pos-online # Wildcard (chỉ dùng môi trường dev/test) SAPO_ALLOW_OPS=*
Toàn bộ knob cấu hình. Một trong SAPO_API_SECRET hoặc SAPO_API_SECRET_FILE là bắt buộc — file mode an toàn hơn vì không lộ qua ps//proc.
| Flag | Default | Description |
|---|---|---|
--mode=<modes> | pos-online | CSV danh sách modes |
--transport=<t> | stdio | stdio hoặc http |
--port=<n> | 3333 | HTTP port (bỏ qua nếu stdio) |
--help | — | In usage |
--version | — | In version |
| Variable | Required | Default | Description |
|---|---|---|---|
SAPO_STORE | yes | — | Store subdomain |
SAPO_API_KEY | yes | — | Private App key |
SAPO_API_SECRET | yes* | — | Private App secret |
SAPO_API_SECRET_FILE | yes* | — | File chứa secret (ưu tiên hơn env) |
SAPO_ALLOW_OPS | no | "" | CSV destructive categories |
SAPO_MAX_AUTO_PAGES | no | 10 | Max auto-pagination pages |
SAPO_RETRY_MAX | no | 3 | HTTP retry attempts |
SAPO_LOG_LEVEL | no | info | error / warn / info / debug / trace |
SAPO_HTTP_HOST | no† | 127.0.0.1 | HTTP bind host |
SAPO_HTTP_PORT | no | 3333 | HTTP port |
SAPO_HTTP_MAX_SESSIONS | no | 100 | Max concurrent MCP sessions |
SAPO_HTTP_SESSION_IDLE_MS | no | 1800000 | Idle session GC (30 min) |
SAPO_MCP_AUTH_TOKEN | no† | — | Bearer token; bắt buộc nếu host non-loopback |
SAPO_HTTP_CORS_ORIGINS | no | — | CSV CORS origins (default: off) |
* Một trong hai bắt buộc. † HTTP-only; token enforce khi host khác 127.0.0.1 / localhost / ::1.
stdio cho MCP client local (Claude Desktop, Cursor). HTTP cho remote agents, Docker, GoClaw — bind loopback mặc định, public bind yêu cầu auth token.
| Method | Path | Description |
|---|---|---|
GET | /health | Liveness probe — { status, version, modes, sessions } |
POST | /mcp | JSON-RPC over Streamable HTTP (init session) |
GET | /mcp | SSE long-poll (header mcp-session-id) |
DELETE | /mcp | Terminate session |
# Local-only (no auth)
sapo-mcp --mode=pos-online \
--transport=http --port=3333
# Public bind — token required SAPO_HTTP_HOST=0.0.0.0 \ SAPO_MCP_AUTH_TOKEN=$(openssl rand -hex 32) \ sapo-mcp --mode=pos-online --transport=http
Session model: mỗi MCP client một UUID session, isolated bằng McpServer instance. Idle session vượt SAPO_HTTP_SESSION_IDLE_MS bị evict tự động. Concurrent cap SAPO_HTTP_MAX_SESSIONS → 503 khi đầy. CORS off mặc định, bật bằng SAPO_HTTP_CORS_ORIGINS (CSV hoặc *).
Có sẵn examples/Dockerfile + examples/docker-compose.yml để tự host.
Trước khi cấu hình client, verify endpoint nào available trên store của bạn. Write-probe có safeguard: chỉ chạy nếu SAPO_STORE chứa test, dev hoặc sandbox.
# Read-only probe — safe, GET only SAPO_STORE=mystore SAPO_API_KEY=xxx SAPO_API_SECRET=yyy npm run probe # Schema drift check (probe + Zod validate vs fixtures) npm run canary # Write probe — chỉ chạy được trên test/dev/sandbox stores npm run probe:write
Pre-1.0 nên tool name & schema có thể đổi giữa các minor bump. Các hạng mục dưới đây là gating cho 1.0.0:
sapo://shop/info, sapo://orders/today, sapo://orders/pending, sapo://inventory/low-stock — read-heavy data dùng Resource hiệu quả hơn tool call lặp.
Templated workflows: respond_to_complaint, weekly_report, seo_optimize_product, customer_followup.
Sub-package surface Sapo webhooks thành MCP events.
Multi-tenant SaaS. Mở khóa 5 internal-only endpoints (purchase_orders, purchase_returns, stock_adjustments, cash_transactions, cashbook) + 4 finance/PO reports đang hoãn.
Verify Private App access cho GraphQL Storefront API; scope tools nếu khả dụng.
Đọc secret duy nhất lúc startup rồi clear khỏi memory — tracked nhưng chưa land.