medusa-mcp
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| HOST | No | Listen host | 0.0.0.0 |
| PORT | No | Listen port | 3000 |
| DATA_DIR | No | Where OAuth clients and token hashes are stored | ./data |
| PUBLIC_URL | No | Public HTTPS origin of this server (without /mcp) | |
| TRUST_PROXY | No | Express trust proxy – number of proxies in front | 1 |
| MEDUSA_API_KEY | No | Secret API key (sk_…) | |
| OWNER_PASSWORD | No | Password required on the consent page | |
| REPORT_TIMEZONE | No | IANA timezone for date filters and report buckets | UTC |
| ACCESS_TOKEN_TTL | No | Access token lifetime in seconds | 3600 |
| MCP_STATIC_TOKEN | No | Optional static bearer token | |
| MEDUSA_READ_ONLY | No | Register read and report tools only | false |
| MEDUSA_TIMEOUT_MS | No | Timeout for Medusa requests | 20000 |
| REFRESH_TOKEN_TTL | No | Refresh token lifetime in seconds | 2592000 |
| MEDUSA_BACKEND_URL | No | Medusa backend URL | |
| ALLOWED_REDIRECT_HOSTS | No | Hosts OAuth clients may use as redirect targets | claude.ai,claude.com,localhost,127.0.0.1 |
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 |
|---|---|
| get_store_infoA | Returns regions (currencies), sales channels, stock locations, shipping options and profiles, and return/refund reasons. A good first call to learn the IDs other tools need. |
| list_ordersA | Lists orders, newest first. Filters: full-text, date range (YYYY-MM-DD in the reporting timezone), customer, order/payment/fulfillment status. |
| get_orderA | Full order detail – line items, addresses, payments (with captures and refunds), fulfillments, tracking numbers and returns. Accepts an order ID (order_…) or the order number. |
| create_fulfillmentA | Creates a fulfillment for an order. Without 'items' it fulfills all remaining unfulfilled quantities. Without 'location_id' it uses the only stock location, if there is exactly one. |
| create_shipmentB | Marks a fulfillment as shipped and attaches a tracking number. Without 'fulfillment_id' it uses the only unshipped fulfillment. |
| mark_deliveredA | Marks a fulfillment as delivered. Without 'fulfillment_id' it uses the only fulfillment that is not delivered yet. |
| cancel_fulfillmentA | Cancels a fulfillment that has not been shipped yet, so its items can be fulfilled again. Without 'fulfillment_id' it uses the only unshipped fulfillment. |
| complete_orderC | Marks the order as completed. |
| cancel_orderA | CANCELS the order. Irreversible – get explicit confirmation from the user before calling. The order must not have active fulfillments. |
| update_orderA | Changes the order's email, shipping or billing address, or metadata (e.g. an internal note). Send only what should change; an address replaces the whole previous address. |
| mark_order_paidA | Records a manual payment (e.g. a received bank transfer or cash on delivery) for the order's unpaid payment collection. Orders without one (e.g. converted draft orders) get a payment collection for the outstanding amount first. |
| capture_paymentA | Captures an authorized payment (charges the customer). Without 'amount' captures the full remaining amount. Without 'payment_id' uses the only payment that is not fully captured. |
| refund_paymentA | REFUNDS money to the customer through the payment provider. Irreversible – confirm the amount with the user before calling. Without 'payment_id' uses the only captured payment that can cover the amount. Refund reasons are listed by get_store_info. |
| create_returnA | Requests a return of order items (the customer is sending them back). Without 'items' returns every shipped item. When the parcel arrives, call receive_return. Refund the money separately with refund_payment. Return reasons are listed by get_store_info. |
| receive_returnA | Records that returned items arrived; they go back to stock. Without 'items' receives everything requested. Without 'return_id' uses the order's only open return. |
| create_draft_orderA | Creates a draft order on behalf of a customer (phone or e-mail orders, B2B). Items by variant_id or SKU (of published products), optionally with a custom unit price. Shipping options are listed by get_store_info. Turn the draft into a real order with convert_draft_order. |
| convert_draft_orderA | Turns a draft order into a regular order (reserves stock). Record the payment afterwards with mark_order_paid. |
| list_customersB | Searches customers by name, email or company, optionally within a customer group. |
| get_customerA | Customer detail with addresses, groups and order history (count, total spent, recent orders). |
| list_customer_groupsC | Customer groups (e.g. B2B, VIP) – used by price lists and promotions. |
| save_customerA | Without customer_id creates a customer (email required); with customer_id updates only the given fields. Can also add an address and add/remove the customer from groups. |
| save_customer_groupA | Without group_id creates a group (name required); with group_id renames it. Can add/remove customers. |
| delete_customer_groupA | DELETES a customer group (the customers stay). Price lists and promotions targeting it stop applying. Confirm with the user first. |
| list_productsA | Lists products with their variants (SKUs). Filter by full-text, status, collection, category or tag. |
| get_productB | Product detail – variants, prices in all currencies, linked inventory items, options, categories, collection, tags, images and sales channels. |
| create_productA | Creates a product with its variants and prices. For a simple product without options pass just 'prices' (and optionally 'sku', 'stock'). For variants define 'options' (e.g. Size: S, M, L) and one variant per combination. Defaults: status draft, the store's default sales channel, the default shipping profile. Category and collection IDs come from list_catalog. |
| update_productA | Updates product fields – texts, status, handle, images, collection, categories, tags, sales channels, metadata. Send only the fields that should change. Lists (category_ids, tags, images, sales_channel_ids) replace the previous list. |
| delete_productA | DELETES the product with all its variants. Irreversible – get explicit confirmation from the user before calling. 'confirm_title' must match the product title exactly. By default the inventory items of its variants are deleted too (only those with nothing reserved). |
| create_variantA | Adds a variant to an existing product, e.g. a new size. 'options' must name every product option; new option values are added automatically. |
| update_variantA | Updates variant fields – title, SKU, barcodes, inventory tracking, backorders, weight, metadata. For prices use set_variant_price. |
| delete_variantA | DELETES one variant of a product. Irreversible – confirm with the user first. 'confirm' must equal the variant's SKU (or its title when it has no SKU). By default its inventory item is deleted too (only when nothing is reserved). |
| set_variant_priceA | Sets the base price (no price rules) of a variant in one currency. All other prices of the variant are preserved. The amount is in major currency units (e.g. 49.99 = 49.99 EUR). For sale or customer-group prices use price lists. |
| list_catalogB | Product categories (with parent, so the tree can be rebuilt), collections, tags and product types – with IDs for other tools. |
| save_categoryA | Without category_id creates a product category (name required); with category_id updates only the given fields. Can also add or remove products. |
| delete_categoryA | DELETES a product category (products stay, they just lose the category). Confirm with the user first. |
| save_collectionA | Without collection_id creates a collection (title required); with collection_id updates it. Can add or remove products (a product belongs to at most one collection). |
| delete_collectionA | DELETES a collection (products stay, they just leave the collection). Confirm with the user first. |
| list_inventoryB | Inventory items with stock per location (stocked, reserved, available). With low_stock_threshold returns only items at or below the threshold. |
| set_stock_levelA | Sets the stocked quantity of an item at a location. Provide either an absolute 'stocked_quantity' or a relative 'adjust_by' (+/-). Identify the item by inventory_item_id or SKU. Without location_id the item's only location is used. If the item is not stocked at the given location yet, it is added there. |
| list_price_listsB | Price lists – sales (temporary discounted prices) and overrides (e.g. B2B prices for a customer group). With price_list_id returns that list including all its prices. |
| save_price_listA | Without price_list_id creates a price list (title required); with price_list_id updates it. 'set_prices' adds or changes the price of a variant in a currency; 'remove_variants' drops variants from the list. type 'sale' shows the original price struck through, 'override' simply replaces it. Plain dates use the reporting timezone. |
| delete_price_listA | DELETES a price list – its prices stop applying immediately. Confirm with the user first. |
| list_promotionsB | Discount codes and automatic promotions with their value, conditions, usage and validity. |
| create_promotionA | Creates a discount code (or an automatic promotion): percentage or fixed amount off the order, specific products, or shipping. Free shipping = applies_to 'shipping', percentage 100. Restricting to products/categories/collections makes it apply to those items only. Plain dates are interpreted in the reporting timezone. |
| update_promotionA | Changes a promotion: activate/deactivate (status), rename the code, change the value, usage limit or validity dates. Identify it by promotion_id or code. |
| delete_promotionA | DELETES a promotion – the code stops working. To pause it, prefer update_promotion with status 'inactive'. Confirm with the user first. A campaign created for its dates (named after the code) is deleted too. |
| sales_reportA | Computes sales for a period: order count, revenue, average order value, units sold, unique customers, a time series (day/week/month) and top products. Amounts are per currency. Canceled and draft orders are excluded. |
| medusa_requestA | Calls any Medusa v2 Admin API endpoint directly – for anything the other tools do not cover (e.g. /admin/reservations, /admin/order-edits, /admin/exchanges, /admin/tax-rates, /admin/shipping-options). Prefer the dedicated tools when one fits. Amounts are in major units. Use 'fields' in the query to choose fields: '+field' adds to the defaults, '*relation' expands a relation. POST creates or updates, DELETE deletes – confirm changes with the user first. Writes to api-keys, users and invites are blocked. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 48 tools
Despite 48 tools, each targets a distinct resource-action pair. Fulfillment, payment, and return tool families are clearly delineated by verbs (create, mark, cancel, capture, refund, receive), and the generic medusa_request is explicitly a fallback. No two tools appear to do the same thing.
The set uses snake_case throughout with a dominant verb_noun pattern, but it mixes upsert conventions: some resources use save_* for create/update (save_collection, save_customer) while others use separate create_* and update_* (create_product, update_product). Two tools (sales_report, medusa_request) are noun-only, breaking the strict verb_noun pattern. This is mostly consistent but not perfectly uniform.
48 tools far exceeds the 16–25 'heavy' threshold and is close to the 50+ extreme. While the Medusa admin domain is broad, the count imposes high selection overhead; a generic medusa_request already provides an escape hatch, so many CRUD tools could be consolidated.
Core lifecycle coverage is strong for orders, products, variants, customers, categories, collections, inventory, price lists, and promotions. Notable gaps include no dedicated delete_customer or order edit/claim/exchange tools, but medusa_request lets agents work around these gaps, so the surface is largely complete.