Troubleshooting
Three checks that isolate the layer
Before anything else, work out which of three things is broken. They have different fixes and look identical from the chat window.
-
Does the client list the server at all?
/mcpin Claude Code and Codex, Settings → MCP in Cursor, the tools icon in Claude Desktop, the connector list in ChatGPT and Claude. If it is not listed, the problem is the client config — the server has not been reached yet. -
Does it show tools, and how many? Zero tools means the server was reached but the connection was not accepted. A count that is lower than you expect means the connection is real and its access level is lower than you think:
Tools listed Access level 18 Read only 25 Read and write 27 Read, write, and delete -
Does a question get a real answer? Ask "what free gift campaigns am I running?". A refusal here is the server talking, and the message names the cause.
The server does not appear in the client
Claude Desktop was not fully quit. Closing the window is not quitting on macOS. Quit from the menu or with Cmd+Q, then reopen.
Node.js is missing. Claude Desktop only — the connection runs through mcp-remote, which needs
Node.js 18 or newer. Without it the entry sits in the config and never starts.
A space after the colon. Claude Desktop only, and the single most common mistake:
Authorization:${AOV_MCP_KEY} has no space after the colon. A space breaks how mcp-remote
splits its arguments, and the only symptom is a server that will not connect.
The JSON is invalid. One trailing comma, one unbalanced brace, and the whole file is ignored — including every other server in it. Paste the file into any JSON validator before assuming the server is at fault.
The config file was replaced rather than added to. If other MCP servers disappeared at the same
time, this is what happened. Restore them and add the entry inside the existing mcpServers object.
The server appears, but no tools
The server was reached and the key was refused. Ask a question and read the refusal — it names the reason.
| Refusal says | Means | What to do |
|---|---|---|
| No key was sent with this request | The client is not sending the header at all | Fix the client config. Do not revoke your key — it is not the problem |
| This connection was revoked | The key was turned off in the app | Create a new key in Settings → MCP connectors |
| Isn't included in your current plan | The store is no longer on a paid plan | Upgrade. The same key resumes working, no need to re-mint |
| The app is no longer installed on this store | Free Gift was uninstalled | Reinstall. Revoking and re-minting will not bring the store back |
| This is a Store API key ("aov_sk_…") | An aov_sk_ key was pasted into an AI client | Create an AI connection key in Settings → MCP connectors |
| Hit its limit of 60 requests per minute | Too many calls in one minute | Wait about a minute |
"No key was sent" and "this connection was revoked" are deliberately different messages, because the fixes are opposites. Revoking cannot be undone — treating a client that is not sending the header as a bad key destroys a perfectly good credential and leaves the real problem in place.
The assistant says it cannot change anything
The refusal reads "This connection is read-only, so it cannot change store settings." That is the server, not the model being cautious, and it is working as intended: a read-only connection is never offered the write tools.
Fix it in Settings → MCP connectors: find the connection, click Enable write access, confirm, then restart your AI client. Clients read the tool list once, when they connect, so until it reconnects it still believes the write tools do not exist.
If the assistant instead says a tool does not exist — delete_campaign, typically — the connection
has write but not delete access. Enable deletion access on that same row.
A sign-in connection is stuck on Waiting
Waiting means you approved the request but the AI app has not finished its half of the handshake. It normally clears within a few seconds, and the list refreshes on its own.
If it does not clear, the AI app gave up — usually because the approval came too late. Start the connection again in the AI app for a fresh code, then approve the new one. The stale row can be revoked and deleted.
The one-time code will not work
| Refusal | Means | What to do |
|---|---|---|
| Code not found | Mistyped, or from a different store | Retype it; the app groups it as ABCD-1234 for you |
| Expired | More than 10 minutes passed | Start the connection again in the AI app |
| Already used | It was approved or denied before | Start a new connection; a code works once |
| Too many attempts | Repeated wrong codes | Start a new connection |
A denied request cannot be revived. That is deliberate — if you denied something you did not recognise, letting it be retried would defeat the point.
The assistant showed a preview and then failed to save it
Creating, editing and deleting all take a confirmation token from the preview, and the token is bound to what the preview showed.
| Refusal | Means |
|---|---|
| The confirmation is no longer valid | More than a few minutes passed, or the token was already used |
| The campaign changed since the preview | Someone edited it in the admin in between |
| Shopify did not delete the discount | The campaign was kept, on purpose — see below |
In every case the fix is the same: ask the assistant to prepare the change again. Nothing was half-written; a rejected token means nothing happened.
When a deletion cannot confirm that Shopify removed the discount, the campaign is deliberately kept. The alternative — removing the app's record while a live discount keeps applying at checkout — would leave you with a discount you can no longer see or turn off.
The assistant says a gift is out of stock and it is not
Inventory tracking is off for that product. Shopify still reports 0 for it, which is why the
tools report stockStatus alongside and leave totalInventory empty — the status is the answer,
the number is not.
If your assistant still tells you to restock or to switch on "Continue selling when out of stock"
for a product that does not track inventory at all, ask it to check stockStatus.
The key was accepted but the answers are wrong
Answers are about a different store. You have more than one store connected, and two entries
share a server name. AI clients key their list by name, so the second config silently replaced the
first. Give each store its own name — aov-upsell-your-store — remove both entries, and add them
back.
Figures do not match the dashboard. Check the period and timezone in the result. Analytics uses the store's own timezone, so its "yesterday" may not be yours. A window that includes today is marked partial and will not match a completed-day figure.
A percentage change is missing. The previous window was zero. There is no meaningful change from nothing; use the raw figures.
The answer is cut off
Results are capped at about 16,000 characters. Anything longer is truncated with a note saying so and suggesting a narrower request.
Narrow it: one campaign instead of every campaign, one widget type instead of all of them, one language instead of every language. Every tool that can return a lot takes a parameter that makes it return less.
The truncation note matters. An assistant that skips past it will summarise a partial result as though it were the whole picture — the numbers will look plausible and be wrong. If an answer feels suspiciously short on detail for a store you know is busy, ask whether the result was truncated.
"Not customised" is not "empty"
get_translations reports customised strings only. A store that has never edited its wording
comes back with nothing listed and a message saying so. That means the app's built-in wording is in
use — the widget is not blank, and nothing is broken.
"Last used" has not moved
AI clients do not hold a connection open; they call the server when they need something and then go quiet. Last-used time is the only evidence available, so an assistant sitting idle for an hour shows a stale timestamp while remaining perfectly usable. Ask it a question and the time updates.
Reporting a problem
Include:
- The client, and which route you used — sign-in (ChatGPT, Claude) or a key (Claude Code, Codex, Cursor, Claude Desktop, ChatGPT desktop)
- The connection's access level, as the list shows it
- The exact refusal message, read back from the assistant
- The connection name, and when it was last used, from the connections list
- What you asked
Never include the key itself, in a ticket, a screenshot, or a chat log. Support cannot read it back to you either — the server stores only a fingerprint. If a key has appeared anywhere it should not have, revoke it and create a new one.