Skip to main content
Glama
suryast

indonesia-civic-stack

by suryast

🇮🇩 indonesia-civic-stack

PyPI MCP Registry CI Python License

Готовые к продакшену скрейперы, нормализаторы и API-обёртки для правительственных источников данных Индонезии.

Инфраструктурный слой, лежащий в основе halalkah.id, legalkah.id, и общественное благо для индонезийского сообщества civic tech и разработчиков.


Зачем

Индонезийские открытые данные формально открыты, но практически недоступны. Каждый разработчик, создающий гражданские инструменты, заново решает одни и те же задачи скрейпинга: регистрации продуктов BPOM, халяльные сертификаты BPJPH, записи компаний AHU. Скрейперы приходят в негодность за считанные месяцы, когда порталы меняются. Не существует общего поддерживаемого слоя.

Этот репозиторий и есть такой слой. Один pip install для запросов к правительственным порталам Индонезии — никаких больше самодельных скрейперов.

В первую очередь для ИИ-агентов

Этот SDK предназначен и для людей, и для ИИ-агентов:

  • 🤖 46 MCP-инструментов — подключайтесь к Claude, GPT или любому MCP-совместимому агенту

  • 📋 SKILL.md — обнаружение навыков ИИ-агента (формат AgentSkills)

  • 🧑💻 AGENTS.md — архитектурное руководство для агентов-программистов (Claude Code, Codex, Cursor)

  • 📝 CLAUDE.md — инструкции, специфичные для Claude Code

  • ✅ Типизированные ответы — обёртка CivicStackResponse, никогда не сырые словари

  • 🔁 Единообразные паттерны — каждый модуль следует одному и тому же контракту


Related MCP server: openapi-mcp-sdk

Архитектура

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

Поток запросов

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

Статус модулей

Модуль

Источник

Данные

Прокси

Статус

bpom

cekbpom.pom.go.id

Регистрации продуктов питания, лекарств, косметики

🌐

✅ Активен

bpjph

cmsbl.halal.go.id

Халяльные сертификаты (1.98M+ записей)

🌐

✅ Активен — переведён на REST API (v1.0.0)

ahu

ahu.go.id

Реестр компаний — PT, CV, Yayasan, Koperasi

🇮🇩

⚠️ Страница переструктурирована — изменилось поле поиска (апр. 2026)

ojk

www.ojk.go.id/waspada-investasi

Лицензированные финансовые организации + список Waspada

🇮🇩

⚠️ Портал переведён на SharePoint (апр. 2026) — скрейпер нужно переписать

oss_nib

oss.go.id

Бизнес-идентификатор (NIB)

🇮🇩

⚠️ Страница переструктурирована — Playwright не находит поля ввода (апр. 2026)

lpse

spse.inaproc.id

Государственные закупки

🇮🇩

✅ Активен — больше не deprecated (v1.0.0)

kpu

infopemilu.kpu.go.id

Данные выборов — кандидаты, результаты, финансы

🌐

✅ Активен

bps

webapi.bps.go.id

Статистические наборы данных (1,000+)

🌐

✅ Активен (требуется BPS_API_KEY)

bmkg

data.bmkg.go.id

Данные о погоде, землетрясениях и стихийных бедствиях

🌐

✅ Активен

simbg

simbg.pu.go.id

Разрешения на строительство (PBG) — мультипортальные

🌐

✅ Активен

jdih

peraturan.go.id

Национальная правовая база — UU, PP, Perpres, Permen

🇮🇩

✅ Новый — скрейпинг через Playwright

ksei

web.ksei.co.id

Статистика по ценным бумагам (62 ежемесячных PDF) + зарегистрированные ценные бумаги

🌐

✅ Новый — HTML-скрейпинг (прокси не нужен)

djpb

data-apbn.kemenkeu.go.id

Темы бюджета APBN — план/исполнение/достижение

🇮🇩

✅ Новый — чистый REST JSON API

lhkpn

elhkpn.kpk.go.id

Декларации об имуществе (чиновников)

—

✅ Активен — reCAPTCHA v3 решается через Playwright

🌐 = работает глобально 🇮🇩 = требует индонезийский прокси (задайте PROXY_URL)

Каждый модуль возвращает одну и ту же обёртку CivicStackResponse — меняйте источники данных, не трогая логику приложения.

Зрелость модулей

Модуль

Скрейпер

Нормализатор

MCP

Тесты

Статус портала

bpom

✅

✅

✅

✅

✅

bpjph

✅

✅

✅

✅

✅ REST API

ahu

✅

✅

✅

✅

⚠️ страница переструктурирована

ojk

✅

✅

✅

✅

⚠️ миграция на SharePoint

oss_nib

✅

✅

✅

✅

⚠️ страница переструктурирована

lpse

✅

✅

✅

✅

🇮🇩 гео-блокировка

kpu

✅

✅

✅

✅

✅

bps

✅

✅

✅

✅

✅

bmkg

✅

✅

✅

✅

✅

simbg

✅

✅

✅

✅

✅

jdih

✅

✅

❌

❌

🇮🇩 Playwright

ksei

✅

✅

❌

❌

✅ (прокси не нужен)

djpb

✅

✅

❌

❌

✅ REST JSON API

lhkpn

✅

✅

✅

✅

✅ Активен (Playwright)


Быстрый старт

Установка

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-сервер (для ИИ-агентов)

Все 14 модулей предоставляют 46 MCP-инструментов для использования с Claude, GPT или любым MCP-совместимым агентом.

# 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-серверов поддерживают два стиля инициализации:

# 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

Обёртка ответа

Каждый модуль возвращает CivicStackResponse:

{
  "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"
}

Значения статуса: ACTIVE, EXPIRED, SUSPENDED, REVOKED, NOT_FOUND, ERROR.

Когда модуль не может получить доступ к своему порталу или отсутствует конфигурация (например, BPS_API_KEY), он возвращает обёртку с ошибкой вместо того, чтобы аварийно завершиться:

{
  "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"
}

Внутреннее устройство модулей

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

Слой shared/ предоставляет:

  • schema.py — модель Pydantic CivicStackResponse, перечисление статусов, вспомогательные конструкторы

  • http.py — фабрика civic_client() с автоматическим прокси, ограничителем скорости, повторными попытками с экспоненциальной задержкой и переписыванием URL для прокси на CF Worker

  • mcp.py — абстрактный базовый класс CivicStackMCPBase для MCP-серверов


Примечания по развёртыванию

Гео-блокировка и требования к прокси

Большинство индонезийских правительственных порталов (*.go.id) ограничивают доступ, разрешая его только индонезийским IP-адресам. Если вы разворачиваете приложение за пределами Индонезии, вы обязаны задать PROXY_URL, чтобы направлять запросы через индонезийский endpoint.

# 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

Без прокси ожидайте: сбои разрешения DNS, таймауты соединения или ответы HTTP 403/404 от большинства модулей.

SDK автоматически читает PROXY_URL из окружения — никаких изменений кода в скрейперах или MCP-серверах не требуется.

Режимы прокси

Режим

Пример PROXY_URL

Как работает

connect

socks5://id-proxy:1080

Стандартный HTTP/SOCKS CONNECT-прокси через транспорт httpx

rewrite

https://x.workers.dev

Переписывает URL в ?url=<target> (автоопределяется для *.workers.dev)

none

(не задан)

Прямое соединение

Переопределите автоматическое определение с помощью PROXY_MODE=connect|rewrite.

Прокси на CF Worker

Готовый к развёртыванию прокси на CF Worker включён в proxy/. Разверните с помощью:

cd proxy && npx wrangler deploy

⚠️ Ограничение CF Worker: Многие порталы .go.id сами находятся за Cloudflare. CF Workers, выполняющие вызовы fetch() к другим источникам, защищённым CF, получают ошибки 403/522. Это известное ограничение Cloudflare.

Проверено через прокси CF Worker:

Портал

Статус

Примечания

data.bmkg.go.id

✅ Работает

JSON API, не за CF

cekbpom.pom.go.id

❌ 403/522

Портал защищён CF

api.ojk.go.id

❌ DNS не работает

NXDOMAIN с марта 2026

infopemilu.kpu.go.id

❌ 403

Защищён CF

lpse.*.go.id

❌ 403

Защищён CF

elhkpn.kpk.go.id

✅ 200

reCAPTCHA v3 решается через headless-браузер Playwright

Для продакшена с порталами, защищёнными CF, используйте индонезийский VPS с прокси SOCKS5/HTTP и установите PROXY_MODE=connect.

Результаты проверки гео-ограничений (март 2026)

Проверено из трёх местоположений, чтобы определить, какие порталы применяют гео-блокировку, а какие WAF:

Портал

Сидней (AU)

Сингапур

Джакарта (ID)

Вердикт

ahu.go.id

❌

✅

✅

Гео-блокировка (SEA+ OK)

elhkpn.kpk.go.id

❌

✅

✅

Гео-блокировка (SEA+ OK)

ojk.go.id

❌ 403

❌ 403

✅

Только ID

jaga.id (KPK)

✅

✅

✅

Без ограничений

data.bmkg.go.id

✅

✅

✅

Без ограничений

cekbpom.pom.go.id

⚠️

⚠️

⚠️

Защита CF (все локации)

webapi.bps.go.id

❌ 403

❌ 403

❌ 403

WAF, не гео (нужен API-ключ)

lpse.lkpp.go.id

❌

❌

❌

Нестабильный (все локации)

coretaxdjp.pajak.go.id

❌

❌

❌

Нестабильный (все локации)

Вывод: Индонезийский прокси (например, CloudKilat Jakarta) открывает доступ к OJK — самому важному гео-ограниченному порталу. Сингапур открывает AHU + LHKPN. Сбои BPS и LPSE не связаны с гео-блокировками.

Урок по усилению защиты VPS

⚠️ Никогда не отключайте парольную аутентификацию и не перезапускайте sshd одним автоматизированным скриптом на свежем VPS. Если SSH-ключ был скопирован неправильно, вы будете заблокированы без возможности восстановления, кроме веб-консоли. Всегда: (1) копируйте ключ, (2) проверяйте, что вход по ключу работает в отдельной сессии, (3) только затем отключайте парольную аутентификацию.

Стабильность URL-адресов порталов

Индонезийские государственные порталы часто меняют структуру URL без предупреждения. Известные изменения по состоянию на март 2026 года:

Модуль

Старый URL

Новый URL

Статус

BPOM

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

/all-produk?q={keyword}

✅ Обновлён

KPU

/Pemilu/caleg/list

/Pemilu/Peserta_pemilu

✅ Обновлён

BMKG

/DataMKG/MEWS/Warning/cuacasignifikan.json

/DataMKG/TEWS/gempadirasakan.json

✅ Обновлён

LHKPN

/portal/user/check_search_announ

reCAPTCHA v3 (Playwright)

🟢 Активен

Модули, которые не работают в течение 60 дней, помечаются как DEGRADED и могут быть архивированы.

Модули на основе браузера

Некоторые порталы требуют настоящий браузер (рендеринг JavaScript, защита от ботов):

Модуль

Браузер

Анти-бот

bpjph

Playwright (Chromium)

Стандартная

ahu

Playwright + Camoufox

Управление ботами (блокировка IP дата-центров)

oss_nib

Playwright (Chromium)

Стандартная

Установка зависимостей браузера:

pip install ".[playwright]"
playwright install chromium

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

API-ключи

Модуль

Требуется ключ

Переменная окружения

Регистрация

BPS

Да

BPS_API_KEY

webapi.bps.go.id/developer/register (бесплатно)

Все остальные

Нет

—

—

Без BPS_API_KEY модуль BPS возвращает конверт ошибки (не падение):

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

Инвентаризация MCP-инструментов

Все 11 модулей предоставляют 40 MCP-инструментов в общей сложности:

Модуль

Инструменты

Кол-во

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


Интеграция с AI-агентами

Этот репозиторий создан с расчётом на AI-агентов как основных потребителей.

Для AI-агентов кодирования

Файл

Назначение

Агент

AGENTS.md

Архитектура, паттерны, критические правила, подводные камни

Все агенты кодирования

CLAUDE.md

Команды, правила «делать/не делать», руководство по стилю

Claude Code

.cursorrules

Правила проекта для Cursor

Cursor

.github/copilot-instructions.md

Инструкции для Copilot

GitHub Copilot

CONTRIBUTING.md

Контракт модуля + чек-лист PR

Все

SKILL.md

Обнаружение навыков (формат AgentSkills)

Агенты с поддержкой навыков

PROMPTS.md

Примеры промптов + рецепты интерактивных артефактов

Все AI-агенты

Подключение MCP-инструментов (выберите один вариант)

Вариант A — Самостоятельно размещённый удалённый сервер (разверните свой):

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"
    }
  }
}

Примечание: Общего размещённого сервера не существует. Каждый пользователь разворачивает собственный экземпляр для управления настройками прокси, лимитами скорости и API-ключами.

Вариант B — Локальная установка через pip:

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

Вариант C — Клонирование репозитория (автообнаружение):

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

Все три варианта дают вам одни и те же 40 инструментов. Затем спросите:

«Проверь, активна ли ещё регистрация BPOM MD 123456789» «Найди компании с названием "Maju Bersama" в реестре AHU» «Какое было последнее землетрясение в Индонезии?»

Дополнительные примеры промптов и рецепты интерактивных артефактов см. в PROMPTS.md.

REST API

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

Примеры промптов

После подключения MCP-инструментов попробуйте эти запросы со своим AI-агентом:

Безопасность пищевых продуктов «Проверь, активен ли регистрационный номер BPOM MD 123456789» «Найди все продукты с парацетамолом, зарегистрированные в BPOM»

Проверка халяльности «Сертифицирован ли продукт XYZ как халяльный? Сверь с регистрацией BPOM» «Найди все халяльные сертификаты, выданные PT Indofood»

Проверка компании «Найди PT Maju Bersama в реестре компаний AHU и проверь, кто директора» «Есть ли у этой компании лицензия OJK? Проверь и реестр лицензий, и список waspada (предупреждений)»

Государственные финансы «Найди декларации о доходах LHKPN для чиновников в Джакарте» «Найди тендеры на строительство дорог на LPSE»

Катастрофы и погода «Какое было последнее землетрясение в Индонезии?» «Получи прогноз погоды для DKI Jakarta от BMKG»

Статистика «Найди наборы данных BPS об уровне бедности по провинциям» «Получи показатель инфляции за последние 5 лет»

Многоисточниковые запросы «Я хочу проверить пищевую компанию: проверь AHU на регистрацию, OJK на финансовую лицензию, BPOM на регистрацию продуктов и BPJPH на халяльные сертификаты» «Сравни декларации LHKPN этих двух чиновников за последние 3 отчётных периода»

Проектные решения для AI-агентов

  1. Единый конверт ответа — каждый инструмент возвращает CivicStackResponse с одинаковыми полями. Агентам не нужна логика разбора для конкретных модулей.

  2. Конверты ошибок, а не исключения — агенты получают структурированную информацию об ошибках, которую можно анализировать, а не трассировки стека.

  3. Самодокументируемые инструменты — описания MCP-инструментов включают типы параметров, ожидаемые значения и формат ответа.

  4. Детерминированные имена — паттерн check_<module>, search_<module>, get_<module>_status во всех модулях.


Безопасность

Функция

Конфигурация

По умолчанию

Аутентификация по API-ключу

Переменная окружения CIVIC_API_KEY

Отключена (открытый доступ)

Ограничение скорости

Переменная окружения CIVIC_RATE_LIMIT

60 запросов/мин на IP

Белый список прокси

Переменная окружения CIVIC_ALLOWED_PROXIES

Любой не частный IP

Защита от SSRF

Встроенная

Блокирует RFC 1918 + localhost

Пользователь контейнера

Dockerfile

Не 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

Разработка

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

Тесты

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

Участие в разработке

См. CONTRIBUTING.md. Каждый PR модуля должен включать:

  • fetch() и search(), возвращающие CivicStackResponse

  • Роутер FastAPI + сервер FastMCP

  • 3+ VCR-фикстуры для тестов

  • README модуля

Модуль, который не работает в течение 60 дней, помечается как DEGRADED и архивируется.


Используется в

  • halalkah.id — Проверка халяльности продуктов (9,57 млн продуктов)

  • legalkah.id — Проверка легальности финансовых учреждений

  • datarakyat.id — Целевая страница и документация

Примеры архитектур

Простая: Проверка халяльности продукта

Одностраничное приложение, которое проверяет, сертифицирован ли продукт как халяльный. Один модуль, прокси не нужен для пользователей в Индонезии.

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}

Средняя: API комплексной проверки из нескольких источников

Инструмент комплаенса, который перекрёстно проверяет компанию по нескольким государственным базам данных. Работает за прокси для зарубежного развёртывания.

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),
    }

Продвинутая: AI-агент с MCP-инструментами

AI-ассистент, который отвечает на вопросы на естественном языке об индонезийских гражданских данных с помощью MCP-инструментов. Агент рассуждает о том, какие порталы запрашивать.

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

Связанные проекты

  • indonesia-civic-signal-monitor — Движок обнаружения аномалий, построенный на этом SDK, отслеживает 11 государственных источников данных на предмет значимых изменений

  • indonesia-gov-apis — Справочная документация по 50+ индонезийским государственным API

  • datarakyat.id — Домашняя страница проекта с полной документацией по модулям

Лицензия

MIT — см. 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