# Connect an AI assistant (MCP)

CarFleet runs an MCP server, so a tenant's own Claude, ChatGPT or agent framework can ask about
their workspace in plain language — and keep the fleet and the price list up to date — with no
integration to build.

## Connect

**Server:** `https://carfleet.ae/api/mcp`
**Auth:** the same API key from **Settings → API & MCP**, sent as a bearer token.

In Claude Desktop or any client that takes a remote MCP server, add the URL and the key. There is
nothing else to set up: the key that works for the REST API works here.

## What a key may do is chosen when you mint it

Two kinds, picked in **Settings → API & MCP**:

- **Read only** — every question below, and nothing else.
- **Read and write** — the same, plus the five write tools at the end.

The choice is fixed at minting and cannot be widened afterwards. A read-only key calling a write
tool is refused by the permission system before it touches anything, with a plain 403. If you want a
different reach than either default offers, build a role in **Settings → Roles** and mint against it
— the key can never exceed its role, and narrowing the role narrows every key holding it at once.

## Questions it answers

Twenty tools, chosen because they answer questions operators actually ask rather than mirroring
endpoints one-for-one.

**Fleet**

| Ask | Tool |
|---|---|
| How big is the fleet, how busy is it? | `fleet_overview` |
| What can I rent out next weekend? | `search_vehicles` |
| What needs servicing soon? | `vehicles_due_for_service` |

**Bookings**

| Ask | Tool |
|---|---|
| What's happening today? | `todays_operations` |
| How many rentals are running? | `booking_overview` |
| Tell me everything about this booking | `get_booking` |
| Who's collecting a car this week? | `upcoming_pickups` |
| What's coming back this week? | `ending_rentals` |
| How did July compare with June? | `bookings_in_period` |
| Has this customer actually paid? | `booking_payments` |

**Customers**

| Ask | Tool |
|---|---|
| Find this customer | `search_customers` |
| What have they rented from us before? | `customer_history` |

**Money**

| Ask | Tool |
|---|---|
| How are we doing? | `finance_overview` |
| Who owes us money, and how late? | `who_owes_us` |
| How much is out in invoices? | `invoice_overview` |
| Show me the overdue invoices | `list_invoices` |
| Do the books have anything unresolved? | `money_health` |

**Catalogue**

| Ask | Tool |
|---|---|
| What extras do we offer, at what price? | `list_addons` |
| What can we charge for on a return? | `list_charge_catalog` |
| What's our VAT rate and payment term? | `get_invoice_settings` |

Every one of these is annotated read-only, so a well-behaved client will not gate them behind a
confirmation prompt.

## What it can change

Only with a read-write key, and only reference data — the fleet and the price list:

| Say | Tool |
|---|---|
| "Add the new Cayenne, plate M/12345, 1 800 a day" | `add_vehicle` |
| "Put the G63's monthly rate up to 22 000" | `update_vehicle` |
| "The Urus is going in for service" | `set_vehicle_status` |
| "Add a child seat at 50 a day" | `upsert_addon` |
| "We charge 150 for interior cleaning now" | `upsert_charge_item` |
| "Change our payment term to 14 days" | `update_invoice_settings` |

Rates and prices are in **fils** — AED × 100 — everywhere except `upsert_charge_item`, whose
`suggestedAmountAed` is whole dirhams, as its name says. Sending 450 where 45000 was meant prices a
car at four and a half dirhams a day.

`set_vehicle_status` goes through the same transition rules the app uses and writes to the vehicle's
status history. A car out on a live rental cannot be marked available, and there is no override
argument to make that refusal go away — that is the point of it.

## What it cannot do, and why

**It cannot issue an invoice, take a payment, or message a customer.** Not with any key this screen
mints. An FTA invoice number is burned when it is allocated and the sequence must stay gapless; a
card charge and a WhatsApp message reach the outside world and cannot be recalled. Those stay with a
person. Ask the assistant to draft; press the button yourself.

**It cannot read identity documents.** Emirates ID, passport and licence numbers are encrypted and
are not reachable through any key. Customers reach the assistant as a NAME, and phone numbers and
email addresses are stripped at the server boundary. Do not design a workflow that needs a document
number from here.

**It cannot see another workspace.** A key belongs to exactly one, and the server builds a fresh
tool set per request bound to that workspace.

## Getting good answers

Install the [CarFleet skill](https://carfleet.ae/.well-known/agent-skills/index.json) alongside it:

```bash
npx skills add https://carfleet.ae
```

The tools tell an assistant WHAT it can call. The skill tells it what the answers mean — that money
is in fils, that `booking.days` is not the rental length, that a receipt header is a container and is
never added to its own lines. Those are the things a tool schema cannot express, and the difference
between a right answer and a confident wrong one.
