Developer docs

MCP server

Connect any AI assistant that supports MCP to your shop. It works as you, with the permissions you give its key.

Looking for the overview instead? See AI agents.


At a glance

EndpointPOST https://app.repair-receipts.com/api/mcp
TransportStreamable HTTP, stateless, JSON responses
AuthAuthorization: Bearer rr_live_…
PlanEstablished (pricing)
Rate limit120 requests per minute per key

1. Create an API key

  1. In Repair Receipts, open Settings, then Integrations, then API and AI Agents.
  2. Name the key after what will use it, for example "Grok quoting bot".
  3. Pick its permissions and, if you like, an expiry of 30, 90, or 365 days.
  4. Copy the key. It is shown once. We store only a hash of it, so it can't be shown again.

A key acts as the person who created it, inside the shop it was created in. It can never see more than that person can. Revoke a key from the same screen and it stops working on the next request.

2. Permissions

PermissionGrants
readSearch and read customers, vehicles, invoices, estimates, appointments, parts and labor, VIN decoding, and shop pricing. Every key has it.
writeCreate customers, draft invoices, and appointments.
sendCreate links that are shared with a customer, such as invoice signature links.

Tools outside a key's permissions are hidden from the assistant. It can't call what it can't see.

3. Connect your assistant

Claude, Cursor, and other MCP clients

Any client that supports remote HTTP MCP servers takes a config like this. Settings shows it filled in after you create a key.

{
  "mcpServers": {
    "repair-receipts": {
      "type": "http",
      "url": "https://app.repair-receipts.com/api/mcp",
      "headers": {
        "Authorization": "Bearer rr_live_YOUR_KEY"
      }
    }
  }
}

Groq

Groq's Responses API calls remote MCP servers directly. Add allowed_tools to narrow it further.

import os, openai

client = openai.OpenAI(
    api_key=os.environ["GROQ_API_KEY"],
    base_url="https://api.groq.com/openai/v1",
)

response = client.responses.create(
    model="openai/gpt-oss-120b",
    input="Draft an invoice for Ana Lopez's 2018 Honda CR-V: replace both front struts.",
    tools=[{
        "type": "mcp",
        "server_label": "repair_receipts",
        "server_url": "https://app.repair-receipts.com/api/mcp",
        "headers": {"Authorization": f"Bearer {os.environ['REPAIR_RECEIPTS_API_KEY']}"},
        "require_approval": "never",
    }],
)
print(response.output_text)

Grok (xAI)

Pass the key as authorization in xAI's remote MCP tool. The server accepts it with or without the Bearer prefix.

{
  "type": "mcp",
  "server_label": "repair_receipts",
  "server_url": "https://app.repair-receipts.com/api/mcp",
  "authorization": "rr_live_YOUR_KEY"
}

Check it works

This lists the tools your key can use.

curl -s https://app.repair-receipts.com/api/mcp \
  -H "Authorization: Bearer $REPAIR_RECEIPTS_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

4. Tools

ToolPermissionWhat it does
search_customersreadFind customers by name, company, phone number, or exact VIN. Returns their vehicles with ids.
get_customerreadContact details, vehicles, and the 10 most recent invoices.
search_parts_laborreadPart list prices and book labor hours for a vehicle, by VIN or year, make, and model.
decode_vinreadYear, make, model, trim, and engine for a 17 character VIN.
get_shop_pricingreadYour labor rate, parts matrix, and default taxes.
list_invoicesreadInvoices newest first. Filter by status, customer, vehicle, number, description, or dates.
get_invoicereadOne invoice with line items, taxes, totals, and a link to open it.
list_estimatesreadEstimates, most recently updated first.
get_estimatereadOne estimate with line items and totals.
list_appointmentsreadAppointments in a time window of up to 62 days.
create_customerwriteCreate a customer. Returns the existing one if the phone number is already on file.
create_invoicewriteCreate a draft invoice priced with your shop's rules. See below.
create_appointmentwritePut a job on the shop calendar.
create_signature_linksendThe public link a customer opens to review and sign an invoice.

Each tool publishes a JSON schema for its input, so your assistant knows the exact fields.

5. Creating invoices

A typical request, such as "2018 CR-V, two front struts", runs in three steps.

  1. search_customers finds the customer and the vehicle id.
  2. search_parts_labor returns strut prices and book labor hours for that vehicle.
  3. create_invoice writes the draft and returns a link to open it.
{
  "customerId": "c0ffee00-0000-4000-8000-000000000001",
  "vehicleId": "c0ffee00-0000-4000-8000-000000000002",
  "description": "Replace both front struts",
  "items": [
    {
      "type": "parts",
      "description": "Front strut assembly",
      "quantity": 2,
      "unitCost": 120
    },
    {
      "type": "labor",
      "description": "R&R front struts",
      "quantity": 2.4
    }
  ]
}

Pricing is worked out on our side, with your settings:

  • A unitPrice, when given, is used as is.
  • Parts without a price get your parts matrix markup on unitCost.
  • Labor without a price uses your shop labor rate. quantity is hours.
  • Your default taxes are added unless applyDefaultTaxes is false.

Invoices are always created as drafts. Every invoice needs a vehicle with a VIN. PassvehicleId for a vehicle on file, or vehicle with vin, year,make, and model. A new customer can be passed as newCustomer. If one with the same phone number exists, that customer is used.

Each create_invoice call makes a new invoice. Don't retry a call that succeeded. The invoice history notes which key created it.

6. Errors

Auth problems come back as a JSON-RPC error with an HTTP status.

StatusMeaning
401Missing, unknown, revoked, or expired key.
403The plan doesn't include API access, or the key's owner left the shop it was created in.
429More than 120 requests a minute on one key. Wait and retry.
503API access is temporarily unavailable. Retry shortly.

Problems inside a tool, such as a customer that doesn't exist or a missing VIN, come back as a tool result withisError: true and a message the assistant can act on.

7. Keeping your shop safe

  • Give each assistant its own key, with only the permissions it needs.
  • Keep keys out of code you share. Use an environment variable.
  • Customer names and notes are text the assistant reads. Review drafts before you send them.
  • Revoke any key you think has leaked. Then create a new one.