sunat-mcp

sunat-mcp

Local MCP server for validating and querying Peruvian RUCs using SUNAT's official reduced registry, stored locally to keep data private.

Category
访问服务器

README

sunat-mcp

Servidor MCP para validar y consultar RUCs peruanos contra el Padrón Reducido oficial de SUNAT, indexado localmente.

Los RUCs que consultas no salen de tu máquina.

sunat-mcp resolviendo consultas reales

El GIF no es una recreación: demo/record.py levanta el servidor por stdio con el cliente oficial de MCP, llama a las herramientas y anima las respuestas que realmente devuelve sobre el índice local. Si el índice no existe, aborta en vez de inventar datos.

El problema

Todo estudio contable peruano valida RUCs a diario: verificar que una factura tenga un RUC bien formado, confirmar la razón social de un proveedor, revisar si un contribuyente está activo y habido antes de aceptar un comprobante.

Las soluciones que existen tienen un problema u otro:

  • Consultar la web de SUNAT a mano — lento, imposible de automatizar.
  • Scrapear la web de SUNAT — frágil (se rompe con cada cambio de HTML) y de legalidad discutible.
  • APIs de terceros — requieren llave, tienen límite de consultas y, sobre todo, le envías a un tercero los RUCs de tus clientes. Para un contador con deber de reserva, eso no es un detalle menor.

Este proyecto toma el camino que casi nadie toma: SUNAT publica el padrón completo como datos abiertos. Se descarga una vez, se indexa, y se consulta local.

Cómo funciona

Padrón Reducido oficial (ZIP, ~372 MiB)
        │  scripts/ingest.py — descarga, verifica SHA-256, recorre en streaming
        ▼
data/padron.sqlite3 — índice local, consulta por clave primaria
        │
        ▼
sunat_mcp/server.py — 4 herramientas MCP  →  Claude Code / Claude Desktop

La ingesta nunca carga el archivo completo en memoria: lee el .txt de 1.56 GB línea por línea directamente desde el ZIP.

Herramientas

Herramienta Qué devuelve Requiere índice Red
validar_ruc Estructura, prefijo y dígito verificador (módulo 11 SUNAT) No No
consultar_ruc Razón social, estado, condición de domicilio, ubigeo, dirección No
buscar_razon_social Contribuyentes cuyo nombre coincide No
estado_padron Fuente, SHA-256, fecha de SUNAT, fecha de ingesta, nº de registros No

validar_ruc funciona sin haber construido el índice: es aritmética pura.

Instalación

Requiere Python 3.10+.

pip install mcp-sunat

O sin instalar nada, directo desde PyPI:

uvx mcp-sunat

El paquete se publica como mcp-sunat; el módulo que se importa es sunat_mcp y el repositorio se llama sunat-mcp. Es la misma distinción que entre pillow y PIL.

Para trabajar sobre el código o construir el índice:

git clone https://github.com/r2nochi/sunat-mcp
cd sunat-mcp
python -m venv .venv
.\.venv\Scripts\pip.exe install -e ".[dev,ingest]"

Construir el índice

.\.venv\Scripts\python.exe scripts\ingest.py

Descarga el ZIP oficial, verifica su checksum y construye el índice.

Ten en cuenta: descarga ~372 MiB y el índice resultante ocupa varios GB en disco. Es una operación de una sola vez; para actualizar, vuelve a correrlo.

Para probar sin bajar todo el padrón:

.\.venv\Scripts\python.exe scripts\ingest.py --limite 50000

El índice quedará marcado como muestra parcial y estado_padron lo avisará.

Rendimiento medido

Sobre el padrón completo del 27/07/2026: 18,297,300 contribuyentes, índice de 2.14 GB (Windows 11, SSD, Python 3.14).

Operación Tiempo Plan de SQLite
consultar_ruc (clave primaria) 0.2 ms SEARCH ... USING PRIMARY KEY
buscar_razon_social por prefijo 0.2 ms SEARCH ... USING COVERING INDEX
buscar_razon_social por subcadena ~40 s SCAN (inevitable, es un LIKE '%x%')
Ingesta completa (descarga + índice) ~22 min

Por qué el índice usa COLLATE NOCASE

La primera versión indexaba razon_social con la colación por defecto (BINARY) y buscaba con LIKE 'TEXTO%'. La búsqueda por prefijo tardaba 39,848 ms.

El motivo: el LIKE de SQLite es case-insensitive por defecto, y por eso no puede usar un índice BINARY — degeneraba en un SCAN de los 18.3 millones de filas. Había además un problema de correctitud: el padrón trae algunas razones sociales en minúscula, que una comparación binaria habría perdido en silencio.

La solución fue indexar con COLLATE NOCASE y resolver el prefijo como un rango (>= 'TEXTO' AND < 'TEXTO' + centinela) en lugar de un LIKE:

antes:  SCAN contribuyente USING COVERING INDEX idx_razon_social      39,848 ms
ahora:  SEARCH contribuyente USING COVERING INDEX idx_razon_nocase         0.2 ms

Hay un test que afirma el plan de ejecución, para que la regresión no pueda volver en silencio.

Conectarlo a Claude Code

claude mcp add sunat --scope user -- <ruta>\sunat-mcp\.venv\Scripts\python.exe -m sunat_mcp.server

O en claude_desktop_config.json:

{
  "mcpServers": {
    "sunat": {
      "command": "C:\\ruta\\a\\sunat-mcp\\.venv\\Scripts\\python.exe",
      "args": ["-m", "sunat_mcp.server"]
    }
  }
}

El índice se busca en data/padron.sqlite3. Para moverlo, define SUNAT_MCP_DB.

Fuente de los datos

Padrón Reducido del RUC, publicado por SUNAT como datos abiertos: https://www.sunat.gob.pe/descargaPRR/mrc137_padron_reducido.html

Archivo: padron_reducido_ruc.zippadron_reducido_ruc.txt Formato: 16 columnas separadas por |, codificación latin-1, - como dato ausente.

RUC | NOMBRE O RAZÓN SOCIAL | ESTADO DEL CONTRIBUYENTE | CONDICIÓN DE DOMICILIO |
UBIGEO | TIPO DE VÍA | NOMBRE DE VÍA | CÓDIGO DE ZONA | TIPO DE ZONA | NÚMERO |
INTERIOR | LOTE | DEPARTAMENTO | MANZANA | KILÓMETRO |

estado_padron expone el SHA-256 del ZIP ingerido y la fecha que informó SUNAT, para que puedas saber exactamente qué versión de los datos estás consultando.

Si SUNAT cambia el esquema, la ingesta se detiene con error en vez de escribir datos en columnas equivocadas.

Límites

Léelos antes de confiar en el resultado:

  • El padrón es una foto, no un servicio en vivo. SUNAT lo publica a diario: entre el 27 y el 28 de julio de 2026 el archivo pasó de 389,882,157 a 389,923,097 bytes. Un RUC creado o dado de baja después de tu última ingesta no se refleja. Por eso estado_padron expone el Last-Modified y el sha256 del ZIP concreto que se ingirió: no basta con saber que consultaste "el padrón", hay que saber cuál.
  • validar_ruc solo comprueba aritmética. Un RUC con dígito verificador correcto puede no existir. Son preguntas distintas.
  • El Padrón Reducido no trae todo. No incluye representantes legales, actividad económica CIIU detallada, teléfonos ni la condición de agente de retención.
  • La búsqueda por nombre es textual, no semántica. No corrige errores de tipeo ni entiende sinónimos. La búsqueda por prefijo es instantánea; la búsqueda por subcadena (%TEXTO) recorre los 18.3 millones de registros y puede tardar decenas de segundos. Es un costo que solo se paga si se pide explícitamente.
  • La dirección se reconstruye uniendo las 10 columnas de domicilio del padrón. No se valida contra ningún servicio de direcciones.
  • Esto no es asesoría tributaria. Para decisiones con efecto legal o contable, verifica en el portal oficial de SUNAT.

Tests

.\.venv\Scripts\python.exe -m pytest -q

Las pruebas generan su propio ZIP de padrón sintético con el mismo formato del oficial (16 columnas, |, latin-1, -). No dependen del archivo real de 372 MiB ni contienen datos de ningún contribuyente real, salvo RUCs que aparecen en la cabecera pública del padrón.

Incluyen una prueba de que la ingesta aborta si SUNAT cambia las columnas.

Licencia

MIT. Los datos del Padrón Reducido son de SUNAT y se rigen por sus propios términos.


Hecho por David Nochi — Ingeniero de IA Aplicada, Lima, Perú.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选