sapo-mcp
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| SAPO_STORE | Yes | Store subdomain | |
| SAPO_API_KEY | Yes | Private App API Key | |
| SAPO_ALLOW_OPS | No | CSV of allowed destructive categories | |
| SAPO_HTTP_HOST | No | HTTP bind host (loopback by default) | 127.0.0.1 |
| SAPO_HTTP_PORT | No | HTTP port | 3333 |
| SAPO_LOG_LEVEL | No | Log level (error/warn/info/debug/trace) | info |
| SAPO_RETRY_MAX | No | HTTP retry attempts | 3 |
| SAPO_API_SECRET | No | Private App API Secret (or use SAPO_API_SECRET_FILE) | |
| SAPO_MAX_AUTO_PAGES | No | Max auto-pagination pages | 10 |
| SAPO_MCP_AUTH_TOKEN | No | Bearer token. Required if host is non-loopback | |
| SAPO_API_SECRET_FILE | No | Path to file containing secret (takes precedence) | |
| SAPO_HTTP_CORS_ORIGINS | No | CSV of allowed CORS origins (default: disabled) | |
| SAPO_HTTP_MAX_SESSIONS | No | Max concurrent MCP sessions | 100 |
| SAPO_HTTP_SESSION_IDLE_MS | No | Idle session GC threshold (30 min) | 1800000 |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": true
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| list_customersA | List customers with optional filters. Returns paginated results via since_id cursor. If has_more=true, call again with next_since_id. |
| get_customerA | Get a single customer by ID, including their address list and order count. |
| search_customersA | Search customers by query string (matches email, phone, name). Returns paginated list. |
| count_customersA | Count total customers in the store, optionally filtered by creation date. |
| list_customer_ordersA | List all orders placed by a specific customer. Returns paginated results via since_id cursor. |
| create_customerA | Create a new customer. Must provide either email OR phone (or both). Optionally include addresses array for inline address creation. Returns the created customer including auto-generated id. |
| update_customerA | Update an existing customer. Only provided fields are modified. Use add_customer_address / update_customer_address tools for address management. |
| list_customer_addressesA | List all saved addresses for a customer, including default address flag and Vietnamese province/district/ward fields. |
| add_customer_addressA | Add a new address to a customer. Required: address1, city, country. Province handling: pass either |
| update_customer_addressA | Update an existing customer address. Only provided fields are modified. To set this address as default, use set_default_customer_address (Sapo dedicated endpoint). IMPORTANT: When changing subdivision fields, pass BOTH the text name AND the code (e.g. province + province_code together) — codes alone are silently dropped. Sapo write API only accepts the pre-2025 3-tier schema; new 2-tier addresses cannot be written via this endpoint (returns 422 "Ward is not supported"). |
| set_default_customer_addressA | Set a customer's default address via Sapo's dedicated endpoint (PUT /customers/{id}/addresses/{addr_id}/default.json). Returns the address now marked default. |
| list_provincesA | List Vietnamese provinces. Default (omit level) = level=3 = pre-2025 63 tỉnh, 3-tier. Use level=2 for post-2025 34 tỉnh, 2-tier (after merger). Province codes differ between schemas: level=3 codes are "1"–"63"; level=2 codes start at "2001". WORKFLOW: For new schema → list_provinces({level:2}) then list_wards({level:2, province_code}). For old schema → list_provinces() → list_districts({province_code}) → list_wards({district_code}). NOTE: Sapo write endpoints (add/update_customer_address) currently accept ONLY level=3 codes; level=2 is read-only as of 2026-05. |
| list_districtsA | List districts (Quận/Huyện) within a province. Only meaningful for level=3 (pre-2025 3-tier schema, default). With level=2 the response is empty because the district level was abolished on 2025-07-01. |
| list_wardsA | List wards (Phường/Xã). For level=3 (default, 3-tier) pass district_code obtained from list_districts. For level=2 (2-tier post-reform) pass province_code obtained from list_provinces({level:2}). Post-reform wards attach directly to province — their district_code is the sentinel "-1". |
| list_productsA | List products with optional filters (status, vendor, product_type). Returns paginated results via since_id cursor. If has_more=true, call again with next_since_id. |
| get_productB | Get a single product by ID, including its variants, options, and images. |
| search_productsA | Search products by title substring. Uses the title filter on the list endpoint. Returns paginated results. |
| count_productsA | Count total products in the store, optionally filtered by status, vendor, or product_type. |
| list_variants_for_productA | List all variants for a product (SKUs, prices in VND, inventory quantities). Returns paginated results via since_id cursor. |
| get_variantA | Get a single product variant by ID. Returns price (VND, float with 4 decimals), SKU, barcode, inventory quantity, and option values. |
| get_inventory_levelsA | Get inventory levels (available + committed quantities) for specific variants at specific locations. Filter by location_id, inventory_item_id, or both. |
| list_ordersA | List orders with optional filters. Returns paginated results via since_id cursor. Filter by status, financial_status, fulfillment_status, or source_name (facebook, web, pos). If has_more=true, call again with next_since_id. |
| get_orderA | Get a single order by ID. Returns full order including line_items, fulfillments, customer, billing/shipping address, and financial details. |
| count_ordersA | Count total orders, optionally filtered by status, financial_status, or date range. Returns { count: N }. |
| search_ordersA | Search orders by name (order #), customer email, or customer phone. Uses filter params on the orders list endpoint. Returns paginated results. |
| update_orderA | Update an existing order via PUT /admin/orders/{id}.json. Supports: tags, note, note_attributes, email, buyer_accepts_marketing. Verified live 2026-05-01. NOTE: The |
| list_order_transactionsA | List all transactions for a specific order. Returns payment attempts, captures, refunds, and voids linked to the order. |
| create_order_transactionA | Create a transaction for an order (e.g. capture, sale, refund). Side effect: creates a Transaction record and may change order financial_status. kind: authorization | capture | sale | void | refund. |
| list_fulfillments_for_orderA | List all fulfillments for a specific order. Returns fulfillment records with tracking info, line_items, and delivery status. |
| get_fulfillmentA | Get a single fulfillment by ID. Returns full fulfillment with tracking info, line_items, and origin address. |
| create_fulfillmentA | Create a fulfillment for an order, optionally specifying line items and tracking info. Side effect: creates a Fulfillment record and marks specified line_items as fulfilled. |
| update_fulfillment_trackingA | Update tracking information for an existing fulfillment. Side effect: modifies the Fulfillment tracking_company, tracking_number, or tracking_url. |
| list_draft_ordersA | List draft orders with optional filters. Returns paginated results via since_id cursor. Filter by status. If has_more=true, call again with next_since_id. |
| get_draft_orderA | Get a single draft order by ID. Returns full draft order including line_items, customer, address, and applied discounts. |
| create_draft_orderA | Create a new draft order. Side effect: creates a DraftOrder in "open" status. Requires at least one line_item with variant_id or title+price for custom items. |
| update_draft_orderA | Update a draft order in "open" status. Side effect: modifies draft order fields. Cannot update completed or cancelled drafts. |
| complete_draft_orderA | Complete a draft order and convert it into a real order. Side effect: creates an Order from the draft; draft status becomes "completed". Use payment_pending=true if payment not yet collected. |
| send_draft_order_invoiceA | Send an invoice email for a draft order. Side effect: sends email to customer; draft status becomes "invoice_sent". Requires customer email on the draft or provide via to param. |
| list_price_rulesA | List price rules (discount rules) with optional filters. Returns paginated results via since_id cursor. Filter by status (active, archived, scheduled). |
| get_price_ruleA | Get a single price rule by ID. Returns full price rule including value_type, value (string), entitled/prerequisite IDs, and usage stats. |
| create_price_ruleA | Create a new price rule (discount rule). Side effect: creates a PriceRule record. value must be a STRING (e.g. "-10.0" for 10% off). title, value_type, value, target_type, allocation_method, customer_selection, target_selection are required. |
| update_price_ruleA | Update an existing price rule. Side effect: modifies the price rule. Only provided fields are updated. value must remain a string if updating. |
| list_discount_codesA | List discount codes for a specific price rule. Returns paginated results via since_id cursor. Must provide price_rule_id. |
| create_discount_codeA | Create a discount code for a price rule. Side effect: creates a DiscountCode that customers can apply at checkout. Code must be unique across the store. |
| list_refundsA | List refunds for a specific order. Returns full refund records with associated transactions, refund line items, and order adjustments. |
| get_refundA | Get a single refund by ID. Returns full refund record. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
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