MCP RAG Proof of Concept — Oil & Gas Prototype
Proyek ini adalah Proof of Concept Multi Context Protocol (MCP) dan Retrieval-Augmented Generation (RAG) untuk industri migas.
Aplikasi ini menghubungkan berbagai sumber internal domain (drilling, production, HSSE, purchase order, timeseries, dan RAG search) ke dalam satu router, sehingga query dari client bisa diarahkan otomatis ke service/repository yang tepat.
Apa itu MCP?
Multi Context Protocol (MCP) adalah protokol untuk menghubungkan LLM dengan berbagai tools atau services di belakang layar.
Dengan MCP, pertanyaan user bisa otomatis dipetakan ke domain tertentu (misalnya drilling events, purchase orders, atau RAG search) lalu dieksekusi dengan cara paling tepat.
Apa itu RAG?
Retrieval-Augmented Generation (RAG) adalah teknik menggabungkan kemampuan LLM dengan pencarian berbasis dokumen.
Alih-alih hanya mengandalkan model, RAG mengambil potongan teks relevan dari database (misalnya doc_chunks), lalu menggunakannya untuk menghasilkan jawaban yang lebih akurat dan bersitasi.
🛑 Problem
Di industri migas, data operasional tersebar di banyak domain dan sistem terpisah:
- Drilling → laporan pengeboran & NPT (Non Productive Time).
- Production → data produksi harian & timeseries.
- HSSE → catatan insiden & laporan keselamatan.
- Purchase Order → status pembelian & vendor.
- Dokumen teknis → file PDF/Word yang terpecah di berbagai departemen.
Akibatnya, untuk menjawab satu pertanyaan sederhana (misalnya "berapa banyak insiden HSSE di rig B07 bulan ini?"), user harus:
- Menghubungi beberapa tim/departemen.
- Mencari file laporan manual.
- Menunggu validasi & rekap data.
Proses ini bisa memakan waktu berhari-hari dan rentan inkonsistensi antar sumber.
✅ Solusi
Proyek MCP + RAG ini menawarkan pendekatan modern:
- MCP Router → bertindak sebagai smart gateway yang mengarahkan pertanyaan user ke domain/data repository yang tepat (drilling, production, HSSE, PO, timeseries).
- RAG Search → menggabungkan keyword search (BM25) dan semantic search (cosine similarity) untuk mengambil potongan dokumen paling relevan.
- LLM Integration → query natural language dari user dipahami & dijawab dengan konteks, lengkap dengan sitasi dari dokumen sumber.
- Chat SSE → jawaban dikirim secara streaming sehingga interaktif, mirip chat dengan asisten AI.
Dampak bagi perusahaan migas:
- ⏱ Lebih cepat → jawaban lintas domain dalam hitungan detik.
- 📊 Lebih akurat → jawaban berbasis dokumen & sitasi, mudah diverifikasi.
- 🔄 Lebih efisien → kurangi beban koordinasi antar departemen.
- 🧩 Lebih fleksibel → mudah diperluas dengan tools/domain tambahan sesuai kebutuhan bisnis.
.
Project : MCP_RAG (Oil & Gas) — Go Version : 0.1.0 Author : Kukuh Tripamungkas Wicaksono (Kukuh TW)
Email : kukuhtw@gmail.com
WhatsApp: https://wa.me/628129893706
Linkedin: https://www.linkedin.com/in/kukuhtw/
License : MIT (see LICENSE)
Summary
Monorepo PoC MCP + RAG untuk studi kasus perusahaan migas.
Fitur utama:
- MCP Router & Tools (PO, Production, Drilling, Timeseries, NPT).
- RAG hybrid (BM25 + cosine) via
/rag/search_v2(MySQL doc_chunks). - Jawaban berbasis dokumen (
answer_with_docs) lengkap sitasi. - Chat SSE (
/chat/stream): planning → normalize → execute → stream. - Plan normalizer (auto switch rag_search_v2, top-N PO by amount).
- REST endpoints siap pakai.
- Konfigurasi via ENV; dukung OpenAI untuk LLM/embeddings (opsional).
Isi Singkat
- Fitur Utama
- Quickstart
- Konfigurasi Lingkungan
- Endpoint Penting
- Arsitektur & Alur Chat SSE
- Normalisasi Rencana (Planner)
- Contoh Pertanyaan
- Troubleshooting
- Lisensi
- Kredit
flowchart TD
%% LAYER: Client
subgraph CLIENT["Client"]
FE["Web Frontend<br/>React + Vite + Tailwind<br/>(/web)"]
end
%% LAYER: API Service
subgraph API["HTTP API Service (cmd/api)"]
SSE["SSE: GET/POST /chat/stream<br/>ChatSSEHandler"]
API_ROUTES["API routes: /api/...<br/>healthz, metrics, login, admin, mirror"]
RAG_V2["RAG: GET/POST /rag/search_v2<br/>ragh.HandlerV2"]
MCP_ROUTE["MCP: POST /mcp/route<br/>mcp.RouterHandler"]
end
%% LAYER: MCP
subgraph MCP["MCP Router & Tools"]
REG["Registry & Router<br/>internal/mcp"]
NORM["Plan Normalizer<br/>NormalizePlan()"]
TOOLS["MCP Tools<br/>(get_production, get_timeseries,<br/>get_drilling_events, get_po_status,<br/>get_po_vendor_compare, get_po_vendor_summary,<br/>summarize_npt_events, get_po_top_amount,<br/>answer_with_docs)"]
end
%% LAYER: RAG
subgraph RAG["RAG Hybrid"]
RAGSRV["ragh.HandlerV2<br/>(BM25 + cosine)"]
ANSWER_DOCS["answer_with_docs<br/>(citations from retrieved_chunks)"]
end
%% LAYER: Data Stores
subgraph DB["MySQL"]
CHUNKS["doc_chunks + embedding JSON"]
DOMAINS["production, timeseries,<br/>drilling_events, purchase_orders,<br/>work_orders, ..."]
end
%% LAYER: Optional LLM/Obs
subgraph EXT["Optional Services"]
LLM["OpenAI LLM & embeddings"]
PROM["Prometheus & Grafana"]
end
%% FLOWS
FE -->|SSE| SSE
FE -->|REST| API_ROUTES
SSE -->|Load tool schemas| REG
REG --> NORM
SSE -->|Plan → Normalize| NORM
NORM -->|Routes RAG MCP | TOOLS
NORM -->|RAG routes to /rag/search_v2| RAG_V2
RAG_V2 --> RAGSRV
RAGSRV --> CHUNKS
TOOLS -->|Domain queries| DOMAINS
TOOLS -->|Answer w/ documents| ANSWER_DOCS
ANSWER_DOCS --> CHUNKS
SSE -->|Synthesizer stream| LLM
LLM --> SSE
SSE -->|SSE events: plan, sources, delta, done| FE
API_ROUTES --> PROM
SSE --> PROM
MCP_ROUTE --> REG
REG --> TOOLS
TOOLS --> DOMAINS
%% Optional embeddings at ingest time
LLM -. embeddings .-> CHUNKS
Fitur Utama
-
MCP Router & Tools:
get_production,get_timeseries,get_drilling_events,get_po_status,get_po_vendor_compare,get_po_vendor_summary,summarize_npt_events,answer_with_docs,get_po_top_amount(Top-N by amount). -
RAG Hybrid: Endpoint
/rag/search_v2memakai MySQL (BM25 + cosine) langsung padadoc_chunks.embedding (JSON). -
Answer With Docs: Jawaban mengutip dokumen dengan sitasi (
DOC-XXXX#pY). -
Chat SSE: Endpoint
/chat/stream→ plan (LLM) → NormalizePlan → eksekusi routes (MCP/RAG) → stream jawaban. -
Plan Normalizer:
- Rewrites route rag → tool
rag_search_v2(payload{query, top_k, alpha}). - Fallback dari
detect_anomalieske RAG jika payload salah tapi pertanyaan bernuansa dokumen. - Perbaikan otomatis kasus Top-N PO by amount → pakai
get_po_top_amount.
- Rewrites route rag → tool
-
Observability:
/metrics,/healthz, log terstruktur.
Quickstart
1) Prasyarat
- Go 1.22+
- MySQL 8+
- Node.js 18+ (untuk FE)
2) Setup DB
make build
make gen-data
make demo-data
make ingest-docs
3) Jalankan Service
# Aminer mysql
[http://localhost:8080/chat](http://localhost:18080/?)
4) Jalankan Frontend
# Akses http://localhost:5173
Konfigurasi Lingkungan
Contoh variabel .env:
# Database
DB_DSN="user:pass@tcp(localhost:3306)/mcp_oilgas?parseTime=true"
# JWT / Admin
ADMIN_JWT_SECRET="supersecret"
# LLM (opsional)
OPENAI_API_KEY="sk-..."
# Planner
MCP_SCHEMAS_DIR="schemas/mcp"
PLAN_MAX_ROUTES=8
Tanpa
OPENAI_API_KEY, sistem tetap berjalan (RAG hybrid & fallback extractive untuk answer_with_docs).
Endpoint Penting
-
Health & Metrics
GET /healthz,GET /readyz,GET /metrics
-
Chat SSE
GET|POST /chat/stream?q=...(SSE events:plan,sources,delta,done, dll.)
-
MCP Router (HTTP-internal)
POST /mcp/route(terima plan atau pertanyaan untuk auto-pilih tool)
-
RAG Hybrid
GET|POST /rag/search_v2→ body{"query":"...","top_k":10,"alpha":0.6}Respon berisiretrieved_chunks
-
Domain HTTP (mirror MCP)
/api/timeseries,/api/drilling-events,/api/po/status,/api/production,/api/work-orders/search,/api/npt/summarize,/api/po/vendor-compare,/api/answer-with-docs, dll.
Arsitektur & Alur Chat SSE
-
Planner (LLM JSON-mode) membaca tools dari
schemas/mcp/*.schema.json. -
NormalizePlan:
- Rute
kind:"rag"→rag_search_v2. - Perbaiki salah rute (mis. top-amount PO).
- Tambah RAG pendukung bila relevan.
- Rute
-
ExecuteRoutes:
- Jalankan MCP tools in-process.
- Jalankan RAG via closure
ragFn(hybrid/rag/search_v2→ fallback embeddings repo).
-
Synthesizer:
- LLM stream jawaban berdasarkan
sources(atau fallback extractive).
- LLM stream jawaban berdasarkan
Normalisasi Rencana (Planner)
Hal-hal yang otomatis ditangani:
- RAG rewrite: semua route
kind:"rag"(termasuk tool lama"rag") diubah ke toolrag_search_v2dengan body{query, top_k, alpha}. - Detect anomalies → RAG: jika payload
detect_anomaliestidak valid, dan pertanyaan tampak “berbasis dokumen”, maka dialihkan ke RAG. - Top-N PO by amount: deteksi frasa seperti “top/tertinggi amount PO”, tambahkan/benarkan rute
get_po_top_amount {limit, ...}.
Contoh Pertanyaan
- Berapa produksi
WELL_A12pada2025-09-05? - Bandingkan total nilai PO status delivered antara SLB dan Weatherford pada
2025-09-20s/d2025-10-06. - Berikan ringkasan jumlah PO per status terbaru.
- Bandingkan total nilai PO antara Halliburton, NOV, dan Weatherford periode
2025-09-01s/d2025-10-11. - Emergency Response Plan.
- Production Forecast Q4 2025.
- Ambil produksi gas
WELL_E05pada2025-09-01. - Berapa produksi
WELL_B07pada September 2025? - Tampilkan produksi gas
WELL_C03pada2025-09-04. - Ambil nilai produksi terbaru untuk
WELL_A12. - Tampilkan semua event NPT pada
WELL_B07selama September 2025. - Apa saja event drilling di
WELL_D02pada minggu 7–13 September 2025? - Daftar event NPT di
WELL_E05pada 3 September 2025? - Ambil semua drilling event di
WELL_C03antara 24–30 September 2025. - Event apa saja yang terjadi di
WELL_F10pada 10 September 2025? - Tampilkan trend flow rate
FLOW_A12pada 1 September 2025 pukul 00:00–00:23. - Nilai flow rate dengan
quality=0padaFLOW_A12selama 11–12 September 2025? - Trend perbandingan rata-rata 5-menit di
FLOW_A12awal 1 Sep 2025? - Ada penurunan signifikan flow rate antara 14 Sep 2025 00:05–00:10 vs 00:15–00:20 di
FLOW_A12? - Ambil oil rate
OIL_D01untuk 18 Sep 2025 penuh (00:00–23:59). - Tampilkan trend
OIL_B07pada minggu 15–16 Sep 2025. - Ambil oil rate
FLOW_A12antara 06:00–12:00 pada2025-09-01. - Bandingkan flow rate
OIL_D01vsOIL_D02pada 18 Sep 2025. - Ambil timeseries untuk
FLOW_C03,FLOW_E05,FLOW_F10selama 3 Sep 2025, lalu tampilkan rata-rata harian.
Troubleshooting
1) /chat/stream tidak menemukan dokumen (retrieved_chunks kosong)
-
Cek endpoint hybrid:
curl "http://localhost:8080/rag/search_v2?q=Production%20Forecast%20Q4%202025"Pastikan respon berformat:
{ "query":"...", "alpha":0.6, "count":10, "retrieved_chunks":[ {"doc_id":"DOC-1005","title":"...","url":"...","page_no":3,"snippet":"...","score":0.123} ] } -
Jika struktur sudah benar namun SSE masih kosong, pastikan NormalizePlan aktif dan
ragFnpadachat_sse_handler.gomembacaretrieved_chunks[*].page_no(bukanpage).
2) Error decode saat MCP plan RAG
-
Pastikan consumer mem‐decode objek yang memiliki field
retrieved_chunks(bukan langsung slice). -
Contoh decode benar (Go):
var resp struct { RetrievedChunks []struct { DocID string `json:"doc_id"` ... } `json:"retrieved_chunks"` }
3) LLM/Embeddings tidak tersedia
- Sistem tetap jalan: RAG hybrid + fallback extractive pada
answer_with_docs. TambahkanOPENAI_API_KEYuntuk jawaban yang lebih natural.
4) Observability
- Cek
/healthz,/metrics, dan log dilogs/.
Lisensi
MIT — lihat berkas LICENSE.
💡 Kenapa Menggunakan Go (Golang)?
Proyek MCP + RAG dibangun dengan Go karena beberapa alasan teknis dan bisnis yang sangat relevan untuk industri migas:
🚀 Performa Tinggi & Efisiensi Compiled → binary cepat, stabil, minim overhead. Ideal untuk query lintas domain dengan latensi rendah.
⚡ Concurrency dengan Goroutines Data dari banyak sumber (SCADA, IoT, ERP) bisa ditarik paralel.
🛡️ Stabil & Teruji Digunakan di Kubernetes, Docker, Hashicorp Consul.
📦 Deploy Mudah (Single Binary) Tidak ada dependency hell, mudah pindah ke on-premise/private cloud.
🔄 Mendukung Real-Time Streaming (SSE) Ribuan koneksi tetap ringan dengan net/http dan goroutines.
Kredit
Dikembangkan oleh Kukuh Tripamungkas Wicaksono (Kukuh TW) sebagai PoC arsitektur MCP + RAG untuk domain migas.

