Check a dealer quote

Paste the quote the dealer sent, or type the selling price and MSRP. You get a grade, the fees and add-ons to push back on, and lines you can send back.

Is my dealer quote fair?. Works in Cursor, VS Code, Claude Code, Codex, ChatGPT apps, n8n.

Mock terminal. Example output, illustrative numbers. Score a real listing. The JSON below is that example.

Deal Score (cardealscore.com) is a used-car price check for AI agents that grades an asking price against current dealer listings.

What score_deal takes and returns

The same contract as POST /api/score. Send a VIN, or year + make + model. Request and response on the used car price API.

Arguments
asking_pricenumberRequired. USD, greater than 0.
mileagenumberRequired. Odometer miles, 0 or more.
vinstring17 characters. Send this, or year + make + model.
yearinteger1980 through next model year.
makestringFor example Toyota.
modelstringFor example Camry.
trimstringOptional.
zipstringOptional. 5 digits. Narrows comps to a local market; omit for US national comps.
Response
gradestring | nullGreat, Good, Fair, High, or Overpriced. Null when coverage is cannot_score.
scorenumber | null0 to 100. Each grade has its own range, so the score always matches the grade. Null when coverage is cannot_score.
expected_pricenumberMarket value estimate from comps, USD.
expected_price_low / _highnumberComp price band, USD.
delta_pctnumber(asking_price - expected_price) / expected_price.
confidencenumber0 to 1, from comp count and data source.
coveragestringscored, partial, or cannot_score. Only scored is billed.
brief / comps_summary / risksstring, string, string[]Plain-text explanation an agent can quote.
comps_count / data_sourcenumber, stringHow many comps, and live, mock, or error.

Example call

score_deal({
  "year": 2019,
  "make": "Example",
  "model": "Sedan",
  "asking_price": 20000,
  "mileage": 40000
})

Example output, illustrative numbers. Score a real listing.

{
  "grade": "Good",
  "score": 87,
  "expected_price": 22000,
  "expected_price_low": 20000,
  "expected_price_high": 24000,
  "delta_pct": -0.09,
  "confidence": 0.8,
  "coverage": "scored",
  "rubric_version": "score_v2",
  "data_source": "example",
  "vehicle": {
    "year": 2019,
    "make": "Example",
    "model": "Sedan"
  },
  "comps_count": 20
}

Grade bands (rubric score_v2)

  • Great delta_pct ≤ -10%
  • Good ≤ -3%
  • Fair ≤ +3%
  • High ≤ +10%
  • Overpriced > +10%

Each grade has its own score range: Great 90 to 100, Good 75 to 89, Fair 60 to 74, High 40 to 59, Overpriced 0 to 39. Inside a range, a lower price scores higher, and only a price 20% or more under expected scores 100. Two more tools ship on the same server: explain_grade maps a delta_pct to a grade with no comps call and no meter, and health reports coverage and limits.

Latency and failure modes

  • One synchronous call. Comps are fetched live for each request and never cached across requests, so a score reflects listings at call time.
  • At most 4 upstream market-data HTTP calls per score. A common car takes 2 searches or fewer.
  • One rate-limit retry, with the back-off capped at 1 second. A monthly quota error fails at once.
  • Thin data returns coverage: cannot_score with a reason. It never falls back to a guessed grade.
  • Comps are US dealer listings, so a private-party price is judged against dealer prices for comparable cars. Facebook Marketplace and Craigslist URLs are not fetched; send the fields instead.

Connect

OAuth 2.1 with PKCE is the default: add the URL with no headers and sign in with an email link the first time. API keys are for clients without OAuth, scripts, and REST. Setup pages: Cursor, VS Code, Claude Code, Claude Desktop, Codex, ChatGPT, n8n. REST: /used-car-price-api. Create a key.

Cursor .cursor/mcp.json

{
  "mcpServers": {
    "dealscore": {
      "url": "https://cardealscore.com/api/mcp"
    }
  }
}

No headers. Cursor discovers OAuth and opens a browser for the email sign-in. Full setup: /integrations/cursor.

VS Code .vscode/mcp.json

{
  "servers": {
    "dealscore": {
      "type": "http",
      "url": "https://cardealscore.com/api/mcp"
    }
  }
}

No headers. VS Code discovers OAuth and opens a browser for the email sign-in. Full setup: /integrations/vs-code.

Claude Code terminal

claude mcp add --transport http dealscore https://cardealscore.com/api/mcp

Then run /mcp, pick dealscore, and choose Authenticate. Full setup: /integrations/claude-code.

Claude Desktop Customize > Connectors

https://cardealscore.com/api/mcp

Add a custom connector with this URL and leave the OAuth fields empty. Claude asks you to sign in the first time it calls score_deal. Config-file setup: /integrations/claude-desktop.

Codex terminal

codex mcp add dealscore --url https://cardealscore.com/api/mcp
codex mcp login dealscore

This writes [mcp_servers.dealscore] to ~/.codex/config.toml and runs the OAuth sign-in. Full setup: /integrations/codex.

ChatGPT apps Developer mode

https://cardealscore.com/api/mcp

Turn on Developer mode in ChatGPT settings, add an app with this MCP URL, and sign in when asked. Full setup: /integrations/chatgpt.

n8n MCP Client Tool

Endpoint: https://cardealscore.com/api/mcp
Server Transport: HTTP Streamable
Authentication: Header Auth
Header name: x-api-key
Header value: YOUR_KEY

Create the key at /keys. A workflow run does not open a browser, so Header Auth is the path to use. Bearer Auth with the same key also works. Full setup: /integrations/n8n.

Clients that take a URL and headers MCP config

{
  "mcpServers": {
    "dealscore": {
      "url": "https://cardealscore.com/api/mcp",
      "headers": { "x-api-key": "YOUR_KEY" }
    }
  }
}

For clients without OAuth. Create a key at /keys. Authorization: Bearer YOUR_KEY also works. Claude Desktop's config file takes a command, not a URL: see /integrations/claude-desktop. REST example: /used-car-price-api.

REST curl

curl -X POST https://cardealscore.com/api/score \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_KEY" \
  -d '{"year":2019,"make":"Example","model":"Sedan","asking_price":20000,"mileage":40000}'

Same response shape as the MCP tool. Over the cap returns HTTP 402. Example output, illustrative numbers. Score a real listing.

Discovery is public JSON: server card, OAuth resource metadata, auth.md, llms.txt. Full reference: API docs.

Metering

  • One meter per account across MCP, REST, and /try. Only coverage: scored is billed. Validation errors and cannot_score are free.
  • Free is 5 scored deals per UTC month. Builder is $19/mo for 1,000. Over the cap, REST returns 402 and MCP returns a score_quota_exceeded tool error. No silent mock. Pricing

FAQ

How do I check a dealer quote?
Send the quote text, or type the selling price and MSRP, at /quote. The check grades the selling price against MSRP and invoice, and it flags a high doc fee, dealer add-ons, GAP, and a service contract. It does not look up the state doc fee cap, and it does not add tax into an out-the-door total.
What does score_deal take?
Send asking_price and mileage, plus a VIN or year, make, and model. trim and zip are optional. The field name is mileage. Same contract as POST /api/score.
What does score_deal return?
A grade (Great, Good, Fair, High, Overpriced), a 0 to 100 score, the expected price band, a brief, and risks. Thin comps return coverage: cannot_score, with grade and score null. That is a normal result, not an error, and there is no guessed grade.
How does an agent connect?
Connect at https://cardealscore.com/api/mcp. OAuth 2.1 with PKCE is the default: add the URL and send no headers. REST and clients that cannot do OAuth use x-api-key or Authorization: Bearer. REST does not accept OAuth access tokens.
What does a scored call cost?
Free is 5 scored deals per UTC month. Builder is $19/mo (founding price) for 1,000 scored calls a month. Only coverage: scored is billed. Validation errors and cannot_score are free. One meter covers MCP, REST, and /try.
Where do the comps come from?
Comps are US dealer listings, so a private-party price is judged against dealer prices for comparable cars. Facebook Marketplace and Craigslist URLs are not fetched; send the fields instead.