Skip to main content
Glama
suryast

indonesia-civic-stack

by suryast

🇮🇩 indonesia-civic-stack

PyPI MCP Registry CI Python License

Produktionsreife Scraper, Normalisierer und API-Wrapper für indonesische Regierungsdatenquellen.

Die Infrastrukturebene hinter halalkah.id, legalkah.id und ein öffentliches Gut für die indonesische Civic-Tech- und Entwickler-Community.


Warum

Indonesische öffentliche Daten sind nominell offen, aber praktisch unzugänglich. Jeder Entwickler, der zivile Werkzeuge baut, löst dieselben Scraping-Probleme unabhängig voneinander: BPOM-Produktregistrierungen, BPJPH-Halal-Zertifikate, AHU-Unternehmensregister. Scraper veralten innerhalb von Monaten, wenn sich Portale ändern. Es gibt keine gemeinsame, gepflegte Schicht.

Dieses Repository ist diese Schicht. Ein pip install, um indonesische Regierungsportale abzufragen – keine maßgeschneiderten Scraper mehr.

KI-Agent zuerst

Dieses SDK ist sowohl für Menschen als auch für KI-Agenten konzipiert:

  • 🤖 46 MCP-Tools – in Claude, GPT oder einen beliebigen MCP-kompatiblen Agenten einbinden

  • 📋 SKILL.md – KI-Agenten-Fähigkeitenermittlung (AgentSkills-Format)

  • 🧑💻 AGENTS.md – Architekturleitfaden für Codierungsagenten (Claude Code, Codex, Cursor)

  • 📝 CLAUDE.md – Claude-Code-spezifische Anweisungen

  • ✅ Typisierte Antworten – CivicStackResponse-Envelope, niemals rohe Dictionaries

  • 🔁 Konsistente Muster – jedes Modul folgt demselben Vertrag


Related MCP server: openapi-mcp-sdk

Architektur

graph TB
    subgraph "Your App"
        A[halalkah.id] 
        B[legalkah.id]
        C[Your Project]
    end

    subgraph "civic-stack"
        SDK[Python SDK]
        MCP[MCP Servers]
        API[REST API]
        
        subgraph "Shared Layer"
            SC[shared/schema.py<br/>CivicStackResponse]
            HC[shared/http.py<br/>Rate limiting · Retries · Proxy]
        end

        subgraph "Phase 1"
            BPOM[bpom<br/>Food & Drug]
            BPJPH[bpjph<br/>Halal Certs]
            AHU[ahu<br/>Company Registry]
        end

        subgraph "Phase 2"
            OJK[ojk<br/>Financial Licenses]
            OSS[oss_nib<br/>Business ID]
            LPSE[lpse<br/>Procurement]
            KPU[kpu<br/>Elections]
        end

        subgraph "Phase 3"
            LHKPN[lhkpn<br/>Wealth Declarations]
            BPS[bps<br/>Statistics]
            BMKG[bmkg<br/>Weather & Disasters]
            SIMBG[simbg<br/>Building Permits]
        end
    end

    subgraph "Government Portals"
        P1[cekbpom.pom.go.id]
        P2[sertifikasi.halal.go.id]
        P3[ahu.go.id]
        P4[ojk.go.id]
        P5[oss.go.id]
        P6[lpse.*.go.id]
        P7[infopemilu.kpu.go.id]
        P8[elhkpn.kpk.go.id]
        P9[webapi.bps.go.id]
        P10[data.bmkg.go.id]
        P11[simbg.pu.go.id]
    end

    A & B & C --> SDK & MCP & API
    SDK & MCP & API --> SC
    SC --> BPOM & BPJPH & AHU & OJK & OSS & LPSE & KPU & LHKPN & BPS & BMKG & SIMBG
    BPOM & BPJPH & AHU & OJK & OSS & LPSE & KPU & LHKPN & BPS & BMKG & SIMBG --> HC
    BPOM --> P1
    BPJPH --> P2
    AHU --> P3
    OJK --> P4
    OSS --> P5
    LPSE --> P6
    KPU --> P7
    LHKPN --> P8
    BPS --> P9
    BMKG --> P10
    SIMBG --> P11

Anfrageablauf

sequenceDiagram
    participant App as Your App
    participant SDK as Civic SDK
    participant HTTP as shared/http.py
    participant Proxy as Proxy (optional)
    participant Portal as Gov Portal

    App->>SDK: search("paracetamol")
    SDK->>HTTP: civic_client(proxy_url)
    Note over HTTP: Auto-reads PROXY_URL<br/>from environment
    alt rewrite mode (CF Worker)
        HTTP->>Proxy: GET ?url=encoded_target
        Proxy->>Portal: Forwarded request
        Portal-->>Proxy: HTML/JSON response
        Proxy-->>HTTP: Response
    else connect mode (SOCKS/HTTP)
        HTTP->>Proxy: CONNECT tunnel
        Proxy->>Portal: Proxied request
        Portal-->>HTTP: Response
    else no proxy
        HTTP->>Portal: Direct request
        Portal-->>HTTP: Response
    end
    HTTP-->>SDK: httpx.Response
    SDK->>SDK: Parse + Normalize
    SDK-->>App: CivicStackResponse

Modulstatus

Modul

Quelle

Daten

Proxy

Status

bpom

cekbpom.pom.go.id

Lebensmittel-, Arzneimittel- und Kosmetikregistrierungen

🌐

✅ Aktiv

bpjph

cmsbl.halal.go.id

Halal-Zertifikate (über 1,98 Mio. Datensätze)

🌐

✅ Aktiv – zu REST-API migriert (v1.0.0)

ahu

ahu.go.id

Unternehmensregister – PT, CV, Yayasan, Koperasi

🇮🇩

⚠️ Seite umstrukturiert – Sucheingabe geändert (Apr. 2026)

ojk

www.ojk.go.id/waspada-investasi

Zugelassene Finanzinstitute + Waspada-Liste

🇮🇩

⚠️ Portal zu SharePoint migriert (Apr. 2026) – Scraper muss neu geschrieben werden

oss_nib

oss.go.id

Unternehmensidentität (NIB)

🇮🇩

⚠️ Seite umstrukturiert – Playwright findet keine Eingabefelder (Apr. 2026)

lpse

spse.inaproc.id

Öffentliches Beschaffungswesen

🇮🇩

✅ Aktiv – nicht mehr veraltet (v1.0.0)

kpu

infopemilu.kpu.go.id

Wahldaten – Kandidaten, Ergebnisse, Finanzen

🌐

✅ Aktiv

bps

webapi.bps.go.id

Statistische Datensätze (über 1.000)

🌐

✅ Aktiv (erfordert BPS_API_KEY)

bmkg

data.bmkg.go.id

Wetter-, Erdbeben- und Katastrophendaten

🌐

✅ Aktiv

simbg

simbg.pu.go.id

Baugenehmigungen (PBG) – Multi-Portal

🌐

✅ Aktiv

jdih

peraturan.go.id

Nationale Rechtsdatenbank – UU, PP, Perpres, Permen

🇮🇩

✅ Neu – Playwright-Scraping

ksei

web.ksei.co.id

Wertpapierstatistiken (62 monatliche PDFs) + registrierte Wertpapiere

🌐

✅ Neu – HTML-Scraping (kein Proxy erforderlich)

djpb

data-apbn.kemenkeu.go.id

APBN-Haushaltsthemen – Ziel/Realisierung/Erreichung

🇮🇩

✅ Neu – saubere REST-JSON-API

lhkpn

elhkpn.kpk.go.id

Vermögenserklärungen (Beamte)

—

✅ Aktiv – reCAPTCHA v3 über Playwright gelöst

🌐 = funktioniert weltweit 🇮🇩 = erfordert indonesischen Proxy (PROXY_URL setzen)

Jedes Modul gibt denselben CivicStackResponse-Envelope zurück – Datenquellen wechseln, ohne die Anwendungslogik anzufassen.

Modulreife

Modul

Scraper

Normalisierer

MCP

Tests

Portalstatus

bpom

✅

✅

✅

✅

✅

bpjph

✅

✅

✅

✅

✅ REST-API

ahu

✅

✅

✅

✅

⚠️ Seite umstrukturiert

ojk

✅

✅

✅

✅

⚠️ SharePoint-Migration

oss_nib

✅

✅

✅

✅

⚠️ Seite umstrukturiert

lpse

✅

✅

✅

✅

🇮🇩 geoblockt

kpu

✅

✅

✅

✅

✅

bps

✅

✅

✅

✅

✅

bmkg

✅

✅

✅

✅

✅

simbg

✅

✅

✅

✅

✅

jdih

✅

✅

❌

❌

🇮🇩 Playwright

ksei

✅

✅

❌

❌

✅ (kein Proxy erforderlich)

djpb

✅

✅

❌

❌

✅ REST-JSON-API

lhkpn

✅

✅

✅

✅

✅ Aktiv (Playwright)


Schnellstart

Installation

pip install indonesia-civic-stack          # Core SDK
pip install "indonesia-civic-stack[mcp]"   # + MCP server (40 tools)
pip install "indonesia-civic-stack[api]"   # + REST API (FastAPI + uvicorn)
pip install "indonesia-civic-stack[all]"   # Everything

Python SDK

import asyncio
from civic_stack.bpom.scraper import search as bpom_search
from civic_stack.bmkg.scraper import get_latest_earthquake

async def main():
    # Search BPOM product registry
    results = await bpom_search("paracetamol")
    for r in results:
        if r.found:
            print(r.result)

    # Get latest earthquake
    eq = await get_latest_earthquake()
    print(eq.result)  # {'date': '...', 'magnitude': '5.2', ...}

asyncio.run(main())

MCP-Server (für KI-Agenten)

Alle 14 Module stellen 46 MCP-Tools für die Verwendung mit Claude, GPT oder einem beliebigen MCP-kompatiblen Agenten bereit.

# Install locally:
pip install "indonesia-civic-stack[mcp]"
claude mcp add civic-stack -- civic-stack-mcp

# Or deploy your own remote server (Railway one-click):
# See "Self-Hosted MCP Server" section below

MCP-Serverklassen unterstützen zwei Initialisierungsstile:

# Style 1: Explicit init
class BpomMCPServer(CivicStackMCPBase):
    def __init__(self):
        super().__init__("bpom")

# Style 2: Class attribute
class BmkgMCPServer(CivicStackMCPBase):
    module_name = "bmkg"

REST API

# Run all modules
uvicorn app:app --port 8000

# With API key auth (recommended)
CIVIC_API_KEY=your-secret-key uvicorn app:app --port 8000

# Individual module
uvicorn modules.bpom.app:app --port 8001

# With proxy
PROXY_URL=socks5://id-proxy:1080 uvicorn app:app --port 8000
# Endpoints
GET /bpom/check/MD123456789012
GET /bpom/search?q=paracetamol
GET /bpjph/check/BPJPH-12345
GET /ahu/search?q=PT+Contoh+Indonesia
GET /ojk/check?name=Bank+BCA
GET /kpu/candidate/search?q=Joko
GET /lhkpn/search?q=Anies          # ✅ reCAPTCHA v3 solved via Playwright
GET /bps/search?q=inflasi           # Requires BPS_API_KEY
GET /bmkg/weather?city=jakarta
GET /simbg/search?q=Jakarta+Selatan

Antwort-Envelope

Jedes Modul gibt CivicStackResponse zurück:

{
  "result": {"product_name": "...", "registration_status": "ACTIVE"},
  "found": true,
  "status": "ACTIVE",
  "confidence": 1.0,
  "source_url": "https://cekbpom.pom.go.id/...",
  "fetched_at": "2026-03-14T06:30:00Z",
  "module": "bpom"
}

Statuswerte: ACTIVE, EXPIRED, SUSPENDED, REVOKED, NOT_FOUND, ERROR.

Wenn ein Modul sein Portal nicht erreichen kann oder eine Konfiguration fehlt (z. B. BPS_API_KEY), gibt es einen Fehler-Envelope zurück, anstatt abzustürzen:

{
  "result": null,
  "found": false,
  "status": "ERROR",
  "confidence": 0.0,
  "source_url": "https://webapi.bps.go.id",
  "module": "bps",
  "detail": "BPS_API_KEY not set. Register at https://webapi.bps.go.id/developer/register"
}

Modul-Interna

civic_stack/bpom/
├── __init__.py
├── app.py          # FastAPI application
├── normalizer.py   # Raw HTML/JSON → structured dict
├── router.py       # FastAPI routes
├── scraper.py      # fetch() + search() — core logic
├── server.py       # FastMCP MCP server
├── Dockerfile
└── README.md

Die shared/-Ebene bietet:

  • schema.py – CivicStackResponse-Pydantic-Modell, Status-Enum, Hilfskonstruktoren

  • http.py – civic_client()-Factory mit Auto-Proxy, Ratenbegrenzer, exponentiellem Backoff-Retry, URL-Umschreibung für CF-Worker-Proxys

  • mcp.py – CivicStackMCPBase-Abstrakte Basisklasse für MCP-Server


Bereitstellungshinweise

Geoblocking- und Proxy-Anforderungen

Die meisten indonesischen Regierungsportale (*.go.id) beschränken den Zugriff auf indonesische IP-Adressen. Wenn Sie außerhalb Indonesiens bereitstellen, müssen Sie PROXY_URL setzen, um Anfragen über einen indonesischen Endpunkt zu leiten.

# Option 1: Indonesian VPS/SOCKS proxy (recommended for production)
export PROXY_URL="socks5://id-proxy.example.com:1080"
export PROXY_MODE="connect"

# Option 2: CF Worker proxy (free, but limited — see below)
export PROXY_URL="https://your-proxy.workers.dev"
# PROXY_MODE auto-detects "rewrite" for *.workers.dev

Ohne Proxy ist zu erwarten: DNS-Auflösungsfehler, Verbindungszeitüberschreitungen oder HTTP-403/404-Antworten der meisten Module.

Das SDK liest PROXY_URL automatisch aus der Umgebung – keine Codeänderungen in Scrapern oder MCP-Servern erforderlich.

Proxy-Modi

Modus

PROXY_URL-Beispiel

Funktionsweise

connect

socks5://id-proxy:1080

Standard-HTTP/SOCKS-CONNECT-Proxy über httpx-Transport

rewrite

https://x.workers.dev

Schreibt URLs zu ?url=<target> um (automatisch erkannt für *.workers.dev)

none

(unset)

Direktverbindung

Automatische Erkennung mit PROXY_MODE=connect|rewrite überschreiben.

CF Worker Proxy

Ein einsatzbereiter CF-Worker-Proxy ist in proxy/ enthalten. Bereitstellen mit:

cd proxy && npx wrangler deploy

⚠️ CF-Worker-Einschränkung: Viele .go.id-Portale befinden sich selbst hinter Cloudflare. CF-Worker, die fetch()-Aufrufe an andere CF-geschützte Ursprünge durchführen, erhalten 403/522-Fehler. Dies ist eine bekannte Cloudflare-Einschränkung.

Über CF-Worker-Proxy verifiziert:

Portal

Status

Hinweise

data.bmkg.go.id

✅ Funktioniert

JSON-API, nicht hinter CF

cekbpom.pom.go.id

❌ 403/522

Portal ist CF-geschützt

api.ojk.go.id

❌ DNS tot

NXDOMAIN seit März 2026

infopemilu.kpu.go.id

❌ 403

CF-geschützt

lpse.*.go.id

❌ 403

CF-geschützt

elhkpn.kpk.go.id

✅ 200

reCAPTCHA v3 über Playwright-Headless-Browser gelöst

Für die Produktion mit CF-geschützten Portalen verwenden Sie einen indonesischen VPS mit einem SOCKS5/HTTP-Proxy und setzen Sie PROXY_MODE=connect.

Testergebnisse zur Geobeschränkung (März 2026)

Getestet von drei Standorten aus, um zu ermitteln, welche Portale Geoblocking vs. WAF durchsetzen:

Portal

Sydney (AU)

Singapur

Jakarta (ID)

Bewertung

ahu.go.id

❌

✅

✅

Geoblockiert (SEA+ OK)

elhkpn.kpk.go.id

❌

✅

✅

Geoblockiert (SEA+ OK)

ojk.go.id

❌ 403

❌ 403

✅

Nur Indonesien

jaga.id (KPK)

✅

✅

✅

Keine Einschränkung

data.bmkg.go.id

✅

✅

✅

Keine Einschränkung

cekbpom.pom.go.id

⚠️

⚠️

⚠️

CF-geschützt (alle Standorte)

webapi.bps.go.id

❌ 403

❌ 403

❌ 403

WAF, nicht geobasiert (API-Schlüssel erforderlich)

lpse.lkpp.go.id

❌

❌

❌

Unzuverlässig (alle Standorte)

coretaxdjp.pajak.go.id

❌

❌

❌

Unzuverlässig (alle Standorte)

Fazit: Ein indonesischer Proxy (z. B. CloudKilat Jakarta) entsperrt OJK – das wichtigste geoblockierte Portal. Singapur entsperrt AHU + LHKPN. BPS- und LPSE-Fehler sind nicht geobezogen.

VPS-Härtungslektion

⚠️ Deaktiviere niemals die Passwort-Authentifizierung und starte sshd in einem einzigen automatisierten Skript auf einem frischen VPS neu. Wenn der SSH-Schlüssel nicht korrekt kopiert wurde, bist du ausgesperrt und hast keinen Wiederherstellungsweg außer einer Web-Konsole. Immer: (1) Schlüssel kopieren, (2) prüfen, dass der Schlüssel-Login in einer separaten Sitzung funktioniert, (3) dann die Passwort-Authentifizierung deaktivieren.

Stabilität der Portal-URLs

Indonesische Regierungsportale ändern ihre URL-Struktur häufig ohne Vorankündigung. Bekannte Änderungen Stand März 2026:

Modul

Alte URL

Neue URL

Status

BPOM

/index.php/home/produk/1/{keyword}/...

/all-produk?q={keyword}

✅ Aktualisiert

KPU

/Pemilu/caleg/list

/Pemilu/Peserta_pemilu

✅ Aktualisiert

BMKG

/DataMKG/MEWS/Warning/cuacasignifikan.json

/DataMKG/TEWS/gempadirasakan.json

✅ Aktualisiert

LHKPN

/portal/user/check_search_announ

reCAPTCHA v3 (Playwright)

🟢 Aktiv

Module, die 60 Tage lang ausfallen, werden als DEGRADED markiert und können archiviert werden.

Browserbasierte Module

Einige Portale erfordern einen echten Browser (JavaScript-Rendering, Anti-Bot-Schutz):

Modul

Browser

Anti-Bot

bpjph

Playwright (Chromium)

Standard

ahu

Playwright + Camoufox

Bot-Management (Datacenter-IP-Blockierung)

oss_nib

Playwright (Chromium)

Standard

Browser-Abhängigkeiten installieren:

pip install ".[playwright]"
playwright install chromium

# For AHU (optional, improves success rate):
pip install camoufox && python -m camoufox fetch

API-Schlüssel

Modul

Schlüssel erforderlich

Env-Variable

Registrierung

BPS

Ja

BPS_API_KEY

webapi.bps.go.id/developer/register (kostenlos)

Alle anderen

Nein

—

—

Ohne BPS_API_KEY gibt das BPS-Modul ein Fehler-Envelope zurück (kein Absturz):

{"status": "ERROR", "detail": "BPS_API_KEY not set. Register at ..."}

MCP-Tool-Inventar

Alle 11 Module stellen insgesamt 40 MCP-Tools bereit:

Modul

Tools

Anzahl

bpom

check_bpom, search_bpom, get_bpom_status

3

bpjph

check_halal_cert, lookup_halal_by_product, get_halal_status, cross_reference_halal_bpom

4

ahu

lookup_company_ahu, get_company_directors, verify_company_status, search_companies_ahu

4

ojk

check_ojk_license, search_ojk_institutions, get_ojk_status, check_ojk_waspada

4

oss_nib

lookup_nib, verify_nib, search_oss_businesses

3

lpse

lookup_vendor_lpse, search_lpse_vendors, search_lpse_tenders, get_lpse_portals

4

kpu

get_candidate, search_kpu_candidates, get_election_results_kpu, get_campaign_finance_kpu

4

lhkpn

get_lhkpn, search_lhkpn, compare_lhkpn, get_lhkpn_pdf

4

bps

search_bps_datasets, get_bps_indicator, list_bps_regions

3

bmkg

get_bmkg_alerts, get_weather_forecast, get_earthquake_history, get_latest_earthquake

4

simbg

lookup_building_permit, search_permits_by_area, list_simbg_portals

3


KI-Agenten-Integration

Dieses Repository ist für KI-Agenten als erstklassige Nutzer konzipiert.

Für KI-Coding-Agenten

Datei

Zweck

Agent

AGENTS.md

Architektur, Muster, kritische Regeln, Stolperfallen

Alle Coding-Agenten

CLAUDE.md

Befehle, Do's/Don'ts-Regeln, Styleguide

Claude Code

.cursorrules

Projektregeln für Cursor

Cursor

.github/copilot-instructions.md

Anweisungen für Copilot

GitHub Copilot

CONTRIBUTING.md

Modulvertrag + PR-Checkliste

Alle

SKILL.md

Skill-Erkennung (AgentSkills-Format)

Skill-bewusste Agenten

PROMPTS.md

Beispiel-Prompts + interaktive Artefakt-Rezepte

Alle KI-Agenten

MCP-Tools verbinden (eine Option wählen)

Option A – Selbst gehosteter Remote-Server (eigene Bereitstellung):

Deploy on Railway

# After deploying to Railway/Fly/Render, add to Claude Code:
claude mcp add civic-stack --transport http https://your-deployment.up.railway.app/mcp

# Or Claude Desktop — add to claude_desktop_config.json:
{
  "mcpServers": {
    "civic-stack": {
      "transport": "streamable-http",
      "url": "https://your-deployment.up.railway.app/mcp"
    }
  }
}

Hinweis: Es gibt keinen gemeinsamen gehosteten Server. Jeder Nutzer stellt seine eigene Instanz bereit, um Proxy-Einstellungen, Ratenbegrenzungen und API-Schlüssel zu kontrollieren.

Option B – Lokale Installation über pip:

pip install "indonesia-civic-stack[mcp]"
claude mcp add civic-stack -- civic-stack-mcp

Option C – Repository klonen (Auto-Erkennung):

git clone https://github.com/suryast/indonesia-civic-stack.git
cd indonesia-civic-stack
pip install -e ".[mcp]"
claude  # Claude Code auto-detects .mcp.json — 40 tools available immediately

Alle drei Optionen bieten dir dieselben 40 Tools. Dann frag:

„Prüfe, ob die BPOM-Registrierung MD 123456789 noch aktiv ist" „Suche nach Unternehmen namens ‚Maju Bersama' im AHU-Register" „Was war das letzte Erdbeben in Indonesien?"

Weitere Beispiel-Prompts und interaktive Artefakt-Rezepte findest du in PROMPTS.md.

REST-API

pip install "indonesia-civic-stack[api]"
civic-stack api --port 8000
# GET http://localhost:8000/bpom/search?q=paracetamol

Beispiel-Prompts

Sobald die MCP-Tools verbunden sind, probiere diese mit deinem KI-Agenten aus:

Lebensmittelsicherheit „Prüfe, ob die BPOM-Registrierungsnummer MD 123456789 noch aktiv ist" „Suche nach allen bei BPOM registrierten Paracetamol-Produkten"

Halal-Verifizierung „Ist Produkt XYZ halal-zertifiziert? Gleiche mit der BPOM-Registrierung ab" „Finde alle Halal-Zertifikate, die an PT Indofood ausgestellt wurden"

Unternehmens-Due-Diligence „Schlage PT Maju Bersama im AHU-Unternehmensregister nach und prüfe, wer die Geschäftsführer sind" „Ist dieses Unternehmen OJK-lizenziert? Prüfe sowohl das Lizenzregister als auch die Waspada-Liste (Warnliste)"

Öffentliche Finanzen „Suche LHKPN-Vermögenserklärungen für Beamte in Jakarta" „Finde öffentliche Vergabeausschreibungen für Straßenbau auf LPSE"

Katastrophen & Wetter „Was war das letzte Erdbeben in Indonesien?" „Hole die Wettervorhersage für DKI Jakarta von BMKG"

Statistiken „Finde BPS-Datensätze zu Armutsquoten nach Provinz" „Hole den Inflationsindikator für die letzten 5 Jahre"

Multi-Quellen-Abfragen „Ich möchte ein Lebensmittelunternehmen verifizieren: Prüfe AHU auf Registrierung, OJK auf Finanzlizenz, BPOM auf Produktregistrierungen und BPJPH auf Halal-Zertifikate" „Vergleiche die LHKPN-Vermögenserklärungen dieser beiden Beamten über die letzten 3 Berichtszeiträume"

Design-Entscheidungen für KI-Agenten

  1. Einheitliches Antwort-Envelope – jedes Tool gibt CivicStackResponse mit denselben Feldern zurück. Agenten benötigen keine modulspezifische Parsing-Logik.

  2. Fehler-Envelopes statt Ausnahmen – Agenten erhalten strukturierte Fehlerinformationen, mit denen sie arbeiten können, keine Stacktraces.

  3. Selbstdokumentierende Tools – MCP-Toolbeschreibungen enthalten Parametertypen, erwartete Werte und Antwortformat.

  4. Deterministische Benennung – check_<module>, search_<module>, get_<module>_status-Muster über alle Module.


Sicherheit

Funktion

Konfiguration

Standard

API-Schlüssel-Authentifizierung

CIVIC_API_KEY Env-Variable

Deaktiviert (offen)

Ratenbegrenzung

CIVIC_RATE_LIMIT Env-Variable

60 Anfragen/min pro IP

Proxy-Allowlist

CIVIC_ALLOWED_PROXIES Env-Variable

Jede nicht-private IP

SSRF-Schutz

Integriert

Blockiert RFC 1918 + localhost

Container-Benutzer

Dockerfile

Nicht-Root (civicapp, uid 1000)

# Production deployment
export CIVIC_API_KEY="your-secret-key"
export CIVIC_RATE_LIMIT=30                          # 30 req/min
export CIVIC_ALLOWED_PROXIES="proxy.example.com"    # optional proxy allowlist
export PROXY_URL="socks5://id-proxy:1080"           # Indonesian proxy
uvicorn app:app --host 0.0.0.0 --port 8000

Docker

docker compose up                             # All modules
docker build -t civic-bpom civic_stack/bpom/      # Individual
docker run -p 8001:8000 -e CIVIC_API_KEY=secret -e PROXY_URL=socks5://proxy:1080 civic-bpom

Entwicklung

git clone https://github.com/suryast/indonesia-civic-stack.git
cd indonesia-civic-stack
python -m venv .venv && source .venv/bin/activate
pip install -e ".[all,dev]"
playwright install chromium

pytest -v              # VCR replay — no live portal calls
ruff check .           # Lint
ruff format --check .  # Format check
mypy shared/           # Type check

Tests

pytest -v                       # 89 tests, VCR replay (no live calls)
pytest tests/bpom/ -v           # Single module
pytest --tb=short -q            # Quick summary
pie title Test Coverage (89 tests)
    "BPOM" : 7
    "BPJPH" : 8
    "AHU" : 12
    "OJK" : 4
    "KPU" : 5
    "LPSE" : 9
    "OSS-NIB" : 6
    "LHKPN" : 10
    "BPS" : 7
    "BMKG" : 8
    "SIMBG" : 7
    "Schema" : 6

Mitwirken

Siehe CONTRIBUTING.md. Jeder Modul-PR muss Folgendes enthalten:

  • fetch() und search(), die CivicStackResponse zurückgeben

  • FastAPI-Router + FastMCP-Server

  • 3+ VCR-Test-Fixtures

  • Modul-README

Ein Modul, das 60 Tage lang ausfällt, wird als DEGRADED markiert und archiviert.


Verwendet von

Beispielarchitekturen

Einfach: Halal-Produktprüfer

Eine Single-Page-App, die prüft, ob ein Produkt halal-zertifiziert ist. Ein Modul, kein Proxy für indonesische Nutzer erforderlich.

graph LR
    subgraph Client
        A[Mobile App / Web]
    end

    subgraph Your Server
        B[FastAPI]
        C[bpjph module]
    end

    subgraph Government Portal
        D[sertifikasi.halal.go.id]
    end

    A -->|POST /check| B
    B --> C
    C -->|scrape| D
    D -->|HTML| C
    C -->|CivicStackResponse| B
    B -->|JSON| A

    style A fill:#f9f9f9,stroke:#333
    style B fill:#e8f5e9,stroke:#2e7d32
    style C fill:#e8f5e9,stroke:#2e7d32
    style D fill:#fff3e0,stroke:#e65100
# app.py — 15 lines, production-ready
from fastapi import FastAPI
from civic_stack.bpjph.scraper import fetch

app = FastAPI()

@app.get("/check/{product_id}")
async def check_halal(product_id: str):
    result = await fetch(product_id)
    return {"halal": result.found, "data": result.result}

Mittel: Multi-Quellen-Due-Diligence-API

Ein Compliance-Tool, das ein Unternehmen über mehrere Regierungsdatenbanken hinweg abgleicht. Läuft hinter einem Proxy für den Einsatz im Ausland.

graph TB
    subgraph Client
        A[Compliance Dashboard]
    end

    subgraph Your Infrastructure
        B[API Gateway]
        C[Due Diligence Service]
        D[ahu module]
        E[ojk module]
        F[bpom module]
        G[oss_nib module]
        H[(Redis Cache)]
    end

    subgraph Proxy Layer
        I[CF Worker Proxy]
    end

    subgraph Government Portals
        J[ahu.go.id]
        K[www.ojk.go.id]
        L[cekbpom.pom.go.id]
        M[oss.go.id]
    end

    A -->|GET /company/:name| B
    B --> C
    C --> H
    C --> D & E & F & G
    D & E & F & G -->|via PROXY_URL| I
    I --> J & K & L & M

    style A fill:#f9f9f9,stroke:#333
    style B fill:#e3f2fd,stroke:#1565c0
    style C fill:#e8f5e9,stroke:#2e7d32
    style D fill:#e8f5e9,stroke:#2e7d32
    style E fill:#e8f5e9,stroke:#2e7d32
    style F fill:#e8f5e9,stroke:#2e7d32
    style G fill:#e8f5e9,stroke:#2e7d32
    style H fill:#fce4ec,stroke:#c62828
    style I fill:#fff8e1,stroke:#f57f17
    style J fill:#fff3e0,stroke:#e65100
    style K fill:#fff3e0,stroke:#e65100
    style L fill:#fff3e0,stroke:#e65100
    style M fill:#fff3e0,stroke:#e65100
# due_diligence.py — parallel checks across 4 portals
import asyncio
from civic_stack.ahu.scraper import search as ahu_search
from civic_stack.ojk.scraper import search as ojk_search
from civic_stack.bpom.scraper import search as bpom_search
from civic_stack.oss_nib.scraper import search as nib_search

async def check_company(name: str) -> dict:
    ahu, ojk, bpom, nib = await asyncio.gather(
        ahu_search(name),
        ojk_search(name),
        bpom_search(name),
        nib_search(name),
    )
    return {
        "company": name,
        "registered": any(r.found for r in ahu),
        "ojk_licensed": any(r.found for r in ojk),
        "bpom_products": len([r for r in bpom if r.found]),
        "nib_valid": any(r.found for r in nib),
        "risk_flags": _assess_risk(ahu, ojk, bpom, nib),
    }

Fortgeschritten: KI-Agent mit MCP-Tools

Ein KI-Assistent, der Fragen in natürlicher Sprache zu indonesischen Bürgerdaten mithilfe von MCP-Tools beantwortet. Der Agent entscheidet, welche Portale abgefragt werden sollen.

sequenceDiagram
    participant User
    participant Agent as AI Agent (Claude/GPT)
    participant MCP as MCP Server
    participant SDK as civic-stack modules
    participant Proxy as CF Worker Proxy
    participant Gov as Government Portals

    User->>Agent: "Is PT Maju Bersama a legitimate company<br/>with halal certification?"

    Note over Agent: Agent reasons: need AHU (company)<br/>+ BPJPH (halal) + OJK (finance)

    Agent->>MCP: search_companies_ahu("PT Maju Bersama")
    MCP->>SDK: ahu.search()
    SDK->>Proxy: GET ahu.go.id/...
    Proxy->>Gov: Forward request
    Gov-->>Proxy: HTML response
    Proxy-->>SDK: Response
    SDK-->>MCP: CivicStackResponse
    MCP-->>Agent: {found: true, status: "ACTIVE", ...}

    Agent->>MCP: check_halal_cert("PT Maju Bersama")
    MCP->>SDK: bpjph.fetch()
    SDK->>Proxy: GET sertifikasi.halal.go.id/...
    Proxy-->>SDK: Response
    SDK-->>MCP: CivicStackResponse
    MCP-->>Agent: {found: true, status: "ACTIVE", ...}

    Agent->>MCP: check_ojk_license("PT Maju Bersama")
    MCP->>SDK: ojk.fetch()
    SDK-->>MCP: {found: false, status: "NOT_FOUND"}

    Note over Agent: Agent synthesizes results

    Agent->>User: "PT Maju Bersama is a registered company (AHU ✅)<br/>with active halal certification (BPJPH ✅).<br/>No OJK financial license found — this is normal<br/>for non-financial companies."
# Connect MCP servers to Claude Desktop — one command per module
claude mcp add civic-ahu   -- python -m civic_stack.ahu.server
claude mcp add civic-bpjph -- python -m civic_stack.bpjph.server
claude mcp add civic-ojk   -- python -m civic_stack.ojk.server

# Or run unified REST API for HTTP-based agents
PROXY_URL=https://your-proxy.workers.dev uvicorn app:app

Verwandt

  • indonesia-civic-signal-monitor – Anomalie-Erkennungs-Engine auf Basis dieses SDK, überwacht 11 Regierungsdatenquellen auf berichtenswerte Änderungen

  • indonesia-gov-apis – Referenzdokumentation für 50+ indonesische Regierungs-APIs

  • datarakyat.id – Projekt-Startseite mit vollständiger Moduldokumentation

Lizenz

MIT – siehe LICENSE

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    D
    maintenance
    Provides seamless access to Malaysia's official government data catalogue, enabling developers to discover, explore, and fetch datasets from the Malaysian government's open data platform through a simple, unified interface.
    4
    7 npm
    12
    ISC
  • A
    license
    Not graded
    quality
    B
    maintenance
    Provides a ready-to-run MCP server and Python SDK for securely interacting with Openapi.com APIs, enabling businesses to retrieve official documents and data through natural language.
    22
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Provides a single MCP endpoint for 90+ tools across 42 backend servers (search, legal, domain, etc.) with per-call credit billing and a single API key.
    1
    MIT