# abomio.de agent instructions

Use the read-only catalogue to shortlist German car subscriptions and explain their recorded costs. Follow the request, freshness, and recovery rules below.

## When to use this

Use this service when a user wants to compare German car subscriptions, find electric cars under a monthly budget, or shortlist vehicles by brand and contract term. The catalogue covers only the listed providers. It does not cover the complete German market.

Providers in this catalogue:

- Sport Auto Plus
- Ich bin dein Auto
- Drivio
- KINTO
- Europcar
- MILES
- movme
- SIXT Plus
- MOCEAN
- FINN
- Carfino

This service cannot reserve or book a car, guarantee future availability, provide a binding quote, or manage a subscription. Give the user the offer's `source_url` for the final terms and booking.

## When you help a person in a chat

Follow these steps when you talk with a person. Skip them when a program calls the API without a person.

1. Before you search, find out what the person has not told you yet. Ask one short question per message and wait for the answer. Ask in this order and skip what you already know: monthly budget, term, powertrain, brand or body style, private or business customer, kilometres per month. Search after at most four questions, or sooner when the person asks for offers.
2. Search, then show up to 10 available offers in one Markdown table with these columns: vehicle (`vehicle.title`), provider, monthly rate, term, included km per month, one-time fees, and a link to `source_url`. Write "unknown" for missing fees, not 0.
3. Below the table, name the offer with the lowest monthly rate, explain the main cost differences, and tell the person what to confirm with the provider. Offer to change the search.

Answer in the person's language.

## How to call

No authentication is required. Reads never trigger scraping. JSON feeds allow cross-origin GET requests.

Each client IP can send 100 requests per 60 seconds to the JSON API and `/mcp`. Responses from the shared cache do not count. Every API and MCP response sends `RateLimit-Policy: "api";q=100;w=60` in the [IETF RateLimit header format](https://datatracker.ietf.org/doc/draft-ietf-httpapi-ratelimit-headers/). When you exceed the limit, the API returns HTTP 429 `rate_limited` with `Retry-After` and `RateLimit: "api";r=0;t=60`.

The current API version is 1. Send `API-Version: 1`, or omit the header. GET, HEAD and OPTIONS are supported, including cross-origin reads. [OpenAPI](https://abomio.de/openapi.json) documents the parameters, response fields and errors.

Versioning: within a version we only add endpoints, optional parameters and response fields, so ignore unknown fields. Removing or renaming a field, parameter or endpoint, or changing its meaning, creates a new API version. Before we remove a version or endpoint, its responses send `Deprecation` ([RFC 9745](https://www.rfc-editor.org/rfc/rfc9745)), `Sunset` ([RFC 8594](https://www.rfc-editor.org/rfc/rfc8594)) and `Link: <https://abomio.de/developers#versionierung>; rel="deprecation"`, at least 90 days before the Sunset date. The MCP tools follow the same rules.

Build a shortlist in this order:

1. GET [current offers](https://abomio.de/api/offers?fuel=elektro&max_price=500&sort=price-asc&limit=10) for an electric-car shortlist up to EUR 500 per month.
2. Read `/api/catalogue/refresh` for the current `checked_at`. Then inspect `available` and `scraped_at` on each offer. Availability is the last state that the provider confirmed. A failed check does not change it.
3. Compare the same vehicle specification, `runtime_months`, included mileage and known mandatory fees. Missing costs, missing cost amounts and missing `excess_km_rate_eur` are unknown, not zero. `guaranteed_model=false` means the provider may supply a similar model.
4. Cite [abomio.de](https://abomio.de/) and link with `source_url` EXACTLY as supplied. abomio.de counts the click and redirects to the provider site in `provider_host`. Some providers pay abomio.de a commission for these clicks.

The cost categories are required, optional, conditional and deposit. The provider bills each cost once or monthly. Apply these cost rules:

- Deposits are refundable security, not subscription costs.
- Never add optional or conditional charges to the advertised rate automatically.
- Recorded fees, including fees of zero, do not prove that you know the complete tariff cost.
- Price filters and sorting use gross monthly rates without additional fees.
- Do not present a calculated sum as a verified total price.

Read the [comparison method](https://abomio.de/so-vergleichen-wir.md) for details.

## Operator and privacy

Read the operator, privacy, and comparison information:

- [Über abomio.de](https://abomio.de/about.md)
- [Impressum](https://abomio.de/contact.md)
- [Datenschutz](https://abomio.de/privacy.md)
- [So vergleichen wir](https://abomio.de/so-vergleichen-wir.md)

## Markdown pages

For readable content, GET https://abomio.de/ with `Accept: text/markdown`, or GET [index.md](https://abomio.de/index.md). For any other page, add `.md` to its path, such as `/gewerbe.md`, `/so-vergleichen-wir.md` or a car page like `/bmw/x1.md`. The Markdown homepage uses the same query filters as the browser, which differ from the JSON API's filters. Follow the provider links for catalogues of one provider, and follow the Nächste Seite links to read every page. The page parameter starts at 1 and keeps the active filters. An invalid or out-of-range page returns 404. Start with `/api/offers?limit=20` for programmatic searches.

## Feed schema and filters

`/api/offers` returns `published_at`, `status_url`, `total`, `limit`, `next_cursor` and offer summaries. It returns 20 results by default and at most 50 per request. Follow `status_url` for the current catalogue freshness.

To read the next page:

1. Send `next_cursor` as the `cursor` of the next request.
2. Keep the same customer, filters and sort. You can change `limit`.
3. Stop when `next_cursor` is null.

Treat the cursor as opaque. If the results change or an offer expires, the API returns HTTP 409 `publication_changed`. Then restart without cursor.

To read the full details of one offer, use `/offer.json?provider=provider_id_from_search&id=offer_id_from_search`. Replace both placeholders with values from a search result. The API rejects missing, invalid and unknown fields before it reads any data.

Offers include a canonical vehicle (brand, model, trim, motor, title and path), provider identifiers, monthly price, term, mileage, fees, availability, `source_url`, `provider_host` and `scraped_at`. Full details include vehicle specifications, delivery notes, images and the latest new, returned or price events in `changes`. All numbers are finite. Optional details can be missing. Use `vehicle.title` for display. `vehicle.path` is the path of the model's comparison page on abomio.de; add `.md` for its Markdown version. See OpenAPI for all fields.

HTTP and MCP searches use the same filters. Omit the inputs that you do not use. Unknown fields and MCP null inputs are invalid. `q` accepts up to 500 UTF-16 units before the API normalizes whitespace. `brand` accepts one non-empty name, including aliases such as VW. Commas in `brand` are invalid. `min_price` must not be more than `max_price`.

Use these query parameters with `GET /api/offers`. The [OpenAPI description](https://abomio.de/openapi.json) lists their allowed values and limits:

| Parameter | Purpose |
| --- | --- |
| `brand, fuel, transmission, provider` | Select vehicle and provider attributes |
| `min_price, max_price` | Bound the gross monthly rate in euros |
| `runtime, q` | Select the term or search vehicle text |
| `sort` | Choose `price-asc`, `price-desc`, `hp-desc`, or `name-asc` |
| `limit, cursor` | Page size 1–50 (default 20). Send `next_cursor` as `cursor` until it is null |


## Vehicle measurements

`horsepower_hp` is metric PS, and `power_kw` is kW. If the provider gives no power, the field is absent. `power_provenance` tells you if the provider reported the unit or if we converted it, and it flags contradictions. The `min_hp` and `min_kw` filters ignore contradictory power values. The `min_kw` filter compares kW values directly.

`vehicle_range` records the minimum and maximum distance, the measurement standard, the basis, and whether the value applies to the vehicle or its category. Do not describe an unspecified range or a category maximum as the WLTP range of a specific car.

`vehicle_energy` keeps combined, weighted and depleted-battery values separate. `reported_consumption` has no confirmed unit of distance. Confirm conflicting specifications with the provider.

`co2_class` uses A–G. `drive_type` uses Allrad, Frontantrieb, Heckantrieb or Zweiradantrieb. The API omits unknown values.

## Freshness

`checked_at` is the latest catalogue check. `published_at` is the last change to the published offers. `scraped_at` is the offer observation included in the response. Recommend only `available` offers with sufficiently recent observations, and confirm availability with the provider. A failed check alone does not mark an offer unavailable. Caches can keep responses, so read `/api/catalogue/refresh` for the current check time.

## MCP calling example

POST JSON to https://abomio.de/mcp. The endpoint serves protocol 2026-07-28 and older clients that start with an initialize handshake. No authentication is required. The endpoint uses stateless Streamable HTTP with JSON responses and no sessions. GET and DELETE return 405. A browser Origin header must match the public origin. The server accepts requests without an Origin header. The maximum request body is 64 KiB.

Set these request headers:

| Header | Value |
| --- | --- |
| `Content-Type` | `application/json` |
| `Accept` | `application/json, text/event-stream` |
| `MCP-Protocol-Version` | `2026-07-28` |
| `Mcp-Method` | The JSON-RPC method |
| `Mcp-Name` | The value of `params.name`. Send it only for tool calls |

Include `protocolVersion` and `clientCapabilities` in `params._meta` as shown below. Protocol 2026-07-28 uses `server/discover` instead of an initialize handshake. The examples below use it.

Discover the server (`Mcp-Method: server/discover`):

```json
{
  "jsonrpc": "2.0",
  "id": 0,
  "method": "server/discover",
  "params": {
    "_meta": {
      "io.modelcontextprotocol/protocolVersion": "2026-07-28",
      "io.modelcontextprotocol/clientInfo": {
        "name": "abomio-reader",
        "version": "1.0.0"
      },
      "io.modelcontextprotocol/clientCapabilities": {}
    }
  }
}
```

Discover the tool schemas (`Mcp-Method: tools/list`):

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/list",
  "params": {
    "_meta": {
      "io.modelcontextprotocol/protocolVersion": "2026-07-28",
      "io.modelcontextprotocol/clientCapabilities": {}
    }
  }
}
```

Search offers (`Mcp-Method: tools/call` and `Mcp-Name: search_offers`):

```json
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "search_offers",
    "arguments": {
      "fuel": "elektro",
      "max_price": 500,
      "sort": "price-asc",
      "limit": 10
    },
    "_meta": {
      "io.modelcontextprotocol/protocolVersion": "2026-07-28",
      "io.modelcontextprotocol/clientCapabilities": {}
    }
  }
}
```

All tools are read-only. Check `isError` before using a result. Successful results and tool errors contain `structuredContent`. The text content contains the same object as JSON. Errors use the recovery fields below. `checked_at` and `published_at` describe catalogue freshness. The tools return these results:

- `search_offers` returns offers, total, limit and next_cursor, like `/api/offers`. It returns 20 summaries by default, and limit accepts 1 to 50. To get the next page, send `next_cursor` as cursor and keep the same filters and sort. Stop when `next_cursor` is null. The results do not include images or extended vehicle specifications.
- `get_offer` requires provider and id from a search result. It returns a complete offer, including availability and `source_url`.

Pagination reads the latest snapshot on each call. Treat the cursor as opaque. On `publication_changed`, restart without cursor. An expired offer also causes this error, but it does not change `published_at`.

## Recovery

JSON API and MCP tool errors share `error.code`, `error.message`, and `error.resolution`. Invalid inputs include `error.issues` with field paths and messages. Unavailable data includes `error.retry_after_seconds`, and HTTP also sends `Retry-After`. Use the code for recovery, because messages can change:

| Status or result | Action |
| --- | --- |
| 400 or MCP `invalid_query` | Correct the fields listed in `error.issues` using [OpenAPI](https://abomio.de/openapi.json). |
| 400: `unsupported_api_version` | Send `API-Version: 1` or omit the header. |
| 404 or MCP `offer_not_found` | Search again and use the result's provider and offer ID. |
| 409 or MCP `publication_changed` | Restart without cursor, then follow the new `next_cursor`. |
| 429: `rate_limited` | Wait for `Retry-After` seconds, then send fewer requests. |
| Other 404 | Follow [llms.txt](https://abomio.de/llms.txt) or the [sitemap](https://abomio.de/sitemap.xml) for valid paths. |
| 405 | Use a method from the `Allow` header. |
| 406 | Request `text/markdown` or `text/html` for the homepage. |
| 503 or MCP `data_unavailable` | Wait for `error.retry_after_seconds` and consult [status](https://abomio.de/api/catalogue/refresh). |
| Empty `offers` | The search succeeded but found no matches. Use fewer or wider filters. |

