Skip to main content
Glama
AnderMC66

sunat-datos-abiertos-mcp

sunat-datos-abiertos-mcp

Servidor MCP (Model Context Protocol) + CLI para consultar los datasets de SUNAT publicados en la Plataforma Nacional de Datos Abiertos del Perú: padrón RUC con clasificación CIIU, padrón de emisores de comprobantes electrónicos, agentes de retención/percepción de IGV, etc.

La idea central: los archivos son enormes (el padrón RUC son ~230 MB comprimidos y ~3 GB de CSV con 12.5 millones de filas) y descargarlos para responder una pregunta no tiene sentido. Este servidor los lee en streaming y filtra, agrupa y perfila sobre la marcha, sin escribir nada en disco.

Requisitos

  • Node.js 18+ (probado en Node 24)

Related MCP server: datagovma-mcp

Instalación

npm install
npm run build

Tools disponibles (MCP)

Tool

Descripción

sunat_listar_datasets

Lista los datasets de SUNAT (slug, título, nº de recursos). Cacheado.

sunat_buscar_recursos

Busca archivos por palabras clave en todo el catálogo, sin tildes ni mayúsculas. La vía más rápida al id de un recurso.

sunat_obtener_dataset

Detalle y lista completa de recursos de un dataset. Cacheado.

sunat_recurso_mas_reciente

El recurso del periodo más reciente de un dataset (p. ej. el último padrón mensual).

sunat_obtener_recurso

Metadata y URL real de descarga de un recurso.

Datos

Tool

Descripción

sunat_perfilar_recurso

Columnas reales del archivo con tipo inferido, vacíos, valores distintos y ejemplos. Úsalo antes de filtrar.

sunat_previsualizar_recurso

Primeras filas ya parseadas como objetos, con delimitador y encoding detectados.

sunat_buscar_en_recurso

Filtra filas dentro del archivo en streaming, sin descargarlo. Filtros por columna (igual, contiene, empieza, termina, regex, mayor, menor) y/o texto libre.

sunat_contar_por_columna

GROUP BY en streaming: cuenta filas por valor de una columna, con filtros previos.

sunat_descargar_recurso

Descarga el archivo completo a disco (último recurso, rara vez necesario).

sunat_cache

Estado o limpieza de la caché local del catálogo.

Flujo típico: sunat_buscar_recursossunat_perfilar_recursosunat_buscar_en_recurso o sunat_contar_por_columna.

Particularidades del portal (verificadas contra la API real)

Este portal es CKAN, pero con varias trampas. Todas están resueltas en el código:

  • package_search y organization_list devuelven 404. Por eso se navega el grupo de SUNAT con group_package_show y la búsqueda por palabras clave se hace en cliente.

  • Ante un error el portal responde HTML, no JSON. Se valida el content-type antes de parsear, así el fallo dice qué pasó en vez de reventar con un error de sintaxis JSON.

  • package_show y group_package_show envuelven el resultado en un array de un solo elemento, a diferencia de package_list/resource_show. Se desenvuelve solo si hace falta.

  • El WAF responde 418 a ciertos User-Agent (curl/*, o cualquiera con una URL entre paréntesis). El User-Agent se mantiene como un token simple producto/versión a propósito.

  • El campo format miente: los padrones RUC se declaran csv pero se sirven como .zip. El tipo se decide por los bytes reales (firma PK), no por la metadata; cada recurso reporta además un formato_real.

  • El delimitador varía entre archivos: PadronRUC_202209.csv usa | y PadronRUC_202412.csv usa ,. Se detecta por archivo, junto con ; y tabulador.

  • El encoding varía: el padrón RUC es latin1 y el de agentes de retención es utf-8. Se detecta con los primeros bytes, así que HUÁNUCO y ENSEÑANZA no salen mojibake.

Uso con Claude Desktop / Claude Code

{
  "mcpServers": {
    "sunat-datos-abiertos": {
      "command": "node",
      "args": ["C:\\source\\mcp-sunat\\build\\index.js"]
    }
  }
}

Uso como CLI

npm run build
npm link        # instala el comando `sunat` globalmente
sunat list                                   # datasets de SUNAT
sunat search padron ruc 2024-12              # busca recursos por palabras clave
sunat show <dataset>                         # detalle y recursos de un dataset
sunat latest <dataset>                       # el recurso más reciente
sunat resource <resource_id>                 # metadata y URL de un recurso

sunat schema <resource_id>                   # columnas reales, tipos, ejemplos
sunat preview <resource_id> -n 50            # primeras filas parseadas
sunat find <resource_id> -w RUC=20100070970  # busca filas sin descargar el archivo
sunat count <resource_id> Departamento -w Estado=ACTIVO   # group by en streaming

sunat download <resource_id> -o ./padron.zip # descarga completa
sunat cache status | clear | path            # caché local

Filtros de find/count (-w, repetible):

Forma

Significado

columna=valor

igualdad

columna~valor

contiene

columna:operador:valor

igual, contiene, empieza, termina, regex, mayor, menor

Las comparaciones ignoran tildes y mayúsculas (huanuco encuentra HUÁNUCO).

Flags globales: --json (salida cruda para pipes) y --no-color.

Ejemplo real

$ sunat find a6892afd-f622-4564-8acd-44644912fcb4 -w RUC=20100070970 \
      -c RUC,Estado,Condicion,Tipo,Departamento
┌─────────────┬────────┬───────────┬──────────────────┬──────────────┐
│ RUC         │ Estado │ Condicion │ Tipo             │ Departamento │
├─────────────┼────────┼───────────┼──────────────────┼──────────────┤
│ 20100070970 │ ACTIVO │ HABIDO    │ SOCIEDAD ANONIMA │ LIMA         │
└─────────────┴────────┴───────────┴──────────────────┴──────────────┘
1 coincidencia(s) | 12,515,483 filas escaneadas | 3.1 GB leidos | escaneo completo: si

12.5 millones de filas recorridas, cero bytes escritos en disco. El tiempo lo pone la red (~3 min con esa conexión), no el parseo.

Configuración por entorno

Variable

Efecto

SUNAT_CACHE_DIR

Carpeta de la caché del catálogo (default ~/.sunat-mcp-cache).

SUNAT_CACHE_TTL_MS

TTL de la caché en ms (default 6 h; 0 la desactiva).

SUNAT_MAX_SCAN_BYTES

Tope de bytes descomprimidos por escaneo (default 6 GB).

SUNAT_DOWNLOAD_DIR

Carpeta destino por defecto de sunat_descargar_recurso.

Solo se cachea la metadata del catálogo (cambia poco). El contenido de los archivos nunca se cachea, y un resultado que no se pudo interpretar tampoco: así un error puntual del portal no envenena la caché.

Límites conocidos

  • Un campo entrecomillado que contenga saltos de línea no está soportado (los archivos de este portal no los usan; soportarlo obligaría a bufferear filas completas).

  • sunat_contar_por_columna rechaza columnas con más de 50 000 valores distintos: agrupar por RUC no tiene sentido, para eso está sunat_buscar_en_recurso.

  • escaneo_completo: false significa que el conteo es parcial (se cortó por límite de filas, bytes o coincidencias). Siempre revisa ese campo antes de afirmar un total.

Desarrollo

npm run build   # compila TypeScript a build/
npm start       # corre el servidor MCP compilado
node build/cli.js list   # corre la CLI sin npm link

Licencia

MIT. Ver LICENSE.

Available Tools

4 tools
sunat_listar_datasetsListar datasets de SUNATA

Lista los datasets (padrones de contribuyentes, comprobantes electronicos, etc.) publicados por SUNAT en la Plataforma Nacional de Datos Abiertos del Peru (datosabiertos.gob.pe). Usa el campo 'dataset' de cada resultado con 'sunat_obtener_dataset' para ver sus recursos.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the burden. It states the tool lists datasets but does not disclose behavioral traits like rate limits, pagination (since no params, likely all results at once), or the exact structure of each result beyond the 'dataset' field.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no wasted words. The first sentence states the purpose, and the second provides usage guidance. Front-loaded and efficient.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no parameters and no output schema, the description is fairly complete: it specifies the data source, gives examples, and links to the next tool. However, it could describe the output format more fully, though the sibling tool reference compensates.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There are no parameters, so schema coverage is 100%. The description adds value by explaining how to use the output (the 'dataset' field) with another tool, which is beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool lists SUNAT datasets, provides examples (padrones, comprobantes), and specifies the source platform (datosabiertos.gob.pe). It distinguishes from sibling tools by indicating how to use the output with sunat_obtener_dataset.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly tells when to use the tool (to list datasets) and directs the agent to use the 'dataset' field with sunat_obtener_dataset for resources. However, it does not explicitly exclude other use cases or compare with siblings beyond the next step.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

sunat_obtener_datasetObtener detalle de un dataset de SUNATA

Devuelve la descripcion y la lista de recursos (archivos) de un dataset de SUNAT identificado por su slug (campo 'dataset' de 'sunat_listar_datasets'). Cada recurso trae un 'id' que se usa con 'sunat_obtener_recurso' o 'sunat_previsualizar_recurso' para acceder al archivo real.

ParametersJSON Schema
NameRequiredDescriptionDefault
datasetYesSlug del dataset, obtenido de sunat_listar_datasets

TDQS

A4.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries full burden. It accurately describes the return structure (description and list of resources) but does not mention any behavioral traits such as read-only nature, authentication requirements, or rate limits.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with the main purpose, no unnecessary words. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity (1 parameter, no output schema), the description adequately explains the return value and how the results link to sibling tools. Lack of annotations is not compensated, but the description is sufficient for correct usage.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the description adds value by explaining where to obtain the slug ('obtenido de sunat_listar_datasets'), which complements the schema's description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool returns the description and list of resources for a SUNAT dataset identified by slug. It also explicitly differentiates from sibling tools by mentioning how resource IDs are used with 'sunat_obtener_recurso' or 'sunat_previsualizar_recurso'.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage context: the slug comes from 'sunat_listar_datasets' and the returned resource IDs are used with other tools. However, it does not explicitly state when to use this tool vs alternatives nor provide any exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

sunat_obtener_recursoObtener metadata y URL de descarga real de un recursoA

Dado el 'id' de un recurso (de 'sunat_obtener_dataset'), devuelve su metadata completa incluyendo la URL directa de descarga del archivo. Nota: en este portal el campo 'formato' no siempre es confiable; muchos archivos declarados como csv en realidad son .zip que contienen el csv adentro.

ParametersJSON Schema
NameRequiredDescriptionDefault
resource_idYesId del recurso, obtenido de sunat_obtener_dataset

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description bears full responsibility. It adds important behavioral context by noting that the 'formato' field is unreliable and that CSV files may actually be ZIP archives. It could mention authentication or rate limits, but the added detail is valuable.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, no filler, efficiently conveys all necessary information. Every word has purpose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Without an output schema, the description summarizes the return value (metadata and download URL). It could list example fields, but for a single-parameter retrieval tool, the given detail is sufficient.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the description does not add new information beyond what the parameter description already says ('Id del recurso, obtenido de sunat_obtener_dataset'). Baseline score applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: given a resource id, it returns full metadata and the download URL. It explicitly references its predecessor (sunat_obtener_dataset), distinguishing it from siblings that handle datasets or previews.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description indicates that the input comes from sunat_obtener_dataset, providing clear context. It includes a warning about the unreliable 'formato' field, but does not explicitly state when not to use or list alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

sunat_previsualizar_recursoPrevisualizar filas de un recurso de SUNATA

Descarga solo el inicio de un recurso de SUNAT (csv suelto o csv dentro de un zip) y devuelve el encabezado mas las primeras filas, sin bajar el archivo completo (algunos pesan cientos de MB). Usa el 'id' de un recurso obtenido de 'sunat_obtener_dataset'.

ParametersJSON Schema
NameRequiredDescriptionDefault
filasNoCantidad de filas de datos a devolver (max 200)
resource_idYesId del recurso a previsualizar

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, so description carries full burden. It discloses that it only downloads the beginning, handles CSV or CSV-in-zip, and returns header plus first rows. This is transparent about read-only behavior and file handling.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two concise sentences with all essential information front-loaded. No wasted words. Every sentence adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, description could specify output format more explicitly, but it clearly states returns header and first rows. It adequately covers the tool's behavior for a preview operation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with descriptions on both parameters. The description reinforces the source of 'resource_id' but adds no new details beyond schema. Baseline 3 is appropriate since schema already documents parameters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states it previews rows of a SUNAT resource, downloading only the beginning. It specifies the verb 'previsualizar' and distinguishes from siblings by noting it avoids full download. This is a specific verb+resource combination.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Description explicitly instructs to use the 'id' from 'sunat_obtener_dataset', providing context for when to use this tool. While it doesn't explicitly state when not to use it or name alternatives, the instruction to use a specific sibling's output is clear guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 4 tool updatesv1.0.0
    • First observedsunat_listar_datasets
    • First observedsunat_obtener_dataset
    • First observedsunat_obtener_recurso
    • First observedsunat_previsualizar_recurso

TDQS

A4.3/5.0

Scored across 4 tools

Disambiguation5/5

Each tool has a distinct purpose: listing datasets, getting dataset details, retrieving resource metadata, and previewing a resource. There is no overlap or ambiguity between them.

Naming Consistency5/5

All tools follow the pattern `sunat_<verb_in_spanish>_<noun>`, using consistent snake_case and infinitive verbs (listar, obtener, previsualizar).

Tool Count4/5

With 4 tools, the server is focused and not excessive. It covers the core workflow of discovering and accessing open data, though a few more tools (e.g., search) could enhance completeness.

Completeness4/5

The tool set covers the full pipeline from listing datasets to previewing resource content. A minor gap is the lack of a tool to directly download a resource, but the URL provided via `sunat_obtener_recurso` addresses that.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    MCP server for Peruvian public-data lookups including SUNAT RUC registrations, BCRP exchange rates, and SEACE tenders. Provides official open-data access through tools for Claude, Cursor, and other MCP clients.
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    MCP server for the Moroccan Open Data portal (data.gov.ma) enabling search and retrieval of datasets, resources, organizations, and groups via CKAN API.
    1
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    MCP server for Peruvian government data, enabling search and anomaly detection in public procurement (OSCE) and legislative tracking (Congress), plus semantic search over both domains.
    -
  • A
    license
    A
    quality
    B
    maintenance
    Local MCP server for validating and querying Peruvian RUCs using SUNAT's official reduced registry, stored locally to keep data private.
    4
    MIT