# ShopHelm Wholesale > Wholesale pricing for Shopify stores, agent-ready. An MCP server at https://wapp.getshophelm.com/mcp (Streamable HTTP) reads and changes a store's wholesale pricing: rules, customer groups, pack sizes and minimums, wholesale-only products, net terms and credit limits, and a pricing health check. ## Connect - Endpoint: https://wapp.getshophelm.com/mcp (this is v1; a breaking change would ship at /v2/mcp). - Auth: OAuth 2.1 with dynamic client registration and PKCE (metadata at https://wapp.getshophelm.com/.well-known/oauth-authorization-server), or a per-store bearer token the merchant creates under Settings → Connect your own AI. - Scopes: pricing:read, pricing:stage, pricing:write, customers:write. Asking for none grants pricing:read and pricing:stage. ## Rules for agents - Use only IDs a read tool returned in this session; any other ID is refused (UNKNOWN_ID). - Writes need an idempotency_key and accept dry_run. Do the dry run first. - With the merchant's direct-changes switch off, create_price_rule and update_price_rule stage a proposal instead of applying. - Every direct change is audited and the merchant can revert it from Activity. - Errors are JSON { code, message, remediation, docs_url }. Act on code. ## Tools - get_rules (pricing:read): Every pricing rule in the store, active and paused, with its group, scope, and priority. Read this before proposing a rule. - find_products (pricing:read): Products and collections whose title matches the query, with product IDs, retail prices, and collection IDs. The only source of IDs for stage_rule. - get_pricing_context (pricing:read): For one product: retail price and what each customer group pays today at qty 1, 10, and 50, with the rule that sets each price. - get_pending_changes (pricing:read): Changes already staged and waiting for the merchant's approval. - stage_rule (pricing:stage): Stage a new pricing rule for the merchant to approve. Writes nothing to the store. Refused when a guardrail fails or an ID was not returned by a read tool in this conversation. - stage_rule_update (pricing:stage): Stage an edit to an existing rule (change its value, scope, group, or pause it with active: false). Writes nothing to the store until approved. - discard_change (pricing:stage): Withdraw a staged change the merchant no longer wants. - present_metrics (pricing:read): Show the merchant a card of up to eight figures (label, value, optional note). Use it when the answer is mostly numbers you read from the snapshot or a tool result; the card is displayed, so do not repeat the figures as a list. - explain_rule_conflicts (pricing:read): For one product, show the merchant which rules compete for each customer group and which rule sets the price at qty 1, 10, and 50 under the store's strategy. Use it when asked why a product gets a price or which rule wins. Computed by the pricing engine; the card is displayed. - list_customer_groups (pricing:read): Every customer group: ID, name, the tag that puts a customer in it, tax exemption, how many customers hold the tag, and how many active rules price for it. - get_customer (pricing:read): One customer by ID: the groups their tags put them in, tax exemption, net terms with credit limit and open balance, and how many contract prices they have. No names or emails. - get_wholesale_price (pricing:read): The unit price checkout charges for a product at a quantity, for a customer (their groups, contract prices, and restrictions), a group, or a buyer in no group. Same engine as checkout; names the rule that sets the price. - preview_customer_pricing (pricing:read): View as customer: what one buyer gets across up to 25 products at qty 1, 10, 50, which products are hidden from them, their pack sizes, minimums, terms, and tax status. Read-only. - get_order_rules (pricing:read): Pack sizes and minimum quantities, order minimums, and wholesale-only restrictions, as checkout enforces them. - get_net_terms (pricing:read): Net terms rules (days and credit limit per group), the invoice payment method's name, and open invoices: counts, amounts owed, overdue, and the largest balances by customer ID. - run_pricing_diagnostics (pricing:read): Run the health check now: findings graded critical, warning, or note, each with what is wrong, what it affects, and a suggested fix. Takes a few seconds. - list_diagnostic_runs (pricing:read): The last ten health check runs: when, and how many critical, warning, and note findings. - get_usage (pricing:read): MCP calls this billing cycle against the plan's quota and limit. - get_audit_log (pricing:read): Recent activity, newest first: who did what (merchant, assistant, connected AI, scheduled job) with a one-line summary. - create_price_rule (pricing:write or pricing:stage): Create a pricing rule. With direct changes on (Settings → Connected AI) and pricing:write, it applies and publishes to checkout; otherwise it is staged for the merchant to approve. Same guardrails either way. Needs idempotency_key unless dry_run; dry_run returns the price preview. - update_price_rule (pricing:write or pricing:stage): Change a rule (value, scope, group, quantities, or active: false to pause). Applies directly or stages, as create_price_rule. Needs idempotency_key unless dry_run. - delete_price_rule (pricing:write): Delete a rule. Needs direct changes on; to stop a rule without them, update it with active: false. Needs idempotency_key unless dry_run. - create_customer_group (pricing:write): Create a customer group (a name and the customer tag that puts buyers in it). Needs direct changes on. Needs idempotency_key unless dry_run. - update_customer_group (pricing:write): Rename a group, change its description, or its tax exemption. The tag cannot change (it would move customers). Needs direct changes on. - delete_customer_group (pricing:write): Delete a group. Its rules are paused, not widened to every buyer. Needs direct changes on. - assign_customer_group (customers:write): Put a customer in a group by adding the group's tag to them; their group prices apply at their next checkout. Needs direct changes to customers on. ## Error codes - INVALID_INPUT: The arguments don't match the tool's schema. Fix the fields named in the message and call again. - UNKNOWN_ID: An ID wasn't returned by a read tool in this session. Look it up first (get_rules, find_products, list_customer_groups, get_customer), then call again with the ID it returns. - NOT_FOUND: The thing named no longer exists in this store. Read again to get current IDs. - GUARDRAIL: A safety guardrail refused the change (for example, it would make items free). Change the values and try again; dry_run shows the effect first. - SCOPE_MISSING: This connection wasn't granted the scope this tool needs. Reconnect and approve the scope named in the message. - WRITE_DISABLED: Direct changes by connected AI are off for this store. The merchant can turn them on in the app under Settings → Connected AI; until then, stage changes for approval instead. - PLAN_REQUIRED: This needs a plan the store isn't on. The merchant can change plan in the app under Settings. - IDEMPOTENCY_REQUIRED: Every write needs an idempotency_key: a fresh unique string per intended change, reused only to retry the same call. - IDEMPOTENCY_MISMATCH: This idempotency_key was already used for a different call. Use a new key for a new change. - LIMIT_REACHED: A store limit was reached (for example, too many staged changes). Resolve the pending items first. - QUOTA_EXCEEDED: This store's MCP calls for the billing cycle are used up. They reset with the next cycle, or the merchant can change plan. - INTERNAL: Something failed on our side. Retry with the same idempotency_key; it is safe. ## Docs - https://wapp.getshophelm.com/docs/agents