Ringkasan
krl-mcp adalah server Model Context Protocol yang membuat MCP host mana pun (Claude Code, Claude Desktop, Cursor) bisa menjawab pertanyaan soal kereta KRL Commuter Jabodetabek: papan keberangkatan, katalog line, stasiun terdekat, dan perencana perjalanan langsung. Sengaja dibangun tanpa infrastruktur — tanpa database, tanpa cache, tanpa jaringan, tanpa Docker. Snapshot jadwal open-krl (±5 MB artefak) di-pin di repo dan di-embed ke executable saat build, sehingga seluruh cerita deployment-nya cuma go install + claude mcp add, jalan dari working directory mana pun.
Ini adalah wajah MCP dari krl-schedule-service — sistem produksiku dengan REST API, Postgres, Redis, dan trip planner. krl-mcp mem-port logika query yang sama di atas kontrak data yang sama menjadi scan memori biasa, membuktikan logika domainnya berdiri sendiri.
Arsitektur & Alur Teknis
boards/*.json ──────┐
stations.json ──────┤ parse sekali ┌──────────────────────────────┐
GTFS stop_times ────┼──────────────▶│ in-memory store (±5 MB RAM) │
GTFS trips ─────────┘ └──────────────┬───────────────┘
│ stdio (JSON-RPC 2.0)
▼
MCP host (Claude Code, ...)
Embed. asset.go me-go:embed snapshot ter-pin; store meng-parse-nya sekali saat boot menjadi slice dan map biasa. Satu binary statis ±15 MB, tanpa asumsi working directory — MCP host bisa men-spawn-nya dari mana saja.
SQL jadi struktur memori. Yang di produksi berjalan sebagai SQL di sini menjadi index prebuilt: self-join trip milik planner menjadi index stop → (trip, seq); warna line di-reduce in-memory; bentuk output JSON kompatibel byte dengan API produksi, dan setiap golden assertion di test suite diverifikasi terhadap artefak sebelum ditulis.
Resolusi stasiun 4 tingkat. "Tanah Tinggi", "tanah tinggi", "TANAHTINGGI", dan "THI" semuanya resolve: exact code → exact name → normalized → substring — tiga map plus fallback scan.
Jam service-day. 24:04 berarti 00:04 setelah tengah malam di hari layanan yang sama — konvensi GTFS yang menjaga kereta malam tetap sortable. Planner menerima jam hingga 47.
Kontrak kejujuran. Saat tidak ada perjalanan langsung, plan_trip mengembalikan meta.transfer_candidates — perhentian di mana rute satu transfer memang mungkin — sehingga pemanggil LLM bisa menalar transfer dari data, bukan mengarang rute. Kosong berarti benar-benar tidak ada. Begitu pula get_trip_stops: headsign bukan rute — kereta 5133D bertuliskan "ANGKE" padahal menempuh ring selatan lewat Manggarai.
Enam Tool
| Tool | Yang dijawab ||---|---|| get_stations | Katalog 111 stasiun (Jabodetabek + Yogyakarta–Solo) dengan koordinat || get_departures | Papan keberangkatan satu stasiun dalam jendela waktu || get_lines | Line komersial dengan warna kanoniknya || plan_trip | Perencana perjalanan langsung: depart_at atau arrive_by, dengan perhentian antara || find_nearest_station | Koordinat GPS → stasiun terdekat beserta jaraknya || get_trip_stops | Urutan perhentian lengkap satu kereta — narasi rute yang bisa diaudit |
Catatan Teknis
- Dogfooding sebagai QA: LLM itu sendiri menemukan tiga bug nyata — path data relatif yang diam-diam menyajikan board kosong, jarak resolusi nama antara deskripsi dan kode, dan halusinasi rute akibat data perhentian antara yang tidak diekspos (fixed dengan mengekspos
via+get_trip_stops— asal mula kontrak kejujuran). - CI sejak push pertama: release pipeline otomatis membangun binary 5 platform; CI (vet + test) pernah menangkap pola
.gitignoretanpa anchor yang diam-diam mengeluarkancmd/dari repo publik — build lokal jalan, clone orang asing gagal. - Pemisahan lisensi: kode MIT; data open-krl yang dibundel CC-BY 4.0 (koordinat OSM di bawah ODbL) — atribusi hidup di
NOTICE, eksplisit dan terpisah.
Tech stack
Architecture
krl-mcp/
├── asset.go # go:embed — pinned boards/stations/GTFS snapshot in-binary
├── cmd/krl-mcp/main.go # stdio entry point (JSON-RPC), cwd-independent
├── internal/server/ # MCP layer: 6 tools over go-sdk + e2e test (builds & spawns own binary)
├── internal/store/ # in-memory store: 4-tier station resolution, planner,
│ # stop→(trip,seq) index, service-day clock (h ≤ 47)
├── data/ # pinned open-krl artifacts + manifest (CC-BY 4.0 / ODbL)
├── Makefile · NOTICE · LICENSE (MIT)
└── .github/workflows/ # CI (vet+test) + Release (5-platform binaries)
…