Skip to main content
Glama

Fable Amazon / REYO Amazon MCP

Fable Amazon is a private Amazon India commerce intelligence and controlled-operations backend. It exposes 56 granular MCP tools over authenticated Streamable HTTP, reads current Amazon SP-API data, computes business metrics, stores private rules/history in Supabase, and gates Amazon mutations behind an exact preview → approval → execute workflow.

This repository is the backend, not a mock dashboard. Production paths never manufacture Amazon data. Tests use isolated fakes and never perform a real Amazon write.

Architecture

ChatGPT / Codex / Claude / Fable
                │
       HTTPS Streamable HTTP MCP
                │
     Next.js 16 App Router on Vercel
                │
        Fable application services
        ├── Amazon SP-API (India)
        ├── intelligence engines
        ├── mutation approval boundary
        └── Supabase/Postgres

The application is split into Amazon adapters, intelligence engines, MCP tool registration, database repositories, mutation controls, and security. Amazon and Supabase credentials are read only in server modules. No buyer address, name, phone, or other restricted PII is requested.

Primary routes:

  • POST/GET/DELETE /mcp — authenticated MCP Streamable HTTP endpoint

  • GET /api/health — configuration readiness without revealing secrets

  • GET /.well-known/oauth-protected-resource — OAuth protected-resource metadata

Related MCP server: Amazon Seller MCP

Implemented capabilities

Read intelligence

  • Orders API v2026-01-01: current-day/range orders, normalized item rows, revenue, units, AOV, status mix, top SKUs, and explicit period comparisons. Current ranges are safely capped because Amazon requires createdBefore to be at least two minutes old.

  • Finances API v2024-06-19: normalized transactions, released/deferred movement, contributing orders/SKUs, fee components, refunds, adjustments, settlement-related rows, and freshness caveats.

  • Listings Items API v2021-08-01: listing search/get, attributes, offers, inventory, issues, and suppression signals.

  • Reports API v2021-06-30: asynchronous request/status/download flow with JSON, CSV, TSV, and GZIP parsing. Serverless requests never wait for report generation.

  • Product Pricing API v2022-05-01: competitive summaries, Featured Offer/reference-price evidence, and guarded price analysis.

  • Sales and traffic: normalized sessions, page views, ordered sales, units, unit-session percentage, Featured Offer percentage, ASIN segmentation, and traffic-vs-conversion comparisons.

  • Composite amazon_review_account: sales, comparable weekdays, finance, fee anomalies, estimated profit, listing issues, suppression, inventory, performance when a ready report is supplied, risks, opportunities, and timestamps.

Financial intelligence

  • Money movement explicitly separates posted/released and deferred amounts and does not claim pickup scans caused a posting.

  • Supabase financial snapshots can be captured and compared. A change is never inferred unless at least two real snapshots exist.

  • The seeded Easy Ship rule flags exactly ₹212.40 at high priority for matching REYO% SKUs, uses ₹64.90–₹88.50 as the expected range, and does not auto-flag ₹88.50.

  • Profit combines Amazon-reported revenue/fees/logistics/refunds with private Fable COGS. SKU COGS takes priority; SQL-like product-family SKU patterns provide a fallback. Missing COGS produces null profit instead of a fabricated number.

Controlled Amazon writes

  • Price, inventory, supported listing-attribute/SEO patches, and listing creation.

  • Exact bulk price, bulk inventory, bulk patch, and bulk-create previews for up to 1,000 selected SKUs.

  • Direct Listings Items operations for up to 20 operations; larger sets use one asynchronous JSON_LISTINGS_FEED.

  • Feed status inspection after bulk submission.

  • PATCH-style changes are preferred. Listing deletion and offer closure are not exposed.

Every Amazon mutation follows this boundary:

request → load current state → protection checks → Amazon validation preview
        → exact signed preview → explicit confirmation → protection re-check
        → single-use atomic consume → Amazon write/feed → immutable per-SKU audit

Approval tokens are HMAC-signed, expire in 60–3,600 seconds, are tied to the initiator and exact payload digest, and cannot be reused. Duplicate SKUs, modified values/SKU sets, expired tokens, validation issues, and protected listings are rejected. Stock-to-zero and large batches are marked high risk. Execution requires the literal confirmation I APPROVE THE EXACT PREVIEW.

Amazon prerequisites

Use a private SP-API application in Amazon's Solution Provider Portal and self-authorize it for the seller account. Record the LWA client ID, LWA client secret, seller ID, and generated refresh token. Amazon documents that private apps can be self-authorized and that the LWA refresh token must be renewed annually.

Request only the non-restricted roles required by the enabled modules:

Role

Used for

Inventory and Order Tracking

Orders and non-PII order tracking

Finance and Accounting

Financial transactions and settlement/report access

Product Listing

Listing reads, validation, updates, creation, inventory, and feeds

Pricing

Competitive pricing operations

Brand Analytics

GET_SALES_AND_TRAFFIC_REPORT and its traffic/conversion metrics

Amazon can change operation-to-role mappings, so confirm the role shown for each operation in the current role mappings before production authorization. Do not add restricted PII roles for this V1.

Amazon India configuration is already the default:

Marketplace ID: A21TJRUUN4KGV
SP-API region endpoint: https://sellingpartnerapi-eu.amazon.com

Current reference material:

Environment variables

Copy .env.example to .env.local for local development. Generate independent random values of at least 32 characters for both MCP and mutation secrets.

Variable

Required

Purpose

AMAZON_LWA_CLIENT_ID

yes

Private SP-API LWA application client ID

AMAZON_LWA_CLIENT_SECRET

yes

LWA client secret; server only

AMAZON_REFRESH_TOKEN

yes

Seller self-authorization refresh token; server only

AMAZON_SELLER_ID

yes

Amazon selling partner ID

AMAZON_MARKETPLACE_ID

yes

Use A21TJRUUN4KGV for India

AMAZON_SP_API_ENDPOINT

yes

Use the EU regional endpoint for India

ALLOW_ENV_AMAZON_FALLBACK

optional

Must be true to use legacy environment Amazon credentials

SUPABASE_URL

yes

Supabase project URL

SUPABASE_SECRET_KEY

yes

Server-only Supabase secret key

SUPABASE_SERVICE_ROLE_KEY

alternative

Legacy alias when a new secret key is unavailable

NEXT_PUBLIC_SUPABASE_URL

admin UI

Browser-safe Supabase Auth URL

NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY

admin UI

Browser-safe publishable key

NEXT_PUBLIC_SUPABASE_ANON_KEY

alternative

Legacy browser-safe key

CREDENTIAL_ENCRYPTION_KEY

yes

32-byte server-only AES-256-GCM master key

HEALTH_CHECK_SECRET

yes

Internal callback secret stored in Supabase Vault too

MCP_AUTH_MODE

yes

shared-secret for private development or oauth-jwt for production clients

MCP_AUTH_SECRET

shared-secret

Bearer token, minimum 32 characters

MCP_OAUTH_ISSUER

oauth-jwt

Exact OAuth issuer URL

MCP_OAUTH_AUDIENCE

oauth-jwt

Expected JWT audience

MCP_OAUTH_JWKS_URL

oauth-jwt

HTTPS JWKS used to verify access-token signatures

MCP_PUBLIC_URL

yes

Public origin, for example https://fable-amazon.vercel.app

MCP_ALLOWED_ORIGINS

optional

Comma-separated additional browser origins

MUTATION_APPROVAL_SECRET

yes

Separate HMAC secret for exact approvals

MUTATION_APPROVAL_TTL_SECONDS

yes

Approval lifetime; default 600

Never prefix these with NEXT_PUBLIC_. Do not put .env.local in source control.

Supabase setup

Create a Supabase project, then apply both migrations in supabase/migrations:

npx supabase@latest login
npx supabase@latest link --project-ref YOUR_PROJECT_REF
npx supabase@latest db push

All application tables have RLS enabled, privileges are revoked from anon and authenticated, and only the server-side service role has access. mutation_audit_logs has a database trigger that prevents updates and deletes.

Add a protected listing in the Supabase SQL editor:

insert into public.protected_listings
  (seller_sku, reason, protection_level)
values
  ('REYO-WINNER-001', 'Current winner', 'FULLY_PROTECTED');

Protect every selected SKU that sold during the last 30 days at mutation time:

insert into public.dynamic_protection_rules
  (rule_name, rule_type, protection_level, parameters)
values
  ('protect recent sellers', 'SOLD_WITHIN_DAYS', 'FULLY_PROTECTED', '{"days":30}');

Add exact SKU COGS:

insert into public.sku_costs
  (seller_sku, product_family, print_cost, paper_cost, packaging_cost, tube_cost, labour_cost, other_cost)
values
  ('REYO-A3-001', 'A3 poster', 18, 7, 4, 6, 5, 0)
on conflict (seller_sku) do update set
  print_cost = excluded.print_cost,
  paper_cost = excluded.paper_cost,
  packaging_cost = excluded.packaging_cost,
  tube_cost = excluded.tube_cost,
  labour_cost = excluded.labour_cost,
  other_cost = excluded.other_cost,
  updated_at = now();

Add a fallback family cost. Patterns use SQL LIKE semantics: % matches many characters and _ matches one.

insert into public.product_family_costs
  (product_family, sku_pattern, unit_cost)
values
  ('A3 poster', 'REYO-A3-%', 40)
on conflict (product_family) do update set
  sku_pattern = excluded.sku_pattern,
  unit_cost = excluded.unit_cost,
  updated_at = now();

The seeded fee rule is deliberately narrow. Add or change rules in fee_rules; a rule can target a SKU pattern and/or ASIN, specify an expected range, flag a specific amount, and exempt a legitimate amount. Rules only report evidence—they never file claims or change account settings.

Local development and verification

Node.js 22 or newer is required.

Copy-Item .env.example .env.local
npm install
npm run dev

Then inspect http://localhost:3000/api/health. A 503 configuration_required response is expected until all required variables are populated.

Run the complete verification suite:

npm run typecheck
npm run lint
npm test
npm run build

The MCP endpoint is http://localhost:3000/mcp. In shared-secret mode, clients must send:

Authorization: Bearer <MCP_AUTH_SECRET>

The endpoint implements current MCP Streamable HTTP semantics on one URL and accepts POST, GET, and DELETE. Origin validation, bearer authentication, request throttling, no-store response headers, typed tool errors, Zod request/upstream boundaries, and secret redaction are enforced.

Deploy to Vercel

  1. Push this repository to a private Git provider repository and import it into Vercel, or link it with npx vercel link.

  2. Add every production variable from the table above in Vercel Project Settings → Environment Variables. Use oauth-jwt for a ChatGPT production connection.

  3. Set MCP_PUBLIC_URL to the final HTTPS origin with no /mcp suffix.

  4. Set MCP_ALLOWED_ORIGINS only for browser origins that genuinely need access.

  5. Deploy with npx vercel deploy --prod or the linked Git production branch.

  6. Verify https://<project>.vercel.app/api/health, OAuth metadata, and an authenticated MCP tool scan.

Deployment does not apply the Supabase migrations automatically. Run supabase db push against the production project before enabling tools.

Production MCP URL:

https://<project>.vercel.app/mcp

MCP authentication and client connection

shared-secret verifies one constant-time bearer token and grants both amazon:read and amazon:write. Use it only with a private client that supports custom authorization headers. A generic remote-MCP connection needs the deployed URL plus the bearer header.

oauth-jwt is the production resource-server mode. It validates signature, issuer, audience, expiry, client identity, and space-delimited scopes against a remote JWKS. Use amazon:read for intelligence-only clients and add amazon:write only for clients allowed to create previews or execute approvals.

This repository intentionally does not act as an OAuth authorization server. Supply an OAuth 2.1/OpenID Connect provider that exposes authorization-server metadata, PKCE-compatible authorization, JWKS, and—where the client requires it—dynamic client registration and refresh/offline access. Configure that provider to issue JWT access tokens for MCP_OAUTH_AUDIENCE; then set the three OAuth variables. The MCP route publishes protected-resource metadata and returns a standards-compatible WWW-Authenticate challenge.

See the MCP authorization specification and Streamable HTTP transport specification.

ChatGPT custom app

Current ChatGPT setup for an eligible account/workspace:

  1. Deploy the server over HTTPS and configure oauth-jwt plus a compatible OAuth provider. The provider should issue refresh tokens and advertise offline_access if continuous connectivity is required.

  2. Enable Developer mode. Workspace admins/owners can use Workspace settings → Apps → Create; authorized users can use Settings → Apps → Create where their plan/workspace permits it.

  3. Enter https://<project>.vercel.app/mcp, select OAuth, complete authorization, and choose Scan Tools.

  4. Review the discovered read and write actions, create the draft app, and test it in a new chat.

  5. Publish only after the Amazon role set, protected listings, COGS, fee rules, approvals, and audits have been verified. Refresh/re-review actions whenever tool definitions change.

Full write-capable MCP support is currently plan/workspace dependent and the UI is still evolving. Consult OpenAI's current Developer mode and MCP apps in ChatGPT before rollout.

For an application using OpenAI's Responses API, pass this server as a remote MCP tool with its server_url, an OAuth access token in authorization, a restricted allowed_tools list where appropriate, and approval behavior suitable for the selected tools. See OpenAI MCP and Connectors.

Read versus write permissions

  • Read tools are annotated readOnlyHint: true; they can call Amazon and compute facts but cannot change Amazon.

  • Report requests and snapshot captures write only job/history metadata and are annotated as non-read-only.

  • Preview tools are non-destructive but require amazon:write because they prepare a possible external mutation and call Amazon validation where supported.

  • amazon_execute_approved_mutation is explicitly destructive, requires amazon:write, an unexpired exact approval token, and the literal confirmation.

  • Tool metadata helps clients display confirmations, but the server-side approval boundary remains authoritative even if a client ignores annotations.

Operational workflow

A safe first production check is:

  1. Call amazon_review_account without a report ID to verify live orders, listings, finance, fees, and COGS coverage. Traffic is explicitly UNAVAILABLE, not guessed.

  2. Call amazon_business_report; poll amazon_report_status; then use its ID with amazon_sales_and_traffic, amazon_conversion_analysis, or amazon_review_account after it is ready.

  3. Call amazon_money_added_yesterday and amazon_shipping_fee_audit for financial reconciliation and the ₹212.40 check.

  4. Capture scheduled financial history by invoking amazon_capture_financial_snapshot from a trusted scheduler, then query amazon_financial_snapshots between two timestamps.

  5. Test a protected dummy SKU and a non-protected dummy SKU with a preview. Inspect the exact diff and validation output before executing.

Admin panel and encrypted credential management

The private panel is protected by Supabase Auth plus an admin_users allowlist. Create the first Auth user in Supabase Dashboard → Authentication → Users, then authorize that user from the SQL editor:

insert into public.admin_users (user_id)
select id from auth.users where email = 'your-admin@example.com'
on conflict (user_id) do update set enabled = true;

Admin routes:

  • /admin/login — Supabase Auth email/password login

  • /admin — private control panel

  • /admin/amazon — encrypted Amazon connection configuration and Test connection

  • /admin/system — dependency state and 30-day connection history

  • /admin/audit — administrator credential/connection events

CREDENTIAL_ENCRYPTION_KEY is a Vercel-only 32-byte base64/hex key. Amazon client ID, client secret, and refresh token are stored as AES-256-GCM ciphertext with per-value random IVs and authentication tags. The key is never placed in Supabase. Existing secrets are never rendered into HTML or API responses; blank secret fields retain their ciphertext. Updating credentials invalidates the in-process credential/access-token cache, so the next Amazon request authenticates with the new values without a redeploy.

The server uses this precedence: active encrypted amazon_connections row → environment credentials only when ALLOW_ENV_AMAZON_FALLBACK=trueAMAZON_CONFIG_MISSING. It never silently combines database and environment fields.

Supabase scheduled health monitoring

The final migration enables Supabase pg_cron, pg_net, and Vault, creates the fable-amazon-connection-health-30m job, and creates a daily 90-day retention job. The cron job does not keep an Amazon session alive: it invokes /api/internal/amazon-health, which obtains an LWA token only for the read-only check, performs one bounded Orders API request, stores the result, and exits.

After the Vercel URL and HEALTH_CHECK_SECRET are configured, store the callback URL and callback secret in Supabase Vault (never in the migration or Git):

select vault.create_secret(
  'https://YOUR_PROJECT.vercel.app/api/internal/amazon-health',
  'fable_amazon_health_url'
);
select vault.create_secret(
  'YOUR_HEALTH_CHECK_SECRET_VALUE',
  'fable_amazon_health_secret'
);

The callback classifies HEALTHY, AUTH_FAILED, RATE_LIMITED, AMAZON_UNAVAILABLE, CONFIG_MISSING, and UNKNOWN_ERROR. A 429 never invalidates credentials; temporary 5xx responses are recorded as Amazon unavailable. Supabase Cron records job runs in its dashboard; inspect the two named jobs and the amazon_connection_health table after applying the migration. This follows Supabase’s current scheduled Edge Function, Cron, and Vault patterns.

GitHub and Vercel Git integration

vercel.json pins Next.js framework detection, npm ci, and npm run build. .github/workflows/ci.yml runs typecheck, lint, tests, and build on pushes and pull requests. .github/workflows/secret-scan.yml runs Gitleaks. Connect the GitHub repository from Vercel Project Settings → Git; Vercel then creates previews for branches/PRs and production deployments for the selected production branch. Put all values from .env.example into Vercel’s encrypted Environment Variables UI. No secret belongs in vercel.json or GitHub workflow files.

Before the first push, inspect tracked files and run a secret scan. The repository ignores .env, .env.local, .env.production, .vercel, Supabase CLI state, and build output; only .env.example is intended to be committed.

Known limitations and production gates

  • No live Amazon call has been made because Amazon account credentials were not supplied. The Supabase connector is authenticated, but creation of the new project is pending confirmation of the sellerboardv2 organization (quoted project cost: $0/month); migrations must be applied and verified there before production use. The deployed integration must then be verified with read-only tools and a controlled test SKU.

  • A compatible external OAuth authorization server is required for production ChatGPT OAuth. JWT resource-server validation is included; authorization/login/consent pages are not.

  • Sales/traffic requires Amazon's Brand Analytics role and an asynchronously generated ready report. amazon_review_account will not invent those metrics when absent.

  • Amazon notes that Finances results may omit recent transactions for up to 48 hours. Movement output therefore reports freshness/confidence and can increase later.

  • Snapshots exist only after a trusted caller or scheduler captures them. No historical balance is backfilled.

  • Large listing feeds are asynchronous. Submission success does not mean every SKU was accepted; inspect amazon_feed_status and the Amazon result document in Seller Central. Result-document parsing for feeds is a future extension.

  • Product Type Definitions schema discovery is not yet automated. Create/patch requests require the caller to supply the correct Amazon product type and attributes; Amazon validation preview runs for direct batches.

  • Account review currently searches one Listings Items result stream with the API's pagination and accepts one ready traffic report. Very large catalogs should add persisted snapshot jobs and incremental report ingestion.

  • Event-driven Amazon Notifications is intentionally deferred until core live reliability is proven.

Security notes

  • Keep the repository private and rotate any secret accidentally exposed outside Vercel/Supabase secret storage.

  • Use separate dev and production Amazon authorizations, Supabase projects, OAuth clients, and approval secrets.

  • Restrict OAuth scopes and tool access per client. A read-only AI should never receive amazon:write.

  • Monitor tool_run_logs, immutable mutation_audit_logs, Amazon request IDs, feed results, and Vercel function errors.

  • Treat MCP clients and report content as untrusted input. Review every bulk SKU list and diff; never bypass the approval service.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers