MCP Server

Last updated: September 13, 2026

BetterReviews is an MCP server (Model Context Protocol, Streamable HTTP transport, protocol version 2025-06-18). Instead of writing curl calls, an AI client gets a small set of tools over your store: search the review corpus, read a review, record and manage marketing claims, link supporting reviews, and ask a reviewer for permission to feature their review.

The server is stateless and plain JSON: every POST carries one JSON-RPC 2.0 message and gets one JSON response; a notification gets 202 with no body. There are no sessions, no server-sent events and no batching.

Two ways to connect

DoorURLAuthTools
Headerhttps://api.betterreviews.app/api/v1/mcpX-API-Key header with a store API keyAll eight (four need Read & Write)
Connector URLhttps://api.betterreviews.app/api/v1/mcp/c/<token>The URL itself (a 90-day connector token)Read-only four

Claude Code

claude mcp add --transport http betterreviews https://api.betterreviews.app/api/v1/mcp \
  --header "X-API-Key: YOUR_API_KEY"

Claude Desktop

Add to claude_desktop_config.json:

{
  "mcpServers": {
    "betterreviews": {
      "type": "http",
      "url": "https://api.betterreviews.app/api/v1/mcp",
      "headers": { "X-API-Key": "YOUR_API_KEY" }
    }
  }
}

claude.ai custom connector

claude.ai connectors cannot send headers, so you use a connector URL instead. Mint one with a Read & Write API key (201):

curl -X POST https://api.betterreviews.app/api/v1/mcp/connector-tokens \
  -H "X-API-Key: YOUR_API_KEY"
{
  "id": "…",
  "name": "mcp-connector",
  "prefix": "ppo_AbCd",
  "expires_at": "2026-12-12T10:00:00Z",
  "url": "https://api.betterreviews.app/api/v1/mcp/c/ppo_…"
}

Paste url as the connector URL in claude.ai. It is shown once. Then:

  • Treat the URL as a password. Anyone who has it can read your reviews and claims until it expires or you revoke it.
  • It is read-only: only search_reviews, get_review, list_claims and permission_preview are available. Mutating tools are not listed and return read_only_token if called.
  • It expires after 90 days; at most two are active per store (422 too_many_connector_tokens).
  • It only works at its own URL. Presented as a header, Bearer token or query parameter anywhere on the REST API it is refused with 401.
  • Revoke it from Settings → Developer in the BetterReviews app (it appears as mcp-connector) or with DELETE /api/v1/mcp/connector-tokens/:id. Revocation is immediate.

Managing connector tokens requires a Read & Write API key: POST mints, GET /api/v1/mcp/connector-tokens lists the active ones as {"data": [...]} (id, prefix, last used, expiry — never the URL), DELETE /:id revokes.


Tools

ToolAuthArgumentsReturns
search_reviewseitherquery (required, ≤500 chars), product_id, min_rating 1–5, limit 1–50reviews[], total, has_more. Natural-language search over the corpus. Requires an active subscription (subscription_required otherwise).
get_revieweitherreview_idRating, title, content, display name, status, stage, rights_status, tags, media count. Never the reviewer's email.
list_claimseitherproduct_id, status, collect_enabled, include_archived, limit, offsetSame shape as GET /claims.
permission_previeweitherreview_id{reachable, masked_email} — the full address never leaves the server.
upsert_claimheader + writeCreate: product_id, claim_text, topic, source (+ optional ask_phrasings, status, collect_enabled). Update: claim_id + fields.{claim}. Same validation as the REST API (invalid_prompt_text, product_not_found, another_claim_active).
set_claim_collectionheader + writeclaim_id, enabled{claim}. One collect-enabled claim per product.
link_reviews_to_claimheader + writeclaim_id, reviews[] of {review_id, evidence_quote?, confidence?} (≤50){claim_id, reviews[], links_total} — the links written by this call plus the claim's total link count.
request_review_permissionheader + writereview_id, scope (text | photo | both, default both){permission_request_id, status}. Consent rules apply: unreachable, opted-out or suppressed reviewers are refused.

The four header + write tools also require the key's Read & Write scope — a Read-only key sees them in tools/list but calling one returns insufficient_scope.

Claim and permission tools are entitlement-gated (claim_collection, rights_management) exactly like the equivalent REST operations; without the entitlement the tool returns entitlement_required. Current plans (Unlimited, Studio) include them. On legacy plans (no longer sold), they are available on Growth and above, and on legacy Pro and Enterprise; stores on the legacy Starter plan do not have them. A store with no active subscription — never subscribed, or cancelled — is in the free state and holds none of the gated entitlements.

Errors

Two layers, matching the MCP specification:

  • JSON-RPC errors for protocol problems: -32601 unknown method, -32602 unknown tool or invalid arguments (wrong type, over-long string, out-of-range number, too many items — checked before any tool runs), -32600 for batch arrays or malformed requests, -32700 for an empty body.
  • Tool results with isError: true for domain outcomes. The text content and structuredContent carry {"error": "snake_case_code"} using the same codes as the REST API: review_not_found, claim_not_found, claim_archived, product_not_found, another_claim_active, invalid_prompt_text, validation_error, missing_fields (with a fields array — upsert_claim create needs product_id, claim_text, topic and source), invalid_search, entitlement_required, subscription_required, read_only_token, insufficient_scope (mutating tool with a Read-only key), immutable_fields (product_id / source cannot change on update), rate_limited, search_unavailable, and the permission-request outcomes (no_reachable_email, consent_blocked, suppressed, already_requested).

HTTP-level: 401 bad/expired/revoked key or token, 403 credential without a store, 413 body over 256 KB, 429 rate limited (120 requests/minute per store on each door; request_review_permission is additionally capped at 10/minute and 200/day per store and returns rate_limited as a tool result). GET returns 405; DELETE returns 204.

Workflow: does our corpus support this claim?

With the header door connected in Claude Code, a typical exchange is:

  1. search_reviews — "keeps drinks hot for hours", filtered to the product.
  2. get_review on the promising hits to read the full text.
  3. upsert_claim — record the claim with a neutral topic and example ask_phrasings.
  4. link_reviews_to_claim — attach the supporting reviews with the quoted sentence and a confidence.
  5. Not enough evidence? set_claim_collection so the AI review chat can ask happy customers about the topic. Enough? permission_preview + request_review_permission before quoting a review in ads.

See the Claims API for field semantics and the API keys guide for creating and revoking keys.