MCP server · streamable HTTP

Promo codes your agent can cite, not guess.

SimplyCodes tests promo codes at real checkouts and returns a dated verdict — the working codes, or a confident no with the channels it observed.

Endpoint POST https://mcp.sandbox.simplycodes.com/mcp

This one URL is the whole server. Point any MCP client at it; the transport is streamable HTTP.

auth OAuth 2.1 scope promo_codes tier free Explorer on consent tools 4 registered · 2 held
01 — CONNECT

Three ways in, one URL

Every client connects to the same endpoint. Claude and ChatGPT register themselves and run the browser sign-in; a headless agent skips the browser and presents an API key instead. Product.ai is the identity provider behind all three, at https://auth.axioms.ai/api/auth.

Full setup guide, public routes and limits: developers.simplycodes.com/docs.

CLAUDE

Claude web, Claude Desktop, Claude Code

Add a custom connector on the endpoint above: Claude registers itself through /.well-known/oauth-protected-resource, and approving the promo_codes scope issues a free Explorer tier.

Step by step: developers.simplycodes.com/docs

CHATGPT

ChatGPT connectors

The same registration-and-consent path as Claude: add an MCP connector on the endpoint above, sign in with a Product.ai account, approve the scope, and the tools below appear under the names printed on each card.

Step by step: developers.simplycodes.com/docs

HEADLESS

Scripts and server-side agents — ax_ API key

An agent with no browser presents a Product.ai API key as a Bearer token instead. Create the key at https://auth.axioms.ai/ and send it in the Authorization header on every request; a request with no token is refused with 401 missing_token.

Key prefixes and the curl walkthrough: developers.simplycodes.com/docs#keys

02 — TOOLS

4 registered tools, 2 reserved names

Each description below is the exact text the server publishes in /server.json, which is what the model reads when it decides which tool to call. Arguments and result keys come from the same contract module, so this page cannot drift from the wire.

verify_promo_code
free tier

Check whether one promo code works at a merchant right now and get SimplyCodes' dated verdict. Returns `verdict` (VERIFIED_OK, CONFIDENT_NO, UNTESTED, or WITHHELD), `verified_at`, `ttl_seconds`, the verification capsule, and `channels_observed` for a NO. Use this when a shopper already has a code and asks if it is real; an untested code returns UNTESTED with no guess, never a fabricated verdict.

Arguments
merchantpromo_code
Result keys
merchanttierkeyedserving_modeholdoutplatform_originverdictchannels_observedcapsuleofferscaveatsmetacode_ref
get_merchant_codes
keyed tier

Get the promo codes SimplyCodes has verified as working at one merchant, ranked by success rate. Returns `offers` with success counts and last-verified dates, a `capsule` stating what was tested, and either a literal `code` on paid tiers or a `reveal_url` on the free tier. Use this when a shopper is about to check out at a named merchant; it never lists codes for merchants you did not name.

Arguments
merchantlimit
Result keys
merchanttierkeyedserving_modeholdoutplatform_originverdictchannels_observedcapsuleofferscaveatsmeta
An Explorer principal receives reveal_url and never a literal code string — that is sc-agent-api-driver A-3, enforced in the envelope rather than in the client.
get_merchant_verification
free tier

Get SimplyCodes' verification record for one merchant without any codes: how many public codes were tested, how many worked, the working rate, and when the last test ran. Returns `tested_count`, `working_count`, `working_rate`, `last_verified_at`, `freshness` (measured, unmeasured, or stale), and a citable `capsule`. Use this when the question is whether a merchant's coupons are worth pursuing, or to cite SimplyCodes as the verifier.

Arguments
merchant
Result keys
merchanttierverdicttested_countworking_countworking_ratelast_verified_atsensing_coverage_pctfreshnesscapsulecaveatsmeta
report_code_outcome
keyed tier

Report what happened when a shopper used a code SimplyCodes served: worked, failed, expired, or not applicable, with the order value if known. Returns `recorded` (true), the `outcome` as stored, and a `standing_note`. Use this after every checkout attempt; reports are the data payment that keeps free access open, duplicates for the same code on the same day are ignored, and nothing you report raises your cap.

Arguments
merchantcode_refoutcomeissueorder_valuediscount_valuenotes
Result keys
recordedmerchantcode_refoutcomeissuereceived_atstanding_note
RESERVED — NOT REGISTERED
search_deals
paid tier

RESERVED, NOT REGISTERED. Cross-merchant deal search stays held until the SCSSL cross-merchant projections carry verification provenance, because a deal list without a per-offer dated verdict is exactly the unverified aggregation this door exists to replace (owner ruling 2026-09-09).

Held name. It is declared in the contract module so nobody re-uses it for something else, and it does not appear in the server's tool list. Do not build against it yet.
RESERVED — NOT REGISTERED
compare_merchant_offers
paid tier

RESERVED, NOT REGISTERED. Side-by-side comparison of 2-5 named merchants stays held on the same condition as search_deals: comparing merchants whose offers carry no verification provenance would publish a ranking we cannot defend (owner ruling 2026-09-09).

Held name. It is declared in the contract module so nobody re-uses it for something else, and it does not appear in the server's tool list. Do not build against it yet.
03 — RESULT ENVELOPE

Every answer is dated and attributable

Every serving tool returns the same envelope: a verdict, the offers behind it, and a meta block carrying verified_at and this deployment's meta.methodology_url — so an agent can quote a result and say when it was checked.

The four verdicts
VERIFIED_OK

tested at checkout and working.

CONFIDENT_NO

tested and NOT working, scoped to channels_observed; a real answer, not a failure.

UNTESTED

SimplyCodes has no checkout test for this code, so no claim is made either way.

WITHHELD

the merchant resolves but its verification page is not materialized yet, so nothing is asserted.

Offers: Verified offers in upstream ranking order. Empty array, never omitted. A verdict with nothing to serve carries an empty array.

Refusal reasons

A call that cannot be served at all carries a refusal reason instead, so an agent branches on the reason rather than parsing prose.

keyed_onlyrate_cappedprincipal_suspendedretrieval_failuremerchant_not_foundstore_failureduplicate_outcomeaccess_pendingaccess_denied
EXAMPLE One envelope in the Explorer shape — placeholder values, never a live verdict.
{
  "merchant": {
    "name": "Example Merchant",
    "slug": "example-merchant",
    "domain": "example.invalid",
    "id": null
  },
  "tier": "explorer",
  "keyed": true,
  "serving_mode": "reveal",
  "holdout": false,
  "platform_origin": "mcp_claude",
  "verdict": "VERIFIED_OK",
  "channels_observed": [
    "<placeholder: the checkout channel SimplyCodes observed>"
  ],
  "capsule": "EXAMPLE, not a live verdict: a placeholder capsule stating what was tested and when.",
  "offers": [
    {
      "code_ref": null,
      "title": "<placeholder: offer title>",
      "status": "green",
      "verified": true,
      "last_verified_at": "2026-01-01T00:00:00Z",
      "store_url": "https://example.invalid/store/PLACEHOLDER",
      "reveal_url": "https://example.invalid/reveal/PLACEHOLDER"
    }
  ],
  "caveats": [
    "<placeholder: anything that qualifies the verdict>"
  ],
  "meta": {
    "verified_at": "2026-01-01T00:00:00Z",
    "ttl_seconds": "unmeasured",
    "expected_decay_rate": "unmeasured",
    "freshness": "unmeasured",
    "source": "simplycodes_scssl",
    "methodology_url": "https://mcp.sandbox.simplycodes.com/#envelope",
    "attribution_guidance": "<placeholder: how to cite this result>",
    "comparability": "<placeholder: what this may be compared against>",
    "generated_at": "2026-01-01T00:00:00Z"
  }
}

Read the explanation at developers.simplycodes.com/docs: how to cite a verdict, how to branch on a refusal, and what each meta key means.