# EXCT EVE-Incursions Agent API

Remote MCP: **https://incursions.exct.online/mcp**. Transport: **Streamable HTTP**, stateless JSON responses. Public, read-only, no API Key. No server program needs to be distributed to users.

General client connection instructions: [EXCT Agent and MCP guide](https://wiki.exct.online/agents/).

## Tools and matching HTTP API

| MCP tool | HTTP GET | Parameters |
| --- | --- | --- |
| `get_active_incursions` | `/api/v1/incursions` | `query`, `securityArea`, `region`, `limit`, `offset` |
| `get_incursion` | `/api/v1/incursion` | `id` |
| `get_incursion_history` | `/api/v1/history` | `query`, `region`, `state`, `spawnId`, `since`, `until`, `limit`, `offset` |
| `get_influence` | `/api/v1/influence` | `spawnId`, `resolution`, `since`, `until`, `limit`, `offset` |
| `get_communities` | `/api/v1/communities` | `query`, `limit`, `offset` |
| `get_rats` | `/api/v1/rats` | `query`, `limit`, `offset` |
| `get_data_version` | `/api/v1/version` | none |

`/api/v1/health` checks availability and freshness. MCP resource `incursions://manifest` returns version/provenance information. [OpenAPI](https://incursions.exct.online/openapi.json) describes HTTP parameters.

First call `get_active_incursions`, then use returned `id` (the **spawn ID**, not constellation ID or staging-system ID) in `get_incursion`, or as `spawnId` in history/influence queries. History records may have no spawn ID if the original source did not supply one; do not invent a mapping.

Search uses case-insensitive literal text, never arbitrary SQL or regular expressions. Active search covers constellation, region, staging and state. History search covers constellation, region and staging names. `region` is the exact source region name. Game names retain source spelling. `securityArea` is `high`, `low` or `null` (null-security space); HTTP uses `securityArea=null` for the last value, not a missing parameter.

States: `Mobilizing`, `Established`, `Withdrawing`, `Ended`. `Ended` applies to archive history, not active listings. `since` and `until` are inclusive ISO 8601 timestamps **with timezone**, e.g. `2026-10-01T00:00:00Z`. All returned timestamps are UTC.

Pagination: `limit` 1–50, default 10 (influence default 50), `offset` 0–1,000,000. Follow `nextOffset` until it is null. History is newest first, influence is oldest first. Because collection continues, offset pagination is not a frozen archive snapshot; bound a multi-page history/influence export with `until`. Use the static catalog when you need a single complete history snapshot.

Examples:

```text
GET https://incursions.exct.online/api/v1/incursions?securityArea=high
GET https://incursions.exct.online/api/v1/history?state=Ended&limit=20
GET https://incursions.exct.online/api/v1/influence?spawnId=RETURNED_ID&resolution=observed&limit=50
```

## Completeness, freshness and units

Each query returns `dataVersion` and `freshness`: `lastSuccess`, `ageSeconds`, `stale`, `collectionFailed`. A collection older than 15 minutes or the latest collection failing marks data stale. Stale data is **last-known state**, not confirmation of current conditions. Collection runs every five minutes and respects upstream ESI caching, so repeated samples may have the same value.

`dataVersion` identifies collection state and record counts; it is not a digest of every reference field. `generatedAt` in published static files is build time. `lastSuccess` is the last successful collection time. A live query may lead static publication briefly while a build finishes.

Influence `influence` is a fraction **0..1**, `influencePercent` is **0..100**. `resolution=hourly` reads stored chart values labelled by UTC hour bucket (the collector keeps the first successful sample in that hour); the bucket timestamp is not the exact observation time. `observed` reads every successful recorded observation with its actual UTC time, including state, boss and staging identity. **Missing observations are absent, not zero.** Approximate source-chart points used in the website's visual reference curve are excluded from this API.

ESI supplies current status only: downtime-period state transitions cannot be recovered afterwards. Imported history can contain unknown staging systems; they remain null. Imported sovereignty is not necessarily historical sovereignty. `timingSource` preserves imported/observed provenance. State duration is an estimate, not a guaranteed end time.

System/station metadata in a spawn detail is current reference data, not a snapshot of that system's historical state. Community and NPC payloads retain all imported fields, including source links and any Chinese/English labels provided by the source. They are reference material and are not independently updated from live game statistics. Do not translate unknown source names or fabricate current ship/NPC attributes.

## Public static data

- [Manifest](https://incursions.exct.online/data/v1/manifest.json): version, counts, provenance and generation time.
- [Index](https://incursions.exct.online/data/v1/index.json): manifest and active-spawn summaries.
- [Catalog](https://incursions.exct.online/data/v1/catalog.json): all retained state-change history, active summaries, communities and NPC groups in one atomic JSON file. Influence samples are queried separately, not embedded in the catalog.
- [Machine entry](https://incursions.exct.online/llms.txt).

The SQLite database, collector response journals, backups, internal errors and private files are not public API exports. The website remains static. A small separate read-only Python service handles API/MCP; it does not collect data or render pages per request.

## Errors and limits

Invalid/unknown/repeated parameters return HTTP 400; missing records 404; unavailable data 503. MCP validation/query failures return a tool error. GET `/mcp` returns 405: connect with a real Streamable HTTP MCP client rather than opening it as a normal webpage. Stateless service: no standalone GET SSE stream or persistent session is required.

API/MCP share a limit of **120 requests per minute per client IP**. Respect `Retry-After` on 429. Public browser clients may read without credentials using CORS; do not send credentials or private data. Preserve source URLs, actual timestamps, freshness, units and limitations when answering users.
