sapo-mcp
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@sapo-mcpshow my recent orders"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
sapo-mcp
Model Context Protocol server for Sapo.vn POS & e-commerce platform.
Features
4 modes, 105 unique tools:
pos-online(51),web(31),pos-counter(15),analytics(10) — 2 read tools shared between pos-online and webTwo transports: stdio (Claude Desktop, Cursor) and Streamable HTTP (Docker, GoClaw)
Safe by default: destructive ops gated via
SAPO_ALLOW_OPS(default: none); all destructive calls also requireconfirm: trueSingle-tenant: one shop per server instance via Private App credentials
Pre-1.0: tool names and schemas may shift on minor bumps. See Post-1.0 roadmap.
Related MCP server: Saleor MCP Server
Installation
Requires Node.js 20 or newer. Verify with node --version.
Option A — npx (no install)
Recommended for MCP clients (Claude Desktop, Cursor). Always pulls the latest published version:
npx -y sapo-mcp@latest --versionOption B — global install
npm install -g sapo-mcp
sapo-mcp --version
sapo-mcp --helpOption C — local project dependency
npm install sapo-mcp
npx sapo-mcp --mode=pos-onlineQuick Start
1. Get Credentials
Create a Private App at developers.sapo.vn:
Store name:
mystorename→mystorename.mysapo.netAPI Key + Secret
2. Configure your MCP client
Claude Desktop
Edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%/Claude/claude_desktop_config.json (Windows):
{
"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"
}
}
}
}Restart Claude Desktop. Tools appear under the 🔌 plug icon.
Cursor
Edit ~/.cursor/mcp.json or per-workspace .cursor/mcp.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 (test/debug)
npx @modelcontextprotocol/inspector \
-e SAPO_STORE=mystorename \
-e SAPO_API_KEY=xxx \
-e SAPO_API_SECRET=yyy \
npx -y sapo-mcp --mode=pos-onlineOpen the printed URL in a browser to inspect/invoke registered tools.
Use --mode=pos-online,web,analytics to register multiple modes (union of tools; shared tools registered once).
3. CLI Flags
Flag | Default | Description |
|
| Comma-separated list of modes to activate |
|
| Transport type ( |
|
| HTTP port (ignored for stdio) |
| — | Print usage and exit |
| — | Print version and exit |
Environment Variables
Variable | Required | Default | Description |
| Yes | — | Store subdomain |
| Yes | — | Private App API Key |
| Yes* | — | Private App API Secret |
| Yes* | — | Path to file containing secret (takes precedence) |
| No |
| CSV of allowed destructive categories |
| No |
| Max auto-pagination pages |
| No |
| HTTP retry attempts |
| No |
| Log level (error/warn/info/debug/trace) |
| No† |
| HTTP bind host (loopback by default) |
| No |
| HTTP port |
| No |
| Max concurrent MCP sessions |
| No |
| Idle session GC threshold (30 min) |
| No† | — | Bearer token. Required if host is non-loopback |
| No | — | CSV of allowed CORS origins (default: disabled) |
*One of SAPO_API_SECRET or SAPO_API_SECRET_FILE is required.
†HTTP-only. Token is enforced when SAPO_HTTP_HOST is not 127.0.0.1/localhost/::1.
Modes
Mode | Status | Description |
| 0.5.0 | Online orders, customers, fulfillment (51 tools) |
| 0.5.0 | Storefront, collections, articles, SEO (31 tools) |
| 0.5.0 | POS counter: locations, inventory write, suppliers, shifts, stock transfers (15 tools) |
| 0.5.0 | Composed reports: revenue, top products/customers, LTV, tax, channel breakdown, discount usage, shift report (10 tools) |
Note:
pos-counterexcludes 5 internal-only endpoints (purchase_orders,purchase_returns,stock_adjustments,cash_transactions,cashbook) — these return HTTP 403 for Private App credentials and require an OAuth Partner App (post-1.0 roadmap).Analytics tools auto-paginate up to
SAPO_MAX_AUTO_PAGES; results carrytruncated: truewhen the cap is hit.
Tool Verification Status
Verification levels for the 105 unique tools (last updated 2026-04-30):
Symbol | Level | What it means |
✅ | Canary-monitored | Endpoint + schema verified live; daily nightly probe via |
🟢 | Live-verified | Endpoint hit during development, schema captured to fixture, not in daily canary |
🟡 | Docs-only | Schema from |
🔵 | Composed | Not a Sapo endpoint — internal aggregation logic, logic-tested via unit tests |
🚨 | Broken | Known non-functional, see notes |
Canary-monitored endpoints (drift detected within 24h)
Resource | Mode(s) | Endpoint |
store | all |
|
products (read) | pos-online, pos-counter |
|
orders | pos-online, pos-counter |
|
customers | pos-online, pos-counter |
|
inventory_levels | pos-online, pos-counter |
|
locations | pos-counter |
|
draft_orders | pos-online |
|
price_rules | pos-online |
|
pages | web |
|
suppliers | pos-counter |
|
stock_transfers | pos-counter |
|
payment_methods | pos-counter |
|
🚨 Broken — needs investigation
Tool | Resource | Issue |
| pos_shifts |
|
| pos_shifts | Same as above. JSON API endpoint not yet located. |
These 2 tools may fail at runtime. POS shift management currently requires admin UI.
Per-tool status
Click each section to expand the full tool list with status icons.
Customers (7)
✅
list_customers,get_customer,search_customers,count_customers,list_customer_orders🟢
create_customer,update_customer
Customer Addresses (4)
🟡
list_customer_addresses,add_customer_address,update_customer_address,set_default_customer_address
Products (read) (4)
✅
list_products,get_product,search_products,count_products
Variants (read) (2)
🟡
list_variants_for_product,get_variant
Inventory (read) (1)
✅
get_inventory_levels
Orders (4)
✅
list_orders,get_order,count_orders,search_orders
Order Transactions (2)
🟢
list_order_transactions,create_order_transaction
Fulfillments (4)
🟢
list_fulfillments_for_order,get_fulfillment🟡
create_fulfillment,update_fulfillment_tracking
Refunds (3)
🟢
list_refunds,get_refund,create_refund(create_refund destructive:SAPO_ALLOW_OPS=refund)
Draft Orders (7)
✅
list_draft_orders,get_draft_order🟡
create_draft_order,update_draft_order,complete_draft_order,send_draft_order_invoice,delete_draft_order(destructive:delete)
Price Rules (5)
✅
list_price_rules,get_price_rule🟡
create_price_rule,update_price_rule,delete_price_rule(destructive:delete)
Discount Codes (3)
🟡
list_discount_codes,create_discount_code,delete_discount_code(destructive:delete)
Destructive (cancel/delete-strict) (4)
🟡
cancel_order,close_order,cancel_fulfillment(destructive:cancel)🟡
delete_customer,delete_variant(destructive:delete_strict)
Store (1)
✅
get_store_info
Articles (5)
🟡
list_articles,get_article,create_article,update_article,delete_article(destructive:delete)
Blogs (5)
🟡
list_blogs,get_blog,create_blog,update_blog,delete_blog(destructive:delete)
Pages (4)
✅
list_pages,get_page🟡
update_page_seo,delete_page(destructive:delete)
Collections (10)
🟡
list_custom_collections,get_custom_collection,create_custom_collection,update_custom_collection,delete_custom_collection(destructive:delete)🟡
list_smart_collections,get_smart_collection🟡
list_collects,create_collect,delete_collect(destructive:delete)
Script Tags (3)
🟡
list_script_tags,create_script_tag,delete_script_tag(destructive:delete)
Products SEO (1)
🟡
update_product_seo
Variants (read, shared) (2)
🟡
list_variants_for_product,get_variant
Locations (2)
✅
list_locations,get_location
Payment Methods (1)
✅
list_payment_methods
Inventory (write) (3)
🟡
adjust_inventory_level,connect_inventory_level🟡
set_inventory_level(destructive:inventory_set)
Variants (write) (1)
🟡
update_variant
POS Orders (2)
✅
list_pos_orders,get_pos_order(uses/admin/orders?source_name=pos)
Suppliers (2)
✅
list_suppliers,get_supplier
Stock Transfers (2)
✅
list_stock_transfers,get_stock_transfer
POS Shifts (2)
🚨
list_pos_shifts,get_pos_shift(see Broken section above — endpoint returns HTML)
All 10 are 🔵 composed (aggregate from multiple Sapo endpoints, no single endpoint to verify):
revenue_summary, top_products, top_customers, customer_ltv, tax_summary, online_vs_counter_breakdown, discount_usage_report, shift_report, inventory_low_stock, inventory_value
Destructive Operations
Destructive tools (cancel, delete, bulk-delete) are blocked by default. To enable specific categories:
# Allow order cancellation and standard deletes only
SAPO_ALLOW_OPS=cancel,delete npx sapo-mcp --mode=pos-onlineSupported categories: cancel, delete, delete_strict, inventory_set, refund, shift_close, cashbook_write.
All destructive tool calls also require confirm: true in the tool arguments — this prevents accidental execution when an LLM calls the tool without explicit intent.
Security
ENV credentials are visible to other processes via ps / /proc/<pid>/environ on shared hosts. Use SAPO_API_SECRET_FILE to pass the secret via a file instead of an env var where possible.
Note: full secret-file isolation (reading the secret only at startup, then clearing) is tracked for the post-1.0 roadmap.
Probing
Verify which Sapo API endpoints are available on your store before configuring tools.
# Read-only probe — safe to run against any store (GET only)
SAPO_STORE=mystore SAPO_API_KEY=xxx SAPO_API_SECRET=yyy npm run probe
# Schema drift check — same probe + Zod validation against fixtures
npm run canaryWrite-probe (npm run probe:write) refuses to run unless SAPO_STORE contains test, dev, or sandbox — never against production.
HTTP Transport (Remote / Docker)
Run as an HTTP server for remote MCP clients (e.g. GoClaw) or self-hosted Docker:
# Local-only (no auth required)
sapo-mcp --mode=pos-online --transport=http --port=3333
# Public bind (auth token required)
SAPO_HTTP_HOST=0.0.0.0 \
SAPO_MCP_AUTH_TOKEN=$(openssl rand -hex 32) \
sapo-mcp --mode=pos-online --transport=httpEndpoints:
Method | Path | Description |
|
| Liveness probe — returns |
|
| JSON-RPC over Streamable HTTP (creates a session on |
|
| SSE long-poll for an existing session ( |
|
| Terminate a session |
Session model: Each MCP client gets a UUID session, isolated by an
McpServer instance. Idle sessions (SAPO_HTTP_SESSION_IDLE_MS) are
evicted automatically. Concurrent sessions cap at SAPO_HTTP_MAX_SESSIONS
(503 returned when full).
Security:
Defaults to
127.0.0.1— loopback only. Token optional.Setting
SAPO_HTTP_HOST=0.0.0.0(or any non-loopback) requiresSAPO_MCP_AUTH_TOKEN. The server refuses to start otherwise.CORS is off by default. Enable per-origin via
SAPO_HTTP_CORS_ORIGINS(CSV of origins, or*for all). Only enable when serving browser-based agents.
Docker
See examples/Dockerfile and
examples/docker-compose.yml.
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:localDevelopment
npm install
npm run typecheck # Type check
npm run lint # Lint
npm run test # Run tests
npm run build # Build for releasePost-1.0 roadmap
The 1.0.0 stable cut is gated on the following items, deferred from this release:
MCP Resources —
sapo://shop/info,sapo://orders/today,sapo://orders/pending,sapo://inventory/low-stock. Read-heavy data is more efficient as a Resource than repeated tool calls.MCP Prompts — templated workflows (
respond_to_complaint,weekly_report,seo_optimize_product,customer_followup).Webhook receiver — sub-package surfacing Sapo webhooks as MCP events.
OAuth 2.0 Partner App — multi-tenant SaaS deployments. Unlocks the 5 internal-only endpoints currently excluded from
pos-counterand 4 deferred finance/PO reports (cashflow_summary,pnl_summary,supplier_purchase_summary,daily_pos_report).Storefront GraphQL module — verify Private App access; scope tools if available.
Changelog
See CHANGELOG.md for the per-version history.
License
MIT — See LICENSE
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- FlicenseBqualityDmaintenanceA Model Context Protocol server that provides comprehensive tools for managing CS-Cart e-commerce stores, enabling product management, order handling, and sales analytics.123
- Flicense-qualityDmaintenanceA Model Context Protocol server that enables AI assistants to interact with Saleor e-commerce data including products, orders, customers, and more.3
- Alicense-qualityDmaintenanceModel Context Protocol (MCP) server wrapping the Pancake POS REST API, enabling AI assistants like Claude to manage Vietnamese e-commerce POS operations with 23 specialized tools and 7 reference resources.MIT
- Alicense-qualityCmaintenanceEnhanced Model Context Protocol (MCP) server for Odoo ERP with advanced tools for sales, purchases, inventory and accounting.MIT
Related MCP Connectors
A Model Context Protocol server for Wix AI tools
A comprehensive Model Context Protocol (MCP) server that enables AI assistants to interact with yo…
Vietnam MISA meInvoice: AI agents create, publish and query e-invoices, stateless BYO.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/nguyennguyenit/Sapo-MCP'
If you have feedback or need assistance with the MCP directory API, please join our Discord server