Skip to main content
The MerchantOps MCP server is a remote Model Context Protocol server, almost entirely read-only. Connect it to an MCP client (Claude Desktop or Claude Code) and ask questions about your catalog in natural language — products, variants, pricing, and publish status. All access is scoped to your organization via OAuth. The one exception to read-only is export_product_data below, which only creates a background export job — it cannot otherwise change your catalog.
Server URL: https://mcp.merchantops.ai/mcp  ·  Transport: Streamable HTTP  ·  Auth: OAuth 2.1 (sign in with your MerchantOps account)

Connect

1

Open connector settings

Settings → Connectors → Add custom connector.
2

Add the server

Name it MerchantOps and enter the URL:
3

Authenticate

Click Connect. A browser window opens to sign in with your MerchantOps account and authorize access. After consent you’re returned to Claude and the MerchantOps tools appear.

Authentication & access

The server authenticates you with OAuth using your MerchantOps account — you don’t create or paste an API key to connect it. Access is scoped to your organization automatically, and connecting it cannot alter your catalog data: every tool is read-only except export_product_data, which only starts a background export job and never touches your products, variants, or prices. Read-only is a guarantee about writes, not about interpretation. Some tools return raw records that need reading carefully — see the caveat on get_product_pricing below — so treat an agent’s answer as a starting point to confirm in the dashboard, not as a final one.
The Settings → API Keys page in your dashboard manages a separate kind of credential — server API keys for direct API access or customer-run workers — and is unrelated to connecting this OAuth-based MCP server. You never paste an API key into an MCP client.
After connecting, ask Claude to run whoami to confirm which account and organization it’s operating as.

Available tools

All tools are scoped to the authenticated member’s organization. Every tool below is read-only except export_product_data, which creates a background export job and nothing else.
get_product drops the deprecated isPublished flag. It could read false on a product whose real publish_status was live, so it only contradicted the truth — use publish_status instead. Every response now also carries a version_note explaining that createdAt/lastModifiedAt describe that one version record, not the product overall (pass include_versions=true to see every version’s), and an audit_note when createdBy or lastModifiedBy weren’t recorded for this version, rather than showing them as misleadingly empty.
get_product_pricing returns raw price-record history, not “the current price.” It returns the product’s price records in every status — draft, active, expired, and superseded — and of every price type (MAP, MAP stepdown, sale, and so on), mixed together and ordered newest- created first, which is not the same as newest-effective. There is no date filter.To identify the price that is actually live, you (or the agent) must read each record’s status, price_type, and effective_from yourself. Treat the answer as a working list to verify in Price records, not as an authoritative current price.
Paged results now page up to 500 at a time, with an explicit signal when more exist. get_product_pricing and list_variants used to stop silently at 100 records, with no way to tell there was more. They now return a paging envelope — total, returned, offset, limit, has_more, and next_offset — on every page, plus a short paging_note telling the agent to keep paging when has_more is true. On a product with a long pricing history or many variants, ask the agent to keep fetching pages rather than trusting the first one. get_product_variant_options is similarly more complete: when every variant shares one value for a property (for example, every width is “D”), that property used to be dropped silently. It’s now listed in an omitted field with a reason, so a dropped property is visible rather than invisible.
A page can also be cut short to stay within a client’s response-size limit. When that happens, the envelope adds size_limited: true and the paging_note explains the page was cut for size, not because the data ended. Always continue from next_offset — never from offset + limit — since a size-limited page can return fewer rows than limit asked for.list_variants rows default to key, isPublished, createdAt, lastModifiedAt, and properties. Pass fields (a list of property keys — use list_filterable_properties to discover them) to shrink each row further to just key plus those properties, which fits more variants in a page. Either way, detail=true returns the full variant record, including properties_metadata (enrichment provenance). get_product_pricing’s compact rows likewise omit any field that’s null for that record.get_product_pricing also returns a pricing_semantics block, built from your organization’s business context: what each price type means and how to pick the live one, when that context is defined. If your organization hasn’t defined any rules yet, the response carries a pricing_semantics_note saying so instead — that’s expected, not an error. A pricing_semantics_error field means the read itself failed (the API could be unreachable); it is never used to mean “undefined,” so the agent doesn’t mistake an outage for an organization with no rules.
The two publish-status tools report each target’s state as live, modified_since_publish, failed, publishing, scheduled, or never_published (the price tool uses live, failed, publishing, or never_published). published_by reads scheduled · approved by the approver when a publish ran automatically on its effective date. When no name was recorded for the publisher or approver, published_by reads the member ID labelled (name not recorded) rather than showing a bare ID as if it were a name — in the tools’ own output and on every publish-history row that carries attribution. See Reading publish status for what each state means.
Publish history can be partial, and the tools say so. Both get_product_publish_status and get_price_publish_status return history_returned and truncated on every call, plus size_limited and a plain-language history_note whenever the list was cut — either because the underlying history is capped (product publish history at the newest 200 rows; it cannot be paged) or because the page was trimmed to fit the response size limit. get_price_publish_status’s history_limit now accepts up to 1000 (previously 200), matching the API’s own maximum — pass a larger history_limit when a cut was due to the limit rather than the size budget.
These tools return the same facts as the dashboard’s publish pills. If your client connected before get_price_publish_status existed, or before the server’s instructions told the agent to check has_more/truncated/ size_limited before concluding from a result, reconnect the connector so it picks up the new tool and instructions.
MCP clients cache the tool list. export_product_data and the paging fields above only appear once you reconnect. Disconnect and re-add the server in your client (or re-authenticate in Claude Code via /mcp) to pick them up.

Exporting data

export_product_data(product_key, kind, format) starts a background export of one product’s prices or variants to CSV or Excel — the same export the Jobs page downloads produce, reachable from an agent conversation. Calling it creates a job and returns right away; it does not wait for the file.
1

Start the export

Call export_product_data with the product key, kind (prices or variants), and format (csv or xlsx).
2

Poll the job

Call get_job with the returned job ID. Once the export finishes, the job’s response includes a signed download link.
3

Download the file

The download link is time-limited — fetch it promptly rather than saving it for later.
If get_job instead returns a stall_note, the export never started — this happens only in the brief window around a MerchantOps deploy. Re-run export_product_data; you don’t need to do anything else.
Reconnect to see get_business_context. MCP clients cache the tool list, so a connection made before this tool existed won’t show it, or the pricing_semantics/derivation_note fields above, until you disconnect and re-add the server (or re-authenticate in Claude Code via /mcp). The same reconnect is needed to use list_filterable_properties’s new offset parameter below — the tool’s signature changed.
list_filterable_properties pages, and search reads every page. Each call returns up to 100 property definitions plus a paging envelope — total, returned, has_more, next_offset, paging_note — keep paging from next_offset while has_more is true. An oversized page (for example a property with a large enum allowed_values) is cut to fit the response-size budget; that sets size_limited: true and resumes from the same next_offset. The underlying API has no search parameter, so the tool walks every upstream page itself rather than only the first: the walk stops after 50 pages (5,000 definitions), and hitting that cap sets search_incomplete: true with a note — never a silent miss.

Business context

Every organization using MerchantOps has its own meaning for its data — which price type is the one that’s actually charged, why a tax code or classification looks the way it does, naming conventions that aren’t obvious from the value alone. get_business_context(topic?, property_keys?, offset?) reads whatever your organization has documented about its own rules, so an agent can check before concluding a value is wrong.
  • topic narrows to one of pricing, classification, publishing, data_conventions, exceptions, or other. Omit it to see everything.
  • property_keys selects per-property derivation notes for specific properties (from list_filterable_properties), regardless of topic. Without it, per-property notes are only included under topic classification or data_conventions (or no topic); under any other topic, a property_notes_note says how many exist instead of dropping them silently.
  • offset continues a paged read. The tool fits as many rules and notes as it can under the response-size budget and returns a paging envelope — total, returned, offset, has_more, next_offset — on every call; keep paging from next_offset while has_more is true, passing the same topic and property_keys on every continuation.
defined is computed from everything your organization has, not from the current filter. A 404 from the underlying API is the only outcome read as “no rules defined” — any other error (a timeout, a permission problem, a 5xx) is returned as an error instead, so an outage is never mistaken for an organization with no rules. A topic/property_keys filter that simply has no matches returns an empty page with a note telling you to drop the filter, not a false “nothing is defined.”
The server’s own instructions now tell the connected agent to call get_business_context before treating a pricing combination, a derived classification, or similar data as a defect — a documented organization rule outranks the agent’s own inference.

Example prompts

Troubleshooting

Make sure pop-ups/redirects aren’t blocked, then retry the connection. In Claude Code, re-run /mcp and re-authenticate. MCP clients cache the tool list — fully reconnect the connector to pick up changes.
Results are scoped to your organization. Run whoami to verify you’re signed in as the expected member and org. If the org is wrong, sign out of the connector and reconnect with the right account.
Confirm the URL is exactly https://mcp.merchantops.ai/mcp (with the /mcp path). This is the only address the server advertises as its protected OAuth resource, so a connector still pointing at an older hostname can fail authorization even though that hostname answers. Remove the old connector and re-add it with the URL above. If problems persist, contact your MerchantOps admin.