sunat-datos-abiertos-mcp
Sunat-datos-abiertos-mcp is a Model Context Protocol server and CLI that lets you query SUNAT's open data (Peruvian tax agency) datasets (RUC registry, electronic invoices, etc.) by streaming through large files without downloading them, offering search, filtering, aggregation, profiling, and preview capabilities.
List SUNAT datasets and their resources.
Search for resources across the catalog by keywords.
Get details and the latest resource of a dataset.
Preview a resource's first rows with detected delimiters and encodings.
Profile a resource: infer column types, emptiness, distinct values, and examples.
Filter rows in a resource using equality, contains, regex, numeric comparisons, etc., without downloading the full file.
Count rows grouped by a column (with filters), with a limit on distinct values.
Download a resource to disk if needed.
Manage the local catalog cache (status, clear, path).
Operates in streaming fashion, memory-efficient, handling portal quirks (HTML errors, misleading formats, variable delimiters/encodings).
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@sunat-datos-abiertos-mcplista los datasets de SUNAT disponibles"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
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 buildTools disponibles (MCP)
Catálogo
Tool | Descripción |
| Lista los datasets de SUNAT (slug, título, nº de recursos). Cacheado. |
| Busca archivos por palabras clave en todo el catálogo, sin tildes ni mayúsculas. La vía más rápida al |
| Detalle y lista completa de recursos de un dataset. Cacheado. |
| El recurso del periodo más reciente de un dataset (p. ej. el último padrón mensual). |
| Metadata y URL real de descarga de un recurso. |
Datos
Tool | Descripción |
| Columnas reales del archivo con tipo inferido, vacíos, valores distintos y ejemplos. Úsalo antes de filtrar. |
| Primeras filas ya parseadas como objetos, con delimitador y encoding detectados. |
| Filtra filas dentro del archivo en streaming, sin descargarlo. Filtros por columna ( |
|
|
| Descarga el archivo completo a disco (último recurso, rara vez necesario). |
| Estado o limpieza de la caché local del catálogo. |
Flujo típico: sunat_buscar_recursos → sunat_perfilar_recurso → sunat_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_searchyorganization_listdevuelven 404. Por eso se navega el grupo de SUNAT congroup_package_showy la búsqueda por palabras clave se hace en cliente.Ante un error el portal responde HTML, no JSON. Se valida el
content-typeantes de parsear, así el fallo dice qué pasó en vez de reventar con un error de sintaxis JSON.package_showygroup_package_showenvuelven el resultado en un array de un solo elemento, a diferencia depackage_list/resource_show. Se desenvuelve solo si hace falta.El WAF responde
418a 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
formatmiente: los padrones RUC se declarancsvpero se sirven como.zip. El tipo se decide por los bytes reales (firmaPK), no por la metadata; cada recurso reporta además unformato_real.El delimitador varía entre archivos:
PadronRUC_202209.csvusa|yPadronRUC_202412.csvusa,. 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ÁNUCOyENSEÑANZAno 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` globalmentesunat 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é localFiltros de find/count (-w, repetible):
Forma | Significado |
| igualdad |
| contiene |
|
|
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: si12.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 |
| Carpeta de la caché del catálogo (default |
| TTL de la caché en ms (default 6 h; |
| Tope de bytes descomprimidos por escaneo (default 6 GB). |
| Carpeta destino por defecto de |
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_columnarechaza columnas con más de 50 000 valores distintos: agrupar por RUC no tiene sentido, para eso estásunat_buscar_en_recurso.escaneo_completo: falsesignifica 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 linkLicencia
MIT. Ver LICENSE.
Available Tools
4 toolssunat_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.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| dataset | Yes | Slug del dataset, obtenido de sunat_listar_datasets |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| resource_id | Yes | Id del recurso, obtenido de sunat_obtener_dataset |
TDQS
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.
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.
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.
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.
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.
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'.
| Name | Required | Description | Default |
|---|---|---|---|
| filas | No | Cantidad de filas de datos a devolver (max 200) | |
| resource_id | Yes | Id del recurso a previsualizar |
TDQS
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.
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.
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.
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.
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.
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.
4 tool updates
v1.0.0- First observed
sunat_listar_datasets - First observed
sunat_obtener_dataset - First observed
sunat_obtener_recurso - First observed
sunat_previsualizar_recurso
TDQS
Scored across 4 tools
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.
All tools follow the pattern `sunat_<verb_in_spanish>_<noun>`, using consistent snake_case and infinitive verbs (listar, obtener, previsualizar).
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.
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
Related MCP Connectors
MCP server for Brazilian Federal Senate open data (legislative, administrative, e-Cidadania).
MCP server for French (BOAMP) + EU (TED) public procurement data via TenderAPI.
This MCP server provides seamless access to Malaysia's government open data, including datasets, w…
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceMCP 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
- AlicenseNot gradedqualityCmaintenanceMCP server for the Moroccan Open Data portal (data.gov.ma) enabling search and retrieval of datasets, resources, organizations, and groups via CKAN API.1MIT
- FlicenseNot gradedqualityCmaintenanceMCP server for Peruvian government data, enabling search and anomaly detection in public procurement (OSCE) and legislative tracking (Congress), plus semantic search over both domains.-
- AlicenseAqualityBmaintenanceLocal MCP server for validating and querying Peruvian RUCs using SUNAT's official reduced registry, stored locally to keep data private.4MIT