mcp-egrul

Servidor MCP para verificar contrapartes a través de egrul.nalog.ru: obtención de extracto EGRUL/EGRIP por INN/OGRN.

Documentación

mcp-egrul

Servidor MCP de ЕГРЮЛ y ЕГРИП: datos de empresas e IP rusas según datos abiertos del servicio fiscal. Puedes instalarlo localmente o conectarlo a Cursor, Claude y cualquier cliente MCP.

Búsqueda en el registro de empresas ruso para agentes de IA.

Glama

mcp-egrul MCP server

Estado: v0.1.2 — la versión open (self-host mediante SQLite) está completamente lista + la parte cliente de hosted Pro (cliente HTTP HostedClient para api.atomno-mcp.ru). Publicado en PyPI, indexado en Glama y Smithery. La propia infraestructura hosted Pro está en desarrollo activo. Cobertura 100.00% (345 pruebas, ruff clean, fastmcp 3.2.4, aplicado mediante --cov-fail-under=100).

Proyecto complementario: mcp-fns-check (capa de verificación de riesgos sobre ЕГРЮЛ).


Qué es

Siete herramientas MCP visibles para el asistente de IA (Cursor, Claude Desktop, Cline, cualquier cliente MCP):

HerramientaDescripciónArgumentos
search_by_innBúsqueda por INN (10 dígitos — persona jurídica, 12 — IP)inn: str
search_by_ogrnBúsqueda por OGRN (13) u OGRNIP (15)ogrn: str
search_by_nameBúsqueda difusa por nombre (FTS5)query: str, limit?: int, only_active?: bool
get_full_cardFicha completa con todas las seccionesinn?: str, ogrn?: str
get_foundersSolo fundadores con participacionesinn: str
get_directorSolo el director actualinn: str
bulk_cardsVerificación masiva (hasta 100 INN)inns: list[str]

Además, una herramienta de diagnóstico ping para comprobar que el servidor está activo.

La especificación completa de los payloads está en src/mcp_egrul/schemas.py (modelos Pydantic CompanyCard, IECard, SearchResult, BulkResult).


Instalación

Opción 1 — mediante PyPI (recomendada para usuarios)

# Без локального clone — работает «из коробки»
uvx atomno-mcp-egrul

# Или установка глобально
pipx install atomno-mcp-egrul
atomno-mcp-egrul

# Или классический pip в venv
pip install atomno-mcp-egrul
atomno-mcp-egrul

Opción 2 — modo dev (para desarrolladores)

Se requiere Python 3.11+ y uv (sustituto rápido de pip, opcional).

git clone https://github.com/atomno-mcp/mcp-egrul
cd mcp-egrul
uv venv
uv pip install -e ".[dev]"

Alternativamente mediante pip:

python -m venv .venv
.venv/Scripts/activate    # Windows
# source .venv/bin/activate  # Linux/macOS
pip install -e ".[dev]"

Ejecución

atomno-mcp-egrul

El transporte por defecto es stdio (entrada/salida estándar JSON-RPC). Adecuado para conectarse a Cursor / Claude Desktop / Claude Code.

Claude Desktop (claude_desktop_config.json)

{
  "mcpServers": {
    "egrul": {
      "command": "uvx",
      "args": ["atomno-mcp-egrul"]
    }
  }
}

Cursor (.cursor/mcp.json en el proyecto o ~/.cursor/mcp.json globalmente)

{
  "mcpServers": {
    "egrul": {
      "command": "uvx",
      "args": ["atomno-mcp-egrul"]
    }
  }
}

Si no usas uv, reemplaza "command": "uvx", "args": ["atomno-mcp-egrul"] por "command": "atomno-mcp-egrul" (requiere pip install atomno-mcp-egrul o pipx install atomno-mcp-egrul).


Docker (self-host) — inicio rápido

# 1. Скачайте дампы ФНС (acceptance на сайте ФНС — раз в жизни).
#    Источники:
#      ЕГРЮЛ — https://www.nalog.gov.ru/opendata/7707329152-egrul/
#      ЕГРИП — https://www.nalog.gov.ru/opendata/7707329152-egrip/
#    Положите их в структуру:
mkdir -p dumps/egrul/2026-04-24 dumps/egrip/2026-04-24
cp ~/Downloads/EGRUL_*.zip dumps/egrul/2026-04-24/
cp ~/Downloads/EGRIP_*.zip dumps/egrip/2026-04-24/

# 2. Первоначальный полный импорт (однократно, ~30-60 минут):
docker compose --profile import run --rm \
    mcp-egrul-import atomno-mcp-egrul-import --registry egrul --full
docker compose --profile import run --rm \
    mcp-egrul-import atomno-mcp-egrul-import --registry egrip --full

# 3. Запустите сервер + фоновый cron-демон:
docker compose up -d
docker compose logs -f mcp-egrul-scheduler

Aproximadamente 10 minutos después de la importación, todas las herramientas (search_by_inn, search_by_name, etc.) ya responden con datos de la copia local de la ФНС.

Esquema del volumen /data dentro del contenedor:

/data/
├── mcp_egrul_data.sqlite     # SQLite + FTS5
└── dumps/                    # read-only монтируется из ./dumps
    ├── egrul/
    │   └── YYYY-MM-DD/*.zip
    └── egrip/
        └── YYYY-MM-DD/*.zip

El demonio cron (atomno-mcp-egrul-scheduler) descarga automáticamente la exportación más reciente después de que la coloques en dumps/<registry>/<YYYY-MM-DD>/ — a las 03:00 Europe/Moscow. Si no hay nada nuevo, el job finaliza con nothing_to_import y no realiza registros adicionales en import_log.


Importación de dumps de la ФНС (modo manual)

Fuentes:

  • ЕГРЮЛ open-data: https://www.nalog.gov.ru/opendata/7707329152-egrul/
  • ЕГРИП open-data: https://www.nalog.gov.ru/opendata/7707329152-egrip/

Formato: archivos XML diarios en ZIP, ~15 GB por copia completa. Legalmente deben descargarse desde el sitio web de la ФНС después de aceptar la licencia — el servidor no descarga los archivos por sí mismo (estrictamente).

CLI:

# Полный первоначальный импорт (однократно):
atomno-mcp-egrul-import --registry egrul --full
atomno-mcp-egrul-import --registry egrip --full

# Инкремент (cron / ручной): загружается только если появилась более
# свежая YYYY-MM-DD-папка, чем последний успешный `import_log.source_dump_date`.
# Если новее нет — exit-code 5 и сообщение `nothing_to_import`.
atomno-mcp-egrul-import --registry egrul --incremental

# Фоновой cron-демон с ежедневным 03:00 MSK (вызывать вручную редко;
# обычно запускается сервисом mcp-egrul-scheduler в docker-compose).
atomno-mcp-egrul-scheduler --run-now

Códigos de salida atomno-mcp-egrul-import:

CódigoSignificado
0La importación se completó correctamente
2Configuración o argumento CLI no válido
4Error de ingesta (XML dañado, no existe el directorio de dumps, error de BD)
5nothing_to_import — la fecha más reciente ya está en la BD (incremental)

Modo Pro / hosted (proxy hacia api.atomno-mcp.ru)

Cuando el usuario establece ATOMNO_API_KEY, las siete herramientas se redirigen automáticamente al API hosted Pro (SPEC §5.4, §5.4.1). El SQLite local no se usa en este modo — hosted Pro ofrece:

  • Datos actualizados al día de hoy (sin el retraso diario del dump open-data): scraping directo de egrul.nalog.ru + fallback de Dadata en el lado del servidor.
  • Endpoint bulk sin rate-limit (POST /companies/bulk) — una sola solicitud en lugar de N recopilaciones locales.
  • Resumen de ficha con IA, historial de cambios, búsqueda por nombre completo del director (herramientas Pro-only — llegan junto con el servidor hosted en la Fase 2, ver §5.4.1).

Precio: Pro — $10/mes por separado o $15/mes junto con mcp-fns-check (clave bundle). Nivel gratuito: 30 solicitudes/día/IP sin registro (SPEC §1).

Configuración en Cursor (.cursor/mcp.json):

{
  "mcpServers": {
    "egrul": {
      "command": "uvx",
      "args": ["atomno-mcp-egrul"],
      "env": {
        "ATOMNO_API_KEY": "your-pro-key-here"
      }
    }
  }
}

Comportamiento y errores — sin fallback silencioso: si el API hosted no está disponible, el cliente lanza una excepción tipada, en lugar de devolver silenciosamente datos del dump local desactualizado. Correspondencia entre HTTP ↔ código de error MCP — en SPEC §5.4.1:

Respuesta HTTP del API hostedExcepción del clienteerror.code
200
400ValidationErrorinvalid_input
401HostedAuthErrorauth_required
403ProRequiredErrorpro_required
404 (code=not_found)NotFoundErrornot_found
404 (ruta incorrecta)SourceUnavailableErrorsource_unavailable
413BulkTooLargeErrorbulk_too_large
429RateLimitedError (+ Retry-After)rate_limit
5xxSourceUnavailableErrorsource_unavailable
timeout / fallo de DNSSourceUnavailableError (cause=timeout/ConnectError)source_unavailable

La validación de INN/OGRN permanece del lado del cliente (los dígitos de control se verifican antes de la solicitud HTTP — ahorro de round-trip en identificadores inválidos).


Configuración (variables de entorno)

VariableDescripciónPor defecto
MCP_EGRUL_DBRuta al archivo SQLite con la copia de ЕГРЮЛ/ЕГРИП./mcp_egrul_data.sqlite
MCP_EGRUL_USER_AGENTUser-Agent del cliente HTTPmcp-egrul/0.1 (+https://github.com/atomno-mcp/mcp-egrul)
MCP_EGRUL_HTTP_TIMEOUTTimeout HTTP en segundos30
MCP_EGRUL_DUMPS_DIRDirectorio con dumps de la ФНС, estructura <dir>/<registry>/<YYYY-MM-DD>/*.zip./dumps
MCP_EGRUL_LOG_LEVELNivel de loggingINFO
TZZona horaria para el scheduler (cron 03:00)Europe/Moscow
ATOMNO_API_KEY(Pro) clave de suscripción hosted — activa el proxy hacia api.atomno-mcp.runo definida
ATOMNO_API_BASE(Pro) URL base del API hostedhttps://api.atomno-mcp.ru/mcp-egrul/v1

Ejemplo — ver .env.example.


Estructura

apps/mcp-egrul/
├── pyproject.toml
├── LICENSE                             # MIT
├── README.md                           # ЭТОТ ФАЙЛ
├── Dockerfile
├── docker-compose.yml
├── .env.example
├── .gitignore
├── src/mcp_egrul/
│   ├── __init__.py
│   ├── server.py                       # FastMCP entrypoint, регистрация 7 тулзов + ping
│   ├── context.py                      # ServiceContext (DI: SQLiteStore + HTTP-клиент)
│   ├── config.py                       # Чтение env-vars в типизированные поля
│   ├── constants.py                    # Все магические числа и enum'ы
│   ├── validators.py                   # Контрольные цифры ИНН (10/12) и ОГРН (13/15)
│   ├── schemas.py                      # Pydantic-модели CompanyCard/IECard/SearchResult/...
│   ├── errors.py                       # McpEgrulError и подклассы
│   ├── db/
│   │   ├── __init__.py
│   │   └── sqlite.py                   # Async-клиент (aiosqlite), init/query/upsert/search + import_log
│   ├── sources/
│   │   ├── __init__.py
│   │   ├── base.py                     # Абстрактный интерфейс Source
│   │   ├── opendata.py                 # ФНС open-data адаптер (read-local → SQLite upsert)
│   │   ├── opendata_parser.py          # Потоковый lxml.iterparse парсер ЕГРЮЛ/ЕГРИП XML
│   │   └── hosted_adapter.py           # HTTP-клиент hosted Pro API (SPEC §5.4.1)
│   ├── tools/
│   │   ├── __init__.py
│   │   ├── search_by_inn.py
│   │   ├── search_by_ogrn.py
│   │   ├── search_by_name.py
│   │   ├── get_full_card.py
│   │   ├── get_founders.py
│   │   ├── get_director.py
│   │   └── bulk_cards.py
│   └── scripts/
│       ├── __init__.py
│       ├── import_opendata.py          # CLI `atomno-mcp-egrul-import` (ручной / одноразовый)
│       └── scheduler.py                # CLI `atomno-mcp-egrul-scheduler` (apscheduler cron 03:00 MSK)
└── tests/
    ├── __init__.py
    ├── conftest.py
    ├── fixtures/
    │   ├── egrul_sample.xml            # Мини-ЕГРЮЛ (2 валидных + 1 skip на неизвестный статус)
    │   └── egrip_sample.xml            # Мини-ЕГРИП (active + closed)
    ├── test_validators.py
    ├── test_schemas.py
    ├── test_config.py                  # Config.from_env + _parse_float_env (валидация env)
    ├── test_sqlite_store.py
    ├── test_cards.py                   # _cards.py: parse_iso_date/datetime + build_*card
    ├── test_server_ping.py             # FastMCP tool-layer + server.main()
    ├── test_tools.py                   # 7 тулзов: happy-path + validation + not_found
    ├── test_opendata_parser.py         # XML-парсер (zip, xml, skip-на-неизвестный-статус)
    ├── test_opendata_source.py         # OpenDataSource.run_ingest (full/incremental)
    ├── test_integration_import.py      # Полный цикл import → search → get_card
    ├── test_import_cli.py              # CLI `atomno-mcp-egrul-import`
    ├── test_scheduler_cli.py           # CLI `atomno-mcp-egrul-scheduler` + _run_scheduler
    └── test_hosted_adapter.py          # HostedClient + маршрутизация тулзов (respx-моки)

Pruebas

pytest -v --cov=src/mcp_egrul

Cobertura actual: 100.00% (345 tests passed, ruff clean, 1529 sentencias + 382 ramas, 0 fallos). Aplicada mediante la política --cov-fail-under=100 — cualquier regresión romperá el CI. Las pruebas cubren:

  • validadores de INN/OGRN/OGRNIP (dígitos de control);
  • Config.from_env + parser de variables float-env (validación, no fallback silencioso);
  • las 7 herramientas MCP (happy-path + validación + not_found + bulk parcial);
  • store SQLite + FTS5 + import_log;
  • parser XML de ЕГРЮЛ/ЕГРИП (zip, xml, salto de registro con estado desconocido);
  • OpenDataSource.run_ingest (full/incremental/nothing_to_import);
  • ciclo de integración completo import fixture → search → get_card → bulk;
  • ambas CLI (atomno-mcp-egrul-import, atomno-mcp-egrul-scheduler) — registro de cron-jobs, parseo de argumentos, _run_daily_ingest en all-happy/nothing_to_import/McpEgrulError, ciclo completo de _run_scheduler con asyncio.Event simulado;
  • capa de herramientas FastMCP mediante mcp.call_tool() — serialización de errores en dicts estructurados, server.main() con env válido e inválido;
  • HostedClient (proxy del API hosted Pro) — happy-path de los 7 métodos, todos los errores HTTP de SPEC §5.4.1 (401/403/404/413/429/5xx), timeout/ConnectError, JSON/payload inválido del servidor, validación de bulk en el cliente, contexto async with; además, enrutamiento desde las herramientas en modo hosted (cuando se define ATOMNO_API_KEY — la solicitud va a api.atomno-mcp.ru, no a SQLite, validación de INN antes de HTTP);
  • casos límite del parser XML (75 unit-tests separados sobre _parse_company/_parse_ie/_parse_share/_parse_director/_parse_founders/fallbacks de dirección/atributos legacy/longitudes inválidas de INN/OGRN/KPP);
  • helpers privados del store SQLite (_wrap, _prepare_row, _row_to_dict, _normalize_bm25, auto-init mediante _ensure, rechazo de estados finish_import inválidos);
  • idempotencia de reentrada ServiceContext, limpieza atexit, Config.from_env ValidationError → código de salida 2 desde la CLI atomno-mcp-egrul-import.

Las API externas nunca se llaman directamente desde las pruebas — solo mediante respx (mockeo HTTP) y fixtures XML locales (tests/fixtures/).


Seguridad y estatus legal

  • Todas las fuentes son datos públicos de la ФНС (datasets abiertos de ЕГРЮЛ / ЕГРИП), cuya distribución está permitida por la ley federal «Sobre la información…» y las normas específicas de ЕГРЮЛ (ver SPEC §8).
  • Las personas jurídicas no están sujetas a la 152-FZ (Sobre datos personales).
  • Los nombres completos de directores y fundadores personas físicas son publicados por la propia ФНС en el registro abierto — la transmisión de estos datos es legal.
  • Sin operaciones de escritura en ninguna API externa.
  • Secretos — solo mediante variables de entorno; en el repositorio — .env.example sin valores.

Aviso legal

El servicio es un agregador e interfaz conveniente sobre los datos públicos de la ФНС. No está afiliado con la ФНС. Se utiliza bajo tu propio riesgo. La información en las respuestas del servicio no sustituye una evaluación jurídica o financiera completa.


Licencia

MIT. Archivo LICENSE en la raíz de la carpeta.