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
- Claude Desktop
- Claude Code
- ChatGPT
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 exceptexport_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.
Available tools
All tools are scoped to the authenticated member’s organization. Every tool below is read-only exceptexport_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.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.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.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.
topicnarrows to one ofpricing,classification,publishing,data_conventions,exceptions, orother. Omit it to see everything.property_keysselects per-property derivation notes for specific properties (fromlist_filterable_properties), regardless oftopic. Without it, per-property notes are only included undertopicclassificationordata_conventions(or no topic); under any other topic, aproperty_notes_notesays how many exist instead of dropping them silently.offsetcontinues 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 fromnext_offsetwhilehas_moreis true, passing the sametopicandproperty_keyson 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.”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
The browser sign-in doesn't complete / tools don't appear
The browser sign-in doesn't complete / tools don't appear
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.Tools return empty results
Tools return empty results
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.