-
Notifications
You must be signed in to change notification settings - Fork 1
OpenReyestr Service
The OpenReyestr Service (mcp_openreyestr/) is a specialized Model Context Protocol (MCP) server within the SecondLayer monorepo. It provides access to Ukrainian state registries -- primarily NAIS (National Information Systems of the Ministry of Justice) open data from data.gov.ua, plus additional sources (DPS tax registries, NAZK anti-corruption declarations, Prozorro public procurement, RNBO sanctions, ARMA seized assets, OpenStreetMap street renamings).
The service supports triple transport: MCP stdio for Claude Desktop, HTTP REST API for web integration, and SSE streaming for long-running queries. It handles tens of millions of records imported from government XML/CSV datasets.
data.gov.ua (ZIP) OpenStreetMap / NAZK / Prozorro / ARMA
| |
v v
sync-all-registries.ts dedicated import scripts
| |
+--- download + unzip |
+--- XML: generic-xml-importer.ts |
+--- CSV: csv-importer.ts (parallel workers) |
| |
v v
PostgreSQL (openreyestr DB) <--------------------------+
|
v
OpenReyestrTools (query layer)
|
v
MCPOpenReyestrAPI (tool definitions + routing)
|
+--- MCP stdio (index.ts)
+--- HTTP REST (http-server.ts, port 3005 prod / 3004 local)
+--- SSE streaming (/api/tools/:toolName/stream)
| Component | Technology |
|---|---|
| Runtime | Node.js 20+ (TypeScript 5.3) |
| Database | PostgreSQL 15+ |
| XML parsing | fast-xml-parser (small/medium), SAX streaming (large/huge) |
| CSV parsing | readline + iconv-lite, parallel DB workers |
| HTTP framework | Express 5 |
| Auth | Bearer token (SECONDARY_LAYER_KEYS) + optional Google OAuth + JWT |
| Metrics | Prometheus (prom-client) |
| Rate limiting | express-rate-limit (300 req/min global, per-IP) |
| Environment | HTTP Port | PostgreSQL Port |
|---|---|---|
| Production | 3005 | 5432 (internal) |
| Local (Docker) | 3004 | 5435 (host-mapped) |
The service exposes 27 tools through the MCP protocol. When accessed through the unified gateway, tool names are prefixed with openreyestr_.
| Tool | Description |
|---|---|
search_entities |
Full-text search across legal entities (UO), entrepreneurs (FOP), and public associations (FSU) by name, EDRPOU, record, status |
get_entity_details |
Full entity profile including founders, beneficiaries, signers, branches, assignees, bankruptcy info |
search_beneficiaries |
Search beneficial owners by name across all entity types |
get_by_edrpou |
Direct lookup by 8-digit EDRPOU code |
get_statistics |
Registry-wide counts (total and active) by entity type |
| Tool | Description |
|---|---|
search_notaries |
Unified Register of Notaries -- search by name, region, status |
search_court_experts |
Register of Certified Court Experts -- search by name, region, expertise type |
search_arbitration_managers |
Register of Arbitration Managers (bankruptcy) -- search by name, certificate status |
search_special_forms |
Register of Special Notarial Document Forms -- search by series, number, recipient |
search_forensic_methods |
Register of Forensic Examination Methods -- search by name, expertise type |
search_legal_acts |
Unified State Register of Normative Legal Acts (EDRNPA) -- search by title, type, publisher |
search_administrative_units |
Administrative-Territorial Dictionary (KOATUU) -- search by settlement, region |
search_streets |
Streets Directory -- search by street name, settlement, region, type |
| Tool | Description |
|---|---|
search_debtors |
Unified Register of Debtors -- search by name, EDRPOU, collection category |
search_enforcement_proceedings |
Automated Enforcement Proceedings System -- search by debtor, creditor, status |
search_bankruptcy_cases |
Register of Bankruptcy Cases -- search by debtor, case number, status |
search_termination_started |
Entities with termination in progress -- search by record, signer, reason |
| Tool | Description |
|---|---|
search_vat_payers |
VAT Payers Registry -- search by name or VAT code |
search_single_tax_payers |
Single Tax Payers Registry -- search by name, TIN, tax group |
search_tax_debt |
Tax Debt Registry -- search by name or TIN; shows debt, penalties, fines |
search_esv_debt |
ESV (Social Contribution) Debt Registry -- search by name or TIN |
| Tool | Description |
|---|---|
search_nazk_declarations |
NAZK Anti-Corruption Declarations (322K records) -- search by declarant, workplace, year, income |
search_arma_seized_assets |
ARMA Registry of Seized Assets in criminal proceedings -- search by owner, case, asset type |
search_prozorro |
Prozorro Public Procurement Tenders (662K records) -- search by title, buyer EDRPOU, CPV code |
search_rnbo_sanctions |
RNBO Sanctions Lists (21K records) -- search by name, aliases, country, identifier |
| Tool | Description |
|---|---|
search_street_renamings |
Street Renaming History from OpenStreetMap (64K streets) -- search by current or old name |
search_exchange_data |
Government agency data exchanges (23.2M records) -- search by entity record, type |
14 migrations define the schema. Key tables:
-
legal_entities-- UO (legal entities): record, edrpou, name, opf, stan, authorized_capital, etc. -
individual_entrepreneurs-- FOP: record, name, stan, farmer flag -
public_associations-- FSU: record, edrpou, name, type_subject, type_branch
-
founders-- company founders (linked via entity_type + entity_record) -
beneficiaries-- beneficial owners -
signers-- authorized signatories / directors -
members-- members of governing bodies (UO only) -
branches-- subsidiaries and representative offices -
predecessors/assignees-- legal succession chain -
executive_power-- executive branch entity link -
termination_started-- entities in termination process -
bankruptcy_info-- bankruptcy/readjustment details -
exchange_data-- government agency data exchanges (23M+ records)
-
notaries-- 7K+ records, unique on certificate_number -
court_experts-- unique on expert_id -
arbitration_managers-- unique on registration_number -
special_forms-- unique on (series, form_number) -
forensic_methods-- unique on registration_code -
bankruptcy_cases-- unique on registration_number -
legal_acts-- EDRNPA acts, unique on act_id -
administrative_units-- KOATUU, unique on md5 hash of composite key -
streets-- unique on (settlement_koatuu, street_name, street_type) -
enforcement_proceedings-- unique on proceeding_number -
debtors-- unique on (proceeding_number, debtor_name, debtor_edrpou)
-
rnbo_sanctions-- RNBO sanctions list (21K), unique on entity_id -
prozorro_tenders-- ProZorro procurement (662K), unique on tender_id -
vat_payers-- VAT registry, unique on vat_code -
single_tax_payers-- single tax, unique on tin -
tax_debt-- tax debt records -
esv_debt-- ESV debt records -
arma_assets-- ARMA seized assets, unique on content_hash -
nazk_declarations-- NAZK declarations (322K), unique on declaration_id -
street_renamings-- OSM street renamings (64K), unique on osm_id
-
cost_tracking-- per-request API cost tracking -
registry_metadata-- last sync dates per registry -
import_log-- import history (status, records imported/failed, timestamps)
All 12 NAIS registries are defined in src/config/registries.ts with:
- Download URL, ZIP/inner file names
- Format (xml or csv), encoding (windows-1251 or utf-8)
- Table name, unique key, record path
- Field mapping (XML/CSV field to DB column, with optional transform functions)
- Update frequency (daily or weekly)
- Size category: small, medium, large, huge (determines parser strategy)
| Command | Script | Description |
|---|---|---|
npm run sync:registries |
sync-all-registries.ts | Sync all 12 NAIS registries (download + import) |
npm run sync:registry --only=X |
sync-all-registries.ts | Sync specific registry(ies) |
npm run sync:weekly |
sync-all-registries.ts | Only registries due for weekly update |
npm run sync:edrpou |
sync-edrpou.ts | Sync EDRPOU (legal entities) from NAIS XML |
npm run import:entities |
import-legal-entities.ts | Import legal entities from local XML |
npm run import:debtors |
import-debtors.ts | Import debtors from local CSV |
npm run import:nais |
download-nais-registries.ts | Download all NAIS ZIP files |
npm run import:street-renamings |
import-street-renamings.ts | Import OSM street renaming data |
Additional import scripts (not exposed as npm scripts but available):
-
import-fop.ts/import-fop-parallel.ts-- FOP import (single/parallel) -
import-uo.ts/import-uo-parallel.ts-- UO import (single/parallel) -
import-fsu.ts-- FSU (public associations) import -
import-arma.ts-- ARMA seized assets import -
import-nazk-declarations.ts-- NAZK declarations import -
import-prozorro.ts-- Prozorro tenders import -
import-from-xml.ts-- Generic XML import helper -
import-all.ts/import-all-streaming.ts-- Bulk import (all entity types)
# Sync all registries
node dist/scripts/sync-all-registries.js
# Sync specific registries
node dist/scripts/sync-all-registries.js --only=notaries,debtors
# Only registries due for weekly update
node dist/scripts/sync-all-registries.js --weekly
# Dry run (show what would sync)
node dist/scripts/sync-all-registries.js --dry-run
# Keep downloaded files after import
node dist/scripts/sync-all-registries.js --keep-files| Size Category | Parser | Strategy | Examples |
|---|---|---|---|
| small | fast-xml-parser (DOM) | Upsert with ON CONFLICT | notaries, court_experts, forensic_methods |
| medium | fast-xml-parser (DOM) | Upsert with ON CONFLICT | bankruptcy_cases, legal_acts |
| large | SAX streaming | Pipelined multi-row INSERTs | special_forms, administrative_units, streets |
| huge | CSV readline + parallel workers | TRUNCATE + bulk INSERT (no ON CONFLICT), drop/recreate indexes | enforcement_proceedings (~30M), debtors (~10M) |
| Endpoint | Auth | Description |
|---|---|---|
GET /health |
No | Full health check with dependency status, uptime, memory |
GET /health/live |
No | Liveness probe (always 200) |
GET /health/ready |
No | Readiness probe (checks DB connectivity + latency) |
GET /metrics |
No | Prometheus metrics (internal network) |
GET /api/stats |
No | Detailed registry statistics: row counts, sources, update times |
| Endpoint | Auth | Description |
|---|---|---|
GET /api/tools |
Bearer | List all available tools with schemas |
POST /api/tools/:toolName |
Bearer | Execute a tool (JSON response or SSE if Accept header set) |
POST /api/tools/:toolName/stream |
Bearer | Execute with SSE streaming |
| Endpoint | Auth | Description |
|---|---|---|
POST /api/admin/sync-registry |
Bearer | Trigger sync for a specific registry (async, returns 202) |
| Variable | Default | Description |
|---|---|---|
DATABASE_URL |
-- | Full PostgreSQL connection string |
POSTGRES_HOST |
localhost | PostgreSQL host |
POSTGRES_PORT |
5435 | PostgreSQL port (host-mapped, container uses 5432) |
POSTGRES_USER |
openreyestr | PostgreSQL user |
POSTGRES_PASSWORD |
-- | PostgreSQL password |
POSTGRES_DB |
openreyestr | Database name |
HTTP_PORT |
3004 | HTTP server port (3005 in prod) |
HTTP_HOST |
0.0.0.0 | HTTP bind address |
SECONDARY_LAYER_KEYS |
-- | API keys for Bearer auth (comma-separated) |
OPENREYESTR_API_KEYS |
-- | Alias for API keys |
JWT_SECRET |
-- | JWT signing secret |
ALLOWED_ORIGINS |
legal.org.ua,stage.legal.org.ua | CORS allowed origins |
NAIS_DATA_DIR |
/tmp/nais-sync | Directory for downloaded registry files |
CSV_IMPORT_WORKERS |
10 | Parallel DB workers for CSV imports |
OPENAI_API_KEY |
-- | OpenAI key (for AI-powered features) |
LOG_LEVEL |
debug | Winston log level |
Built with deployment/Dockerfile.mono-openreyestr. Services in docker-compose:
-
postgres-openreyestr-{env}-- PostgreSQL database -
migrate-openreyestr-{env}-- Runs migrations on startup -
app-openreyestr-{env}-- HTTP server (the main service)
cd mcp_openreyestr
# Install dependencies
npm install
# Setup database (create + migrate)
npm run db:setup
# Run in development (HTTP mode)
npm run dev:http
# Run in MCP stdio mode
npm run dev
# Build
npm run build
# Run tests
npm test
# Lint
npm run lint
# Production start
npm run build && npm run start:http| Service | File | Responsibility |
|---|---|---|
OpenReyestrTools |
api/openreyestr-tools.ts | Query execution layer (all 27 search methods) |
MCPOpenReyestrAPI |
api/mcp-openreyestr-api.ts | MCP tool definitions, routing, response formatting |
Database |
database/database.ts | PostgreSQL pool management |
CostTracker |
services/cost-tracker.ts | Per-request cost estimation and tracking |
MetricsService |
services/metrics-service.ts | Prometheus metrics (HTTP duration, PG pool) |
GenericXmlImporter |
services/generic-xml-importer.ts | Config-driven XML parser (DOM + SAX streaming) |
CsvImporter |
services/csv-importer.ts | Parallel CSV import with readline + workers |
StreamingXmlParser |
services/streaming-xml-parser.ts | SAX-based streaming for large XML files |
DownloadService |
services/download-service.ts | HTTP download with redirects and retries |
EntityValidator |
services/entity-validator.ts | Entity data validation |
ImportProgress |
services/import-progress.ts | Import progress tracking and logging |
| Registry | Source | Format | Update Frequency | Approximate Size |
|---|---|---|---|---|
| Legal Entities (UO) | NAIS EDR | XML (win-1251) | Daily | ~2M records |
| Entrepreneurs (FOP) | NAIS EDR | XML (win-1251) | Daily | ~3M records |
| Public Associations (FSU) | NAIS EDR | XML (win-1251) | Daily | ~300K records |
| Notaries | NAIS | XML (win-1251) | Weekly | ~7K records |
| Court Experts | NAIS | XML (win-1251) | Weekly | ~15K records |
| Arbitration Managers | NAIS | XML (win-1251) | Daily | ~2K records |
| Special Forms | NAIS | XML (win-1251) | Weekly | Large |
| Forensic Methods | NAIS | XML (win-1251) | Weekly | ~1K records |
| Bankruptcy Cases | NAIS | XML (win-1251) | Daily | Medium |
| Legal Acts (EDRNPA) | NAIS | XML (utf-8) | Weekly | Medium |
| Administrative Units | NAIS | XML (win-1251) | Weekly | Large |
| Streets | NAIS | XML (win-1251) | Weekly | Large |
| Enforcement Proceedings | NAIS | CSV (win-1251) | Daily | ~30M records |
| Debtors | NAIS | CSV (win-1251) | Daily | ~10M records |
| RNBO Sanctions | OpenSanctions (ua_nsdc) | JSON/API | Periodic | ~21K records |
| Prozorro Tenders | ProZorro API | JSON/API | Periodic | ~662K records |
| VAT Payers | DPS (data.gov.ua) | CSV | Snapshot (23.02.2022) | Large |
| Single Tax Payers | DPS (data.gov.ua) | CSV | Snapshot | Large |
| Tax Debt | DPS (data.gov.ua) | CSV | Periodic | Large |
| ESV Debt | DPS (data.gov.ua) | CSV | Periodic | Medium |
| NAZK Declarations | NAZK API | JSON/API | Periodic | ~322K records |
| ARMA Seized Assets | ARMA open data | JSON/API | Periodic | Medium |
| Street Renamings | OpenStreetMap (Overpass) | JSON | Periodic | ~64K records |
When ENABLE_UNIFIED_GATEWAY=true is set on mcp_backend, the OpenReyestr tools are available through the unified endpoint at https://legal.org.ua/api/tools/openreyestr_<tool_name>. The gateway proxies requests to the OpenReyestr service internally.
Every tool call is tracked with:
- Request ID, tool name, client key
- Pre-execution cost estimate
- Post-execution actual cost and duration
- Status (completed/failed) with error messages
Data stored in cost_tracking table for billing and monitoring.