Documentation

Put your parts catalog inside ChatGPT — and Claude, Cursor, and any other MCP client — with one server.

Overview

theNasty is a ChatGPT app for parts commerce, built on the Model Context Protocol. Inside the conversation, the model surfaces fitment-matched parts across your wired-in suppliers, prices them into a quote, and checks the user out — no storefront to leave the chat for. The same server works in any MCP client.

Payment settles on a Stripe-hosted page and is confirmed by a verified webhook. All amounts on this page are integer cents (e.g. 4899 is $48.99).

Quickstart

In ChatGPT or Claude, add theNasty from the app / connector directory and sign in when prompted — no key needed. From Claude Code or another MCP client, point it at the server URL and it will run the same sign-in flow:

bash
claude mcp add --transport http nasty /mcp

Or skip the browser sign-in by passing an API key as a bearer token:

bash
claude mcp add --transport http nasty /mcp \
  --header "Authorization: Bearer <your-key>"

Claude now has three tools — search_parts, price_quote, checkout — and the garage://me resource.

Every tool result comes back as the MCP content envelope { content: [{ type: "text", text: "<JSON>" }] }. The examples below show the parsed JSON from inside that text field.

Authentication

The server is an OAuth 2.1 protected resource. An unauthenticated request to /mcp returns 401 with a WWW-Authenticate header pointing at /.well-known/oauth-protected-resource/mcp. From there clients discover the authorization server (/.well-known/oauth-authorization-server), register themselves dynamically, and send the user through sign-in with PKCE (S256). Access tokens last one hour; refresh tokens rotate on every use and last 30 days.

API keys (Authorization: Bearer nasty_…) still work for scripts and CLI clients. Keys and tokens are stored hashed, are revocable, and scope every call to one user and garage. A missing, expired, or revoked credential returns 401.

Self-serve key management ships with the dashboard. During the public beta, request a key at partners@thenasty.ai.

search_parts

search_parts({ query, vehicle?, intent? })

Find parts across wired-in suppliers, ranked by fitment, and flagged against the caller's garage.

Parameters
query
string · required
What the user needs, in their words.
vehicle
string · optional
Platform/engine hint for fitment.
intent
string · optional
e.g. "repair" or "upgrade".
Example call
json
{
  "query": "impeller water pump",
  "vehicle": "'87 Mercruiser 3.0 Alpha One"
}
Response (sample data)
json
{
  "parts": [
    {
      "sku": "47-43026Q06",
      "name": "Water Pump Repair Kit",
      "brand": "Mercury Marine",
      "category": "cooling",
      "priceCents": 4899,
      "stock": 12,
      "icon": "impeller",
      "supplier": "Bay Marine, Tampa FL",
      "leadTime": "ships same day under 3pm",
      "fitment": { "platform": "alpha-one-gen-ii", "confidence": "exact" },
      "inGarage": false
    },
    {
      "sku": "18-2643",
      "name": "Drive Shaft Seal Kit",
      "brand": "Sierra",
      "category": "seals",
      "priceCents": 1275,
      "stock": 7,
      "icon": "orings",
      "supplier": "West Reef Diesel",
      "leadTime": "freight via R+L same-week",
      "fitment": { "platform": "alpha-one-gen-ii", "confidence": "optional" },
      "inGarage": false
    },
    {
      "sku": "28-79953Q1",
      "name": "Lower Unit Gear Lube, 32 oz",
      "brand": "Mercury Marine",
      "category": "chemicals",
      "priceCents": 1450,
      "stock": 60,
      "icon": "bottle",
      "supplier": "Bay Marine, Tampa FL",
      "leadTime": "ships same day under 3pm",
      "fitment": { "platform": "all-alpha-bravo", "confidence": "required" },
      "inGarage": true
    },
    {
      "sku": "567-PST",
      "name": "Pipe Thread Sealant w/ PTFE, 50ml",
      "brand": "Loctite",
      "category": "chemicals",
      "priceCents": 999,
      "stock": 40,
      "icon": "tube",
      "supplier": "Bay Marine, Tampa FL",
      "leadTime": "ships same day under 3pm",
      "fitment": { "platform": "universal", "confidence": "required" },
      "inGarage": false
    }
  ],
  "note": "Matched 4 parts across suppliers."
}

Ordering reflects fitment ranking — the closest match leads. The gear lube is flagged inGarage: true because the caller already owns it.

price_quote

price_quote({ items: [{ sku, qty }] })

Price a set of parts: subtotal, free 2-day shipping, tax, and total — all server-computed.

Parameters
items
array · required
SKUs + quantities to price.
Example call
json
{
  "items": [
    { "sku": "47-43026Q06", "qty": 1 },
    { "sku": "567-PST", "qty": 1 },
    { "sku": "18-2643", "qty": 1 }
  ]
}
Response (sample data)
json
{
  "lineItems": [
    { "sku": "47-43026Q06", "name": "Water Pump Repair Kit", "qty": 1, "unitPriceCents": 4899, "lineCents": 4899, "partId": 1 },
    { "sku": "567-PST", "name": "Pipe Thread Sealant w/ PTFE, 50ml", "qty": 1, "unitPriceCents": 999, "lineCents": 999, "partId": 2 },
    { "sku": "18-2643", "name": "Drive Shaft Seal Kit", "qty": 1, "unitPriceCents": 1275, "lineCents": 1275, "partId": 3 }
  ],
  "subtotalCents": 7173,
  "shippingCents": 0,
  "taxCents": 538,
  "totalCents": 7711
}

checkout

checkout({ items: [{ sku, qty }] })

Create an order and get a Stripe-hosted Checkout link. Ship-to comes from the authenticated user's saved address. The order is marked paid only by the verified checkout.session.completed webhook — never by the client.

Parameters
items
array · required
SKUs + quantities to purchase.
Example call
json
{
  "items": [
    { "sku": "47-43026Q06", "qty": 1 },
    { "sku": "567-PST", "qty": 1 },
    { "sku": "18-2643", "qty": 1 }
  ]
}
Response (sample data)
json
{
  "orderId": 1,
  "publicId": "NSTY-7B2K-9341",
  "checkoutUrl": "https://checkout.stripe.com/c/pay/cs_test_a1B2c3...",
  "totalCents": 7711
}

garage://me

garage://meis an MCP resource — not a tool. Read it to get the caller's owned parts and recent orders, so the model knows what's already on the shelf and won't re-sell parts the user already has.

json
{
  "ownedParts": [
    { "sku": "28-79953Q1", "name": "Lower Unit Gear Lube, 32 oz", "qty": 1, "source": "seeded" }
  ],
  "recentOrders": [
    { "publicId": "NSTY-7B2K-9341", "status": "paid", "totalCents": 7711, "createdAt": "2026-05-13T17:02:00.000Z" }
  ]
}

Errors & guarantees

  • 401 — a missing, invalid, or revoked key is rejected.
  • Unknown SKU price_quote and checkout error and list the bad SKUs rather than silently dropping them.
  • Out of stock — surfaced in search_parts and blocked at checkout.
  • Idempotent — replaying a paid webhook is a no-op: no double charge and no duplicate garage rows.
  • Server-authoritative pricing — amounts are always recomputed from the catalog; the caller never sets prices, and all money is integer cents.

Example conversation

  1. The user describes a repair — “my impeller's shot on my '87 Mercruiser 3.0 Alpha One.”
  2. Claude calls search_parts. The gear lube comes back flagged inGarage, so it's skipped — the user already has it.
  3. Claude calls price_quote on the parts it needs: subtotal, free shipping, and tax come back to a $77.11 total.
  4. Claude calls checkout, which returns a Stripe-hosted link.
  5. The user pays. The webhook confirms the order, Claude shows the confirmation, and the purchased parts are added to the garage.