AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
MCP verified MIT Self-run

Sapo MCP

mcp-nguyennguyenit-sapo-mcp · by nguyennguyenit

Model Context Protocol server for Sapo.vn POS & e-commerce — 105 tools across 4 modes, stdio + Streamable HTTP, single-tenant Private App.

No reviews yet
0 installs
5 views
0.0% view→install

Install

$ agentstack add mcp-nguyennguyenit-sapo-mcp

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/mcp-nguyennguyenit-sapo-mcp)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
3mo ago

Declared compatibility

Claude CodeClaude DesktopCursorWindsurf

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Sapo MCP? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

sapo-mcp

[](https://www.npmjs.com/package/sapo-mcp) [](LICENSE) [](https://nodejs.org)

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 web
  • Two 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 require confirm: true
  • Single-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](#post-10-roadmap).

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 --version

Option B — global install

npm install -g sapo-mcp
sapo-mcp --version
sapo-mcp --help

Option C — local project dependency

npm install sapo-mcp
npx sapo-mcp --mode=pos-online

Quick Start

1. Get Credentials

Create a Private App at developers.sapo.vn:

  • Store name: mystorenamemystorename.mysapo.net
  • API 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-online

Open 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 | |------|---------|-------------| | --mode= | pos-online | Comma-separated list of modes to activate | | --transport= | stdio | Transport type (stdio or http) | | --port= | 3333 | HTTP port (ignored for stdio) | | --help | — | Print usage and exit | | --version | — | Print version and exit |

Environment Variables

| Variable | Required | Default | Description | |----------|----------|---------|-------------| | SAPO_STORE | Yes | — | Store subdomain | | SAPO_API_KEY | Yes | — | Private App API Key | | SAPO_API_SECRET | Yes | — | Private App API Secret | | SAPO_API_SECRET_FILE | Yes | — | Path to file containing secret (takes precedence) | | SAPO_ALLOW_OPS | No | "" | CSV of allowed 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 | Log level (error/warn/info/debug/trace) | | SAPO_HTTP_HOST | No† | 127.0.0.1 | HTTP bind host (loopback by default) | | 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 threshold (30 min) | | SAPO_MCP_AUTH_TOKEN | No† | — | Bearer token. Required if host is non-loopback | | SAPO_HTTP_CORS_ORIGINS | 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 | |------|--------|-------------| | pos-online | 0.5.0 | Online orders, customers, fulfillment (51 tools) | | web | 0.5.0 | Storefront, collections, articles, SEO (31 tools) | | pos-counter | 0.5.0 | POS counter: locations, inventory write, suppliers, shifts, stock transfers (15 tools) | | analytics | 0.5.0 | Composed reports: revenue, top products/customers, LTV, tax, channel breakdown, discount usage, shift report (10 tools) |

> Note: pos-counter excludes 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 carry truncated: true when 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 .github/workflows/canary.yml | | 🟢 | Live-verified | Endpoint hit during development, schema captured to fixture, not in daily canary | | 🟡 | Docs-only | Schema from docs/sapo-api-reference.md (Sapo official); mock tests only, no live probe | | 🔵 | 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 | /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 | | inventorylevels | pos-online, pos-counter | /admin/inventory_levels.json | | locations | pos-counter | /admin/locations.json | | draftorders | pos-online | /admin/draft_orders.json | | pricerules | pos-online | /admin/price_rules.json | | pages | web | /admin/pages.json | | suppliers | pos-counter | /admin/suppliers.json | | stocktransfers | pos-counter | /admin/stock_transfers.json | | payment_methods | pos-counter | /admin/payment_methods.json |

🚨 Broken — needs investigation

| Tool | Resource | Issue | |---|---|---| | list_pos_shifts | posshifts | /admin/pos_shifts.json returns Content-Type: text/html (Sapo POS web app shell), not JSON. | | get_pos_shift | posshifts | 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.

pos-online — 51 tools (with SAPO_ALLOW_OPS=*)

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)

web — 31 tools

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

pos-counter — 15 tools

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)

analytics — 10 tools

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-online

Supported 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//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 canary

Write-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=http

Endpoints:

| Method | Path | Description | |--------|------|-------------| | GET | /health | Liveness probe — returns { status, version, modes, sessions } | | POST | /mcp | JSON-RPC over Streamable HTTP (creates a session on initialize) | | GET | /mcp | SSE long-poll for an existing session (mcp-session-id header) | | DELETE | /mcp | 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) requires

SAPO_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](examples/Dockerfile) and [examples/docker-compose.yml](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:local

Development

npm install
npm run typecheck   # Type check
npm run lint        # Lint
npm run test        # Run tests
npm run build       # Build for release

Post-1.0 roadmap

The 1.0.0 stable cut is gated on the following items, deferred from this release:

  • MCP Resourcessapo://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-counter and 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](CHANGELOG.md) for the per-version history.

License

MIT — See [LICENSE](LICENSE)

Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.