Skip to main content
Glama
fjordskii

DealScore MCP

DealScore

Agent-callable car deal grade + brief. Thin Next.js MVP for dogfood testing and GTM.

Compare an asking price to expected market value and return a grade (Great / Good / Fair / High / Overpriced), numeric score, comps summary, risks, and confidence — without scraping Facebook Marketplace or Craigslist.

Env / dogfood / MarketCheck wiring: docs/ENV.md

Live dogfood

Use: https://dealscore-xi.vercel.app

Do not use https://dealscore.vercel.app — that alias points at another Vercel project (sigue), not this app.

The production site is public (SSO off). Web Analytics is on. Open the URL and use the form (no API key). For REST and MCP, send x-api-key or Authorization: Bearer from the Production DEALSCORE_API_KEYS value in Vercel — the secret is not in this repo.

MarketCheck is live in production. MARKETCHECK_API_KEY is already set (via Vercel API, not a dashboard paste). Scores use live comps (data_source: live). Unset or remove that key and redeploy to fall back to deterministic mock comps. With the key set, upstream failures return coverage: cannot_score — they do not silently mock.

Known smoke (live): 2020 Camry, $18,500 ask, 62k mi, ZIP 33803 → Great, expected ~$22,378, 17 comps, data_source: live.

Related MCP server: CarsXE

Stack

  • Next.js App Router on Vercel

  • MCP Streamable HTTP at /api/mcp via mcp-handler + @modelcontextprotocol/server

  • REST gateway for agents (POST /api/score, POST /api/explain)

  • MarketCheck for live comps + price prediction (on in production)

  • NHTSA vPIC for VIN decode

  • Deterministic mock comps only when MARKETCHECK_API_KEY is unset (data_source: mock, coverage: partial)

Local development

cp .env.example .env.local
npm install
npm run dev

Open http://localhost:3000 and score a vehicle via the web form (no API key required). Leave MARKETCHECK_API_KEY empty locally to stay on mock comps.

Live vs mock: Production has the MarketCheck key set. Failures return cannot_score (no silent mock). Local/dev without the key uses mock.

Environment variables

Variable

Required

Description

MARKETCHECK_API_KEY

Production: set (live). Local: optional

Live inventory + MarketCheck Price. Set = live (prod today). Unset = mock. When set, upstream failures return coverage: cannot_score (never silent mock).

DEALSCORE_API_KEYS

Production yes

Comma-separated keys for x-api-key / Bearer on POST /api/score, /api/explain, and /api/mcp.

See .env.example and docs/ENV.md. Production secrets live in Vercel only; .env.example uses dev-local-key as a placeholder.

Authentication

Programmatic routes (POST /api/score, POST /api/explain, /api/mcp) accept either:

  • x-api-key: YOUR_KEY

  • Authorization: Bearer YOUR_KEY

Keys must match a value in DEALSCORE_API_KEYS. In development, when that env var is empty, programmatic routes are open without a key.

GET /api/health is unauthenticated.

API

Base URL for production: https://dealscore-xi.vercel.app

Health

curl -sS https://dealscore-xi.vercel.app/api/health

Production should report coverage.marketcheck.key_configured: true and mode: live_when_key_set. Health only means the env var is present, not that a given score call succeeded.

Score a deal (REST)

Replace YOUR_DEALSCORE_API_KEY with a value from Production DEALSCORE_API_KEYS in Vercel.

curl -X POST https://dealscore-xi.vercel.app/api/score \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_DEALSCORE_API_KEY" \
  -d '{
    "year": 2020,
    "make": "Toyota",
    "model": "Camry",
    "asking_price": 18500,
    "mileage": 62000,
    "zip": "33803"
  }'

VIN example:

curl -X POST https://dealscore-xi.vercel.app/api/score \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_DEALSCORE_API_KEY" \
  -d '{
    "vin": "1HGCM82633A004352",
    "asking_price": 16000,
    "mileage": 62000,
    "zip": "78701"
  }'

Explain a grade

curl -X POST https://dealscore-xi.vercel.app/api/explain \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_DEALSCORE_API_KEY" \
  -d '{ "delta_pct": -0.08 }'

Response shape (score)

{
  "grade": "Great",
  "score": 100,
  "expected_price": 22378,
  "expected_price_low": 13999,
  "expected_price_high": 32997,
  "delta_pct": -0.1733,
  "comps_summary": "...",
  "brief": "...",
  "risks": ["..."],
  "confidence": 0.92,
  "coverage": "scored",
  "rubric_version": "score_v1",
  "data_source": "live",
  "vehicle": { "year": 2020, "make": "Toyota", "model": "Camry" },
  "comps_count": 17
}

Illustrative live payload from the Camry smoke (ask $18,500 / 62k mi / ZIP 33803). Price band and expected price move with the market. data_source is live (key set + usable comps), mock (key unset), or error (key set but cannot score).

MCP (Streamable HTTP)

DealScore exposes an MCP server at /api/mcp with tools mirroring the REST API:

Tool

REST equivalent

score_deal

POST /api/score

explain_grade

POST /api/explain

health

GET /api/health

Production URL: https://dealscore-xi.vercel.app/api/mcp

Cursor — remote MCP

Add to .cursor/mcp.json (or Cursor MCP settings):

{
  "mcpServers": {
    "dealscore": {
      "url": "https://dealscore-xi.vercel.app/api/mcp",
      "headers": {
        "x-api-key": "YOUR_DEALSCORE_API_KEY"
      }
    }
  }
}

Bearer auth also works:

{
  "mcpServers": {
    "dealscore": {
      "url": "https://dealscore-xi.vercel.app/api/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_DEALSCORE_API_KEY"
      }
    }
  }
}

Claude Desktop — remote MCP

Use mcp-remote for stdio bridge, or connect directly if your client supports Streamable HTTP:

{
  "mcpServers": {
    "dealscore": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://dealscore-xi.vercel.app/api/mcp",
        "--header",
        "x-api-key:YOUR_DEALSCORE_API_KEY"
      ]
    }
  }
}

Directory publish (later)

server.json in the repo root is a stub for MCP directory listings (e.g. Glama). Suggested topics when publishing: automotive, pricing, agents, market-data. Remote URL MCP is sufficient for GTM — npm publish is not required.

Rubric (score_v1)

Implementation: src/lib/dealscore/rubric.ts.

delta_pct = (asking_price - expected_price) / expected_price

≤ -10%  → Great
≤ -3%   → Good
≤ +3%   → Fair
≤ +10%  → High
else    → Overpriced

Score maps linearly: score = clamp(100 - delta_pct * 200, 0, 100).

Confidence adjusts by comp count and whether data is live vs mock.

Cache

Comps are fetched per request (MarketCheck ToS R2). No cross-request persistence — each /api/score or score_deal call fetches MarketCheck (or mock) comps once for that request only.

Deploy (Vercel)

Production deployment: https://dealscore-xi.vercel.app (not dealscore.vercel.app).

  1. Import fjordskii/dealscore in Vercel (team: fjordskiis-projects).

  2. Environment variables (see docs/ENV.md) — Production already has both set via Vercel API:

    • DEALSCORE_API_KEYS (required in production)

    • MARKETCHECK_API_KEY (set in production = live comps; unset + redeploy = mock)

  3. Deploy from main.

Web Analytics (@vercel/analytics) is enabled in the root layout.

Tests

npm test
npm run build

Limitations (honest)

  • No Facebook Marketplace or Craigslist URL paste/scraping

  • Mock comps are deterministic demo data, used only when MARKETCHECK_API_KEY is absent

  • With a MarketCheck key configured, auth/rate-limit/upstream errors and insufficient comps return coverage: cannot_score with data_source: error — never silent mock fallback

  • /api/health reports key_configured for MarketCheck, not live connectivity

  • No Stripe billing, affiliates, or PII collection in MVP

  • Fail-closed: returns coverage: cannot_score rather than inventing a Great deal

License

Private — fjordskii holdings.

Related MCP Servers

  • A
    license
    C
    quality
    D
    maintenance
    Enables access to comprehensive vehicle information including VIN decoding, license plate OCR, vehicle history checks (theft, title, salvage records), market valuations, specifications, and warranty data for vehicles across North America and Europe.
    61
    1
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Decode VINs, look up specs, history, recalls, market value, and OBD codes. Recognize license plates and VINs from images. Access comprehensive vehicle data by year, make, and model to power automotive workflows.
    12
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables AI assistants to decode VINs, check stolen vehicle databases, and retrieve market valuations through natural language.
    2
    -