startline
# Startline AI — MCP server, web app & voice API
The serving layer for [Startline AI](#related-repos): an AI companion for
motorsport event documents. One process gives you an MCP server for AI agents,
a phone-first event-day web app, a voice endpoint for Siri, amendment diffs and
calendar export — all over a local document vault.
Built after marshalling at a Formula 1 event, where the official app delivers
PDFs but can't answer *"what time does sign-on close on Saturday?"* — and where
an amendment is just another PDF that never tells you what changed.
## Two kinds of search
**Index search** — SQLite FTS5 + BM25 over heading-level chunks with
event-jargon synonyms (`sign-on` = `muster`, `MxM` = `minute x minute`).
Instant, deterministic, works with no signal at the track.
**Agent search** — an MCP server exposing nine typed tools, so an AI assistant
can reason across documents and cite pages:
| Tool | Purpose |
|---|---|
| `list_events` / `event_overview` | inventory, categories, amendment count |
| `list_docs` | filter by event and category |
| `search` | full-text with citations |
| `read_doc` | fuzzy name match, `pages="3-5"` slicing |
| `schedule_for` | parsed day timeline, with amendment warnings attached |
| `diff_amendment` | what an amendment actually changed |
| `amendments` / `doc_history` | version chains |
Register it with any MCP client:
```json
{ "mcpServers": { "startline": {
"command": "uv",
"args": ["run", "--directory", "/path/to/startline-server", "startline-mcp"]
}}}
```
## Amendment diffs
The feature the official apps don't have. Each amendment is structurally
diffed against the schedule it amends — rows matched by normalised text and
classified moved / added / removed inside the amendment's time window — then
summarised:
> *"The one-minute signal to the marshalling area is delayed from 17:09 to
> 17:24, and the reconnaissance lap release from 17:10 to 17:25. A new
> 20-minute signal checkpoint has been added at 17:15."*
Results are cached by content hash, so each amendment costs one model call ever.
## Running it
```bash
uv sync
uv run startline-mcp # MCP server (stdio)
uv run startline-serve # web app + voice API on :8095
uv run startline-caption # vision-caption maps and diagrams (cached)
uv run startline-faq # pre-answer common marshal questions (cached)
```
Point it at a vault with `STARTLINE_VAULT=/path/to/vault` (default
`~/startline-vault`). AI features need `ANTHROPIC_API_KEY` in the environment;
without it, index search and the offline answer fallback still work.
### Endpoints
| Route | What |
|---|---|
| `/` | event-day web app — day chips, NOW/NEXT timeline, filter, amendment banner, ask box |
| `/ask?q=` | answer engine (used by the web app, Siri and the iOS app) |
| `/api/events`, `/api/schedule`, `/api/diff` | JSON for clients |
| `/api/docs`, `/api/file?path=` | browse and stream the event's source PDFs/images |
| `/api/faq` | pre-answered common questions, grounded in the event's docs |
| `/calendar.ics?day=&q=` | RFC 5545 export, optionally filtered |
Answers come back in the language the question was asked in — a Vietnamese
question gets a Vietnamese answer, while document titles stay in the original.
### Voice
`SIRI-SETUP.md` has the Apple Shortcut recipe (dictate → HTTP → speak) and a
launchd plist for running the server permanently. The iOS app below does this
natively with an App Intent.
## Vision captions
Maps, gate diagrams and notice photos carry no extractable text, so they are
invisible to search. `startline-caption` sends the rendered pages to a vision
model, asks it to describe the page *and transcribe every label*, and caches the
result by content hash. Ingest bakes captions into the notes, which makes
questions like *"how do I get through the zone fence near post 2.5?"*
answerable from an image.
## Related repos
| Repo | Role |
|---|---|
| **startline-vault** | ingest pipeline + offline index search |
| **startline-ios** | native SwiftUI client |
## License
MIT
TDQS
Scored across 9 tools
Each tool targets a distinct resource and action: events, documents, search, schedules, amendments, and history. Overlap is minimal and clarified by descriptions (e.g., event_overview vs. list_docs).
Names mix conventions: list_events, list_docs, read_doc, diff_amendment follow verb_noun, while event_overview, schedule_for, amendments, and doc_history do not. However, all names are still descriptive and readable, so the inconsistency is moderate rather than chaotic.
Nine tools is well within the ideal 3–15 range. Each tool serves a clear purpose in the event-documentation domain, and none feel redundant or unnecessary.
The domain is a read-only knowledge base for motorsport events, and the set covers event listing, document search/read, per-day schedules, amendments, and version history. No obvious workflow dead ends remain; even superseded documents and amendment diffs are handled.