The server doesn't appear at all, or the client reports invalid config
What you'll see. After editing your configuration, the server isn't in the list, or the client complains about malformed JSON.
Why. MCP client configs are JSON, which is unforgiving. A trailing comma, a missing bracket, or curly quotes (" instead of ") makes the whole file unreadable, and the client skips it silently.
What to do:
- Re-paste the example from Connect your client and change only the key. Don't retype brackets or quotes by hand.
- Check for curly quotes — they sneak in when you copy from a chat window or a document.
- No comma after the last entry; every
{needs its}. - Save, then fully quit and reopen the client so it re-reads the file.
StreamableHTTPError: Unexpected content type: null
StreamableHTTPError: Unexpected content type: nullWhat you'll see. On clients that connect through the mcp-remote bridge — Claude Desktop, most commonly — the server fails with Unexpected content type: null or a StreamableHTTPError.
Why. mcp-remote runs on Node, and it breaks on Node's current release line. You need the LTS line, Node 24. Key, config and network can all be correct and you'll still see this.
What to do:
node --version # expect v24.xIf it reports v25 or higher, install the LTS specifically:
brew install node@24
brew unlink node 2>/dev/null; brew link --overwrite --force node@24Do not run brew install node or brew upgrade node — both install the newest release, which is what causes this. Then fully quit and reopen the client.
Clients that speak HTTP natively — Claude Code, Cursor — don't need Node at all. If you're hitting this, check whether your client supports the native HTTP configuration instead.
401 or 403 on execute-request
401 or 403 on execute-requestWhat you'll see. Documentation tools work fine; execute-request fails.
Why. This is always a key problem, never a connection problem — documentation tools work with no key at all, so their success tells you nothing about your credentials.
What to check:
- The header name is
x-apptweak-key, and the value is the key from your API dashboard. - If your config uses an environment-variable placeholder, confirm the client actually expands it. Some clients pass the literal string through. Inlining the key is the reliable option.
- Confirm your API plan is active and has credits. A depleted balance fails differently from a bad key, but both stop execution.
A 200 with no data from Console Data API endpoints
200 with no data from Console Data API endpointsWhat you'll see. An App Store Connect or Google Play Console endpoint returns 200 and an empty result.
Why. apptweak-integrations-api serves data from accounts you have connected to AppTweak. If the connection doesn't exist, there's nothing to return — and that's a successful empty response, not an error.
What to do. Confirm the App Store Connect or Play Console account is connected in AppTweak, then retry. If it is connected and you still get nothing, the integration may have stopped syncing — worth raising with support rather than debugging in the agent.
Requests start failing under load
What you'll see. A batch of calls succeeds, then later ones fail.
Why. The API allows 60 requests per 10 seconds. Agents fanning out across many apps or keywords hit this, and so do generated scripts with uncapped loops.
What to do. Add a delay or retry-with-backoff to generated code, and batch multiple apps or keywords into single calls where the endpoint supports it. See Credits and limits for agents.
The agent is confidently wrong about the data
Worth knowing, because it doesn't look like an error.
- Country and language codes are free text, not enums. A wrong code is rejected rather than corrected. The authoritative lists are the
countriesandlanguagesendpoints onapptweak-api. - iOS and Android integration reports aren't symmetrical. iOS reports break down by device and in-app event only; there's no iOS equivalent of the Android channel/traffic-source breakdown. Don't assume parity.
Having your agent call start-here-guide at the start of every session is the cheapest way to avoid all of these — it carries the current list. You can also paste them into your repo; see Agent context files.