MCP Spreadsheet

Lee, consulta, edita y convierte archivos xlsx y csv de forma segura.

Documentación

mcp-spreadsheet

Entrégale una hoja de cálculo a tu asistente de IA y habla con ella. Apúntala a cualquier archivo .xlsx, .xlsm, .xlsb, .xls, .ods, .csv o .tsv en tu máquina y pregúntale qué contiene, fíltralo, calcula una nueva columna o guárdalo en otro formato. Se encarga de las partes complicadas de los archivos reales por ti: adivina qué fila contiene los encabezados, detecta si un CSV está separado por comas, punto y coma o tabulaciones, mantiene intactas las comas y saltos de línea entre comillas, lee números de texto con formato $1,250.00 e informa los tipos por columna y los recuentos de celdas vacías. Nunca edita tu archivo original: cada escritura va a una nueva ruta a menos que elijas explícitamente overwrite. Nada sale de la máquina y no hay ninguna clave de API que obtener.

spreadsheet demo

Lee, consulta y amplía hojas de cálculo reales desde el chat sin tocar nunca el archivo original.

Instalación en 60 segundos

La publicación en npm para @theluckystrike/mcp-spreadsheet está pendiente. Hasta entonces, el paquete de un clic .mcpb o un clon + compilación es la vía funcional: ambos están verificados a continuación.

Un clic (.mcpb): descarga spreadsheet.mcpb de la última versión y haz doble clic en Claude Desktop: https://github.com/theluckystrike/mcp-servers/releases/latest

Claude Desktop (claude_desktop_config.json):

{
  "mcpServers": {
    "spreadsheet": {
      "command": "npx",
      "args": ["-y", "@theluckystrike/mcp-spreadsheet"]
    }
  }
}

Claude Code:

claude mcp add spreadsheet -- npx -y @theluckystrike/mcp-spreadsheet

Cursor (.cursor/mcp.json):

{
  "mcpServers": {
    "spreadsheet": {
      "command": "npx",
      "args": ["-y", "@theluckystrike/mcp-spreadsheet"]
    }
  }
}

El formulario npx anterior empieza a funcionar en cuanto se publique el paquete. Hasta entonces, usa el paquete .mcpb de arriba, o compila desde el código fuente con exactamente estos tres comandos:

git clone https://github.com/theluckystrike/mcp-servers.git && cd mcp-servers
npm install
npm run build -w packages/mcp-license -w servers/spreadsheet

Luego apunta el command de tu cliente a node con un argumento: la ruta absoluta a servers/spreadsheet/dist/index.js.

Para ejecutar en modo Pro, establece MCP_LICENSE_KEY en el mismo bloque de configuración, o llama a license_activate una vez con tu clave.

Herramientas

HerramientaQué hace
sheet_infoNombres de hojas, tamaño, fila de encabezado adivinada, tipo por columna, valores de muestra, recuentos de vacíos
sheet_readLee filas como tabla de texto, registros JSON o CSV; paginación limit/offset o un range A1
sheet_queryFiltra con where, group_by + aggregate (suma, recuento, promedio, mínimo, máximo), selecciona columnas con select, sort (también alias de agregación), limit
sheet_statsrecuento, vacío, distintos, mínimo, máximo, suma, media, mediana por columna (valores principales para columnas de texto)
sheet_findBusca texto en cualquier parte del libro; devuelve direcciones de celda y una vista previa de la fila
sheet_writeEscribe filas (objetos o matrices) como archivo nuevo, una adición o una sobrescritura explícita
sheet_add_columnAñade una columna calculada a partir de una fórmula, guardada en un archivo nuevo. Los resultados numéricos se redondean como sus entradas (2 decimales de entrada, 2 decimales de salida); decimals lo anula
sheet_convertConvierte una hoja a csv, xlsx o json
license_statusGratis o Pro, y dónde actualizar
license_activateActiva una clave Pro (verificada sin conexión)

Plantilla de recurso: sheet://<path> devuelve el resumen sheet_info para ese archivo. Recurso: sheet://recent enumera los archivos que este servidor ha abierto desde que se inició, los más recientes primero (solo en memoria: no se escribe nada en el disco, por lo que la lista vuelve a estar vacía después de un reinicio).

Indicación: explore_sheet recorre un archivo desconocido: sheet_info primero, luego llamadas sheet_query concretas construidas a partir de las columnas que realmente encontró.

Lo que puedes decir

Tú dicesHerramienta
"Abre sales.xlsx y dime qué contiene."sheet_info
"Muéstrame las primeras 50 filas."sheet_read
"¿Qué representante vendió más unidades en la región Norte? Top 5 con totales."sheet_query (group_by + aggregate)
"¿Cuántas celdas vacías hay en la columna Email y cuál es el tamaño de pedido mediano?"sheet_stats
"Encuentra todas las filas que mencionen 'reembolso'."sheet_find
"Escribe esto como una hoja nueva llamada Resultados Q3."sheet_write
"Añade una columna Ingresos que sea Unidades por Precio Unitario, guárdala como CSV junto al original."sheet_add_column
"Convierte este xlsx a JSON."sheet_convert
"¿Estoy en el plan gratuito o en Pro?"license_status
"Aquí está mi clave de licencia, actívala."license_activate

Ejemplo práctico

Desde docs/USER_VALUE_R2.md, un archivo de prueba de 400 filas con una fila de título y una fila en blanco encima del encabezado real (fila 3), hojas Sales / Reps / Notes, precios almacenados como cadenas como "1,516.16". Una llamada, verdad terreno confirmada contra el generador: Turing 650, Hopper 567, Linus T 551, Lovelace 486, Liskov 290.

You: Which rep sold the most units in the North region? Top 5 with totals.

  sheet_query {
    path: "/Users/you/sales.xlsx", sheet: "Sales",
    where: "[Region] = \"North\"",
    group_by: ["Rep"],
    aggregate: [{ col: "Units", fn: "sum", as: "total_units" }],
    sort: { col: "total_units", dir: "desc" },
    limit: 5
  }

Assistant: Query: where [Region] = "North"; group by Rep; sum Units as total_units;
sort total_units desc; limit 5
5 groups from 102 of 400 rows, showing 5

Alan Turing     650
Grace Hopper    567
Linus T         551
Ada Lovelace    486
Barbara Liskov  290

La respuesta ahora repite la consulta exacta que ejecutó (la línea Query:) antes de los números, de modo que un filtro que no pediste (un AND [Status] = "Closed" accidental, por ejemplo) es visible en lugar de reducir silenciosamente la respuesta.

Un segundo ejemplo, añadiendo una columna y guardando sin tocar la fuente:

You: Add a Revenue column and save it as a CSV next to the original.

  sheet_add_column {
    path: "/Users/you/sales.xlsx", sheet: "Sales",
    name: "Revenue", formula: "[Units] * [Unit Price]",
    out_path: "/Users/you/sales.csv"
  }

Assistant: Wrote 400 rows (401 lines with header) to sales.csv.
Revenue = Units * Unit Price on every row, total 10,142,542.04.
Source file untouched.

El lenguaje where y formula

Un pequeño lenguaje de expresiones, analizado y evaluado directamente. No hay eval ni ejecución de código: una palabra suelta siempre es un nombre de columna, nunca un valor de JavaScript.

  • Columnas: [Unit Price] para nombres con espacios, Qty en caso contrario. La búsqueda no distingue mayúsculas.
  • Comparaciones: = != > >= < <= contains startswith endswith
  • Lógica: AND OR NOT y paréntesis. AND se une con más fuerza que OR.
  • Aritmética en fórmulas: + - * % / con la precedencia habitual.
  • Cadenas: comillas 'single' o "double"; duplica una comilla para escaparla.
[Qty] >= 5 AND ([Status] = "open" OR [Region] contains "north")
[Amount] > 1000 AND NOT [Customer] startswith 'Test'

Ejemplo de fórmula para sheet_add_column: [Qty] * [Unit Price]. Cuando cada columna que la fórmula lee tiene como máximo 2 decimales, el resultado se redondea a 2 decimales, de modo que [Amount] * 1.23 sobre dinero da 40.79 en lugar de 40.7868. Pasa decimals (0-10) para elegir la precisión tú mismo.

Los números escritos como texto en un CSV se convierten por patrón, no por longitud: 1250.00, 12.00 y 1,250.00 se convierten todos en números en la salida xlsx, de modo que el propio SUM de Excel los cuenta. Los valores con forma de identificador y los ambiguos permanecen como texto: 007 conserva sus ceros iniciales y 1.250,00 se deja como está en lugar de adivinarse.

Las comparaciones de texto ignoran mayúsculas y espacios circundantes. Valores como $1,250.00, 1 250 y 12% se comparan como números, de modo que [Amount] > 1000 funciona en una columna que tu hoja de cálculo almacenó como texto.

Gratis vs Pro

GratisPro
Cada herramienta que lee un archivo (sheet_info, sheet_read, sheet_query, sheet_stats, sheet_find, sheet_add_column, sheet_convert)Archivos de hasta 5 MB y 5,000 filasSin límite (hasta el tope de archivo de 50 MB)
sheet_write, sheet_add_column, sheet_convertHasta 500 filas escritas por archivo; por encima de eso no se escribe nada y la herramienta lo diceSin límite
Hojas, formatos, lenguaje de expresionesTodoTodo

Por encima de un límite de lectura gratuito, la herramienta aún hace el trabajo y devuelve la parte que se le permite devolver (las primeras 5,000 filas), con una nota que dice lo que se omitió. Por encima del límite de escritura gratuito no se escribe nada en absoluto: un archivo parcial que parece completo es peor que ningún archivo, por lo que la herramienta se niega, te dice el recuento de filas y el tope, y sugiere una solución gratuita (filtra las filas primero o escribe en lotes de 500 filas). Nada falla en silencio.

Obtén Pro

$19 de pago único para este servidor, $39 para cada servidor, de por vida: https://mcp.zovo.one/buy/spreadsheet

Cómo almacena datos

Este servidor no mantiene ninguna base de datos propia: lee y escribe los archivos de hoja de cálculo a los que lo apuntas, directamente en tu disco, y nada más. Cada escritura (sheet_write, sheet_add_column, sheet_convert en modo overwrite) va primero a un archivo temporal en el mismo directorio y luego se renombra en su lugar, de modo que una escritura interrumpida deja el original intacto o el archivo nuevo completo, nunca uno truncado. Como no hay archivo de estado compartido, no hay bloqueo de asesoramiento que tomar: dos llamadas que escriben en dos rutas de salida diferentes no pueden colisionar, y una llamada a overwrite el mismo archivo dos veces seguidas es simplemente dos escrituras en secuencia. Para respaldar tus datos, respalda los propios archivos de hoja de cálculo: no hay nada más que copiar.

Límites y advertencias honestas

  • Las lecturas gratuitas tienen un tope de 5,000 filas y 5 MB; las escrituras gratuitas tienen un tope de 500 filas por archivo y se niegan en lugar de truncar: recibes un error que nombra el recuento de filas y el tope, nunca un archivo más corto que parezca completo.
  • El tope duro es de 50 MB independientemente del nivel; un archivo que supere eso se rechaza directamente con un mensaje claro en lugar de arriesgar el agotamiento de memoria.
  • El lenguaje where/formula es intencionalmente pequeño: sin expresiones regulares, sin funciones personalizadas, sin referencias entre hojas en una sola fórmula. Cubre comparaciones, lógica booleana y aritmética, nada más.
  • Escribir un xlsx reemplaza una hoja, no el libro. sheet_write con append o overwrite lee todo el libro, intercambia la hoja que nombraste y escribe todas las demás hojas de vuelta, de modo que Sheet2 y sus datos sobreviven a una adición a Sheet1. Lo que no se conserva es la hoja que se está escribiendo: se reconstruye a partir de valores, por lo que fórmulas, formato de celdas, formato condicional, gráficos, validación de datos y celdas combinadas en esa única hoja se convierten en valores simples. Las otras hojas conservan sus celdas tal como se leyeron. Haz una copia primero si la hoja de destino tiene formato que no puedas recrear.
  • Los números escritos como texto se leen con reglas sensibles a la configuración regional. 1,250.00, 1 250.00, $1,250.00, 12,99, 1.234,56 y EUR 1 250,00 se leen todos como números; una coma decimal solo se acepta en la forma inequívoca (una coma con exactamente dos dígitos al final, puntos o espacios agrupando). Cualquier cosa que mezcle separadores de otra manera (1,2500.00) permanece como texto en lugar de adivinarse. Valores con ceros iniciales (007) y enteros demasiado grandes para aritmética exacta (más de 9,007,199,254,740,991) permanecen como texto para que nunca se alteren silenciosamente.
  • Las fechas conservan su tipo de celda. Una celda de fecha leída de un xlsx sigue siendo una fecha a través de consultas y a través de una conversión de vuelta a xlsx. En salida de texto, CSV y JSON se representa como ISO: 2026-09-04 para una fecha, 2026-09-03T15:30:00 cuando la celda lleva una hora.
  • La suposición de fila de encabezado de sheet_info es una heurística (busca la primera fila con menor vacío y mayor densidad de texto que las filas de arriba). Maneja una fila de título y una fila en blanco encima del encabezado; no es a prueba de todos los diseños, y siempre puedes confirmar lo que eligió antes de consultar.

Solución de problemas

  • npx se cuelga o no encuentra el paquete: la publicación npm de este paquete está pendiente. Usa el paquete .mcpb o la ruta de clonar y compilar indicada arriba hasta que esté disponible.
  • Usando el paquete .mcpb: se instala directamente en Claude Desktop; no hay un paso de configuración separado.
  • Usando la ruta de clonación: el binario del servidor es servers/spreadsheet/dist/index.js después de npm run build. Apunta el command de tu cliente a node con esa ruta absoluta como único argumento.
  • Versión de Node: requiere Node >= 18. Verifica con node -v.
  • "La ruta no existe": el mensaje incluye la ruta absoluta resuelta (con ~ expandido) -- compruébala contra dónde está realmente el archivo, especialmente dentro de un cliente en sandbox o contenedor.
  • Una escritura se rechaza con un mensaje de recuento de filas: alcanzaste el límite gratuito de escritura de 500 filas. Filtra los datos con sheet_query primero, escribe en lotes o activa Pro.
  • No aparece nada / fallos silenciosos: los registros van solo a stderr, nunca a stdout. En Claude Desktop revisa Configuración -> Desarrollador -> el archivo de registro del servidor; en Claude Code revisa la terminal o --mcp-debug.

Seguridad

  • Las rutas que no existen se rechazan con la ruta resuelta en el mensaje; ~ se expande.
  • Los archivos de más de 50 MB se rechazan con un mensaje claro en lugar de agotar la memoria.
  • sheet_add_column y sheet_convert escriben en un archivo nuevo y se niegan a sobrescribir uno existente a menos que pases out_path tú mismo.
  • sheet_write con mode: "new_file" se niega a sobrescribir un archivo existente. Solo mode: "overwrite" reemplaza el contenido de un archivo.
  • Los archivos de salida se escriben con un nombre temporal y se renombran en su lugar, por lo que una escritura interrumpida no puede truncar un archivo.

Privacidad

Todos los datos permanecen locales. Los archivos se leen y escriben en tu propio disco, las claves de licencia se verifican sin conexión con una clave pública integrada, y el servidor no realiza ninguna solicitud de red.

Se combina con

Preguntas frecuentes

¿Maneja una hoja de cálculo con una fila de título encima de los encabezados? Sí. sheet_info adivina la fila de encabezados e informa qué fila eligió, por lo que una exportación con una línea de título y una línea en blanco encima de los encabezados reales se abre correctamente sin que especifiques nada.

¿Puede agrupar y sumar, o solo filtrar? Agrupa. sheet_query toma group_by más aggregate con suma, conteo, promedio, mínimo o máximo, y puede ordenar por un alias agregado, por lo que las preguntas de top-N-por-categoría son una sola llamada.

¿Sobrescribirá mi archivo original? No, a menos que pases explícitamente una ruta de salida que apunte al origen. sheet_add_column y sheet_convert escriben un archivo nuevo junto al original por defecto.

¿Qué sucede en el plan gratuito con un archivo más grande que el límite? Las lecturas devuelven las primeras 5,000 filas con una nota que indica lo que se omitió. Las escrituras de más de 500 filas se rechazan directamente en lugar de producir un archivo truncado, y el mensaje te indica el recuento de filas, el límite y una forma gratuita de evitarlo.

¿Se envía mi dato a algún lugar? No. El servidor se ejecuta localmente en tu máquina y lee tus archivos directamente. No realiza solicitudes de red, y no almacena nada propio más allá de los archivos que le pides que escriba.

Creado por theluckystrike. Soporte: support@zovo.one