CSVBox MCP Server
Servidor MCP para crear, validar y gestionar importadores de CSVBox y flujos de trabajo de datos CSV.
Documentación
csvbox-mcp-server
Un servidor universal de Model Context Protocol (MCP) para CSVBox. Expone la gestión de hojas de importación de CSVBox como herramientas MCP para que puedas crear, reemplazar, parchear, generar, validar y estructurar importadores desde cualquier cliente compatible con MCP: Claude Desktop, Cursor, Windsurf, Roo Code, Cline, VS Code, ChatGPT MCP y más.
Funciona sobre stdio, por lo que funciona igual en todos los clientes.
Herramientas
| Herramienta | Propósito | Llamada a la API |
|---|---|---|
create_sheet | Crear una hoja de CSVBox | POST /1.1/sheet |
update_sheet | Reemplazar una hoja existente | PUT /1.1/sheet/{key} |
patch_sheet | Actualizar parcialmente una hoja | PATCH /1.1/sheet/{key} |
generate_sheet_json | Prompt en lenguaje natural → JSON completo de hoja (vía LLM) | ninguna (llama al LLM) |
create_importer_from_prompt | Prompt en lenguaje natural → validar → crear | POST /1.1/sheet (+ LLM) |
generate_import_code | Código de integración (vanilla-js/react/vue/angular) | ninguna |
generate_sheet_functions | Prompt en lenguaje natural → columnas virtuales / funciones de validación / transformaciones de datos (vía LLM) | ninguna (llama al LLM) |
validate_schema | Validación local de esquema | ninguna |
CSVBox actualmente no tiene endpoints GET o LIST, por lo que intencionalmente no hay herramientas
get_sheet/list_sheet.
También expone dos prompts MCP:
| Prompt | Propósito |
|---|---|
create_csvbox_sheet | Hacer que el LLM del cliente anfitrión construya una hoja CSVBox completa (sin necesidad de clave LLM en el servidor). |
csvbox_sheet_functions | Hacer que el LLM del cliente anfitrión redacte columnas virtuales, funciones de validación y transformaciones de datos (sin necesidad de clave LLM en el servidor). |
Generación de hoja a partir de prompt
generate_sheet_json y create_importer_from_prompt usan un LLM para convertir una solicitud de formato libre en una hoja CSVBox completa: title, sheet_columns, destinations, webhooks, security_settings y steps. Solo los campos de datos reales se convierten en columnas; los destinos, webhooks, dominios, regiones, configuración de carga de archivos y pasos se colocan en sus secciones de configuración correspondientes, nunca se convierten en columnas. Hay tres niveles:
- LLM del servidor: cuando se establece
ANTHROPIC_API_KEYoOPENAI_API_KEY, el servidor llama al LLM directamente. Funciona en MCP Inspector y sin interfaz gráfica. - Prompt MCP (
create_csvbox_sheet): cuando no tienes clave de servidor, los clientes anfitriones (Cursor, Claude Desktop, Cline) ejecutan la generación con su propio modelo y luego llaman avalidate_schemaycreate_sheet. Gratis. - Nada configurado:
generate_sheet_jsondevuelve un error estructurado de "no hay proveedor LLM configurado" que apunta al prompt MCP, ycreate_importer_from_promptno llama a la API de CSVBox. No hay respaldo con expresiones regulares.
Expansión de categorías / módulos
El generador funciona en uno de dos modos, elegidos automáticamente según el prompt:
- Extracción (predeterminado): el prompt nombra campos concretos (p. ej., "columnas nombre, correo, teléfono"). Solo esos se convierten en columnas; no se inventa nada.
- Expansión: el prompt nombra módulos / categorías de negocio como lista (p. ej., "módulos para: Información de la empresa, Proveedores, Nómina, Factura"), solicita un esquema completo/detallado, o pide una cantidad de columnas ("al menos 100 columnas"). Cada módulo nombrado se expande en varias columnas realistas, con prefijo y tipo correcto (p. ej., Proveedores →
supplier_id,supplier_name,supplier_gstin,supplier_email, …). Se respeta un mínimo explícito y cadacolumn_namees globalmente único.
Los tipos de datos y validaciones se infieren de los nombres de los campos y de los tipos solicitados:
| Solicitado / implícito | Columna type | Validadores |
|---|---|---|
| Desplegable / estado / categoría con opciones fijas | list | values: [...] opciones candidatas |
| Porcentaje / percent | number | min_value: 0, max_value: 100 |
| Numérico positivo (cantidad, recuento, stock, costo, edad) | number | min_value: 0 |
| ID / código / número de referencia | text | — |
| Correo electrónico | email | — |
| Teléfono / móvil | phone_number | — |
| URL / sitio web | url | — |
| Precio / costo / monto / salario | currency | — |
| Campos de fecha | date | format: "YYYY-MM-DD" |
| Booleano / is_* / activo | boolean | — |
| GST / GSTIN / ID fiscal | regex | patrón GSTIN |
| Código PIN / código postal (India) | regex | ^[1-9][0-9]{5}$ |
Esquemas grandes: los modelos predeterminados (
claude-haiku-4-5,gpt-4o-mini) son económicos pero producen esquemas de 100+ columnas notablemente mejores cuando se sobrescriben con un modelo más potente medianteLLM_MODEL(p. ej.,claude-sonnet-4-6). El límite de salida se eleva para admitir hojas grandes; si una solicitud sigue siendo demasiado grande, la respuesta se marca comoTRUNCATED(un resultado distinto, no un error de análisis) y no se llama a la API de CSVBox: reduce la cantidad de columnas / módulos o usa un modelo con mayor presupuesto de salida y reintenta.
Colecciones de funciones (columnas virtuales, funciones de validación, transformaciones de datos)
Además de las seis propiedades de la hoja, la API de hojas de CSVBox acepta tres colecciones cuyos elementos llevan una cadena js_code que CSVBox ejecuta durante una importación:
| Colección | Identificada por | Máx. | js_code debe… |
|---|---|---|---|
virtual_columns | column_name | 20 | devolver el valor de celda calculado |
validation_functions | function_name | 10 | devolver un arreglo de cadenas de error ([] = válido) |
data_transforms | transform_name | 10 | mutar el objeto csvbox y devolverlo |
Dentro de js_code, el objeto csvbox expone row, column, virtual, user, import y environment. Los dos accesores no son intercambiables: una columna virtual es por fila y usa csvbox.row.<name> (un escalar), mientras que una función con ámbito de "column" ve la columna completa mediante csvbox.column.<name> (un arreglo).
Campos opcionales compartidos: scope (column | row; no en columnas virtuales), run_at (before_validation | after_validation; solo transformaciones de datos), columns / dynamic_columns, active, dependencies y _delete (solo PATCH).
Cómo redactarlas
// generate_sheet_functions (requires ANTHROPIC_API_KEY or OPENAI_API_KEY)
{
"prompt": "add a virtual column joining first and last name, and check every email contains an @",
"sheet": { "title": "Customers", "sheet_columns": [ ... ] }
}
Devuelve { "virtual_columns": [...], "validation_functions": [...], "source": ..., "validation": {...} }. Las colecciones que la solicitud no implica se omiten, nunca se devuelven como arreglos vacíos.
Esta herramienta no llama a la API de CSVBox. Lee el js_code generado y luego aplícalo tú mismo con patch_sheet. Pasa sheet para que el modelo haga referencia a nombres de columna reales y el validador pueda verificar esas referencias: CSVBox no tiene endpoint de lectura, por lo que debe proporcionarse en línea. Sin clave LLM, usa el prompt MCP csvbox_sheet_functions en su lugar.
PUT vs PATCH: lee esto antes de aplicar
update_sheet (PUT) | patch_sheet (PATCH) | |
|---|---|---|
| Colección que envías | autoritativa: cualquier elemento existente no nombrado se elimina | fusionada: los elementos no nombrados se dejan intactos |
"virtual_columns": [] | elimina los 20 | no-op |
| Clave omitida | intacta | intacta |
_delete: true | no válido | elimina ese elemento (se ignoran todos sus demás campos) |
Usa patch_sheet para aplicar funciones generadas. Valida primero con el verbo correspondiente:
// validate_schema
{ "sheet": { "data_transforms": [ ... ] }, "mode": "patch" }
mode es create (predeterminado), put o patch. Solo afecta a las colecciones de funciones: bajo put, un arreglo vacío es un error grave en lugar de una advertencia, y _delete se rechaza fuera de patch.
Dependencias
Un elemento puede cargar hasta 5 scripts de terceros:
{ "url": "https://cdn.jsdelivr.net/npm/dayjs@1.11.10/dayjs.min.js",
"globals": ["dayjs"],
"integrity": "sha384-..." }
Solo se permiten cdn.jsdelivr.net, unpkg.com y cdnjs.cloudflare.com; solo https, ruta .js/.mjs, sin cadena de consulta, fragmento, userinfo ni puerto.
Seguridad. Este servidor nunca ejecuta
js_code: aquí es solo una cadena opaca. El JavaScript generado es salida de modelo sin revisar, así que léelo antes de aplicarlo con PATCH a un importador en producción. Una dependencia sin resumenintegritypuede cambiar bajo tus clientes en cualquier momento;validate_schemaadvierte cuando falta una.
Consulta docs/sheet-functions-example.json para ver una carga útil completa.
Instalación
npm install @csvbox/mcp-server
O compila desde el código fuente:
git clone <this-repo> csvbox-mcp-server
cd csvbox-mcp-server
npm install
npm run build
Esto produce dist/index.js: el punto de entrada que lanzan los clientes MCP.
Variables de entorno
Copia .env.example a .env y completa tus credenciales de CSVBox:
CSVBOX_API_KEY=your_api_key
CSVBOX_API_SECRET=your_api_secret
Las credenciales de CSVBox solo se requieren para las herramientas respaldadas por API (create_sheet, update_sheet, patch_sheet, create_importer_from_prompt). validate_schema y generate_import_code funcionan sin credenciales.
Nota sobre el encabezado de autenticación: el cliente envía
x-csvbox-api-keyyx-csvbox-secret-api-key(coincidiendo con las cargas útiles de referencia de CSVBox). Están definidos como constantes ensrc/services/csvbox-api.tssi tu cuenta usa nombres de encabezado diferentes.
Proveedor LLM (para generación de hoja a partir de prompt)
generate_sheet_json y create_importer_from_prompt necesitan un LLM. Establece uno de:
ANTHROPIC_API_KEY=sk-ant-...
OPENAI_API_KEY=sk-...
El proveedor se detecta automáticamente:
| Condición | Proveedor | Modelo predeterminado |
|---|---|---|
LLM_PROVIDER=anthropic (y su clave establecida) | Anthropic | claude-haiku-4-5 |
LLM_PROVIDER=openai (y su clave establecida) | OpenAI | gpt-4o-mini |
ANTHROPIC_API_KEY establecido (sin LLM_PROVIDER) | Anthropic | claude-haiku-4-5 |
OPENAI_API_KEY establecido (sin LLM_PROVIDER) | OpenAI | gpt-4o-mini |
| ninguna clave establecida | ninguno: las herramientas devuelven un error que apunta al prompt MCP create_csvbox_sheet | — |
LLM_PROVIDER desambigua cuando ambas claves están presentes; LLM_MODEL sobrescribe el modelo para el proveedor elegido. Para esquemas grandes de categorías/módulos (100+ columnas), establece LLM_MODEL a un modelo más potente (p. ej., claude-sonnet-4-6): consulta Expansión de categorías / módulos.
MCP Inspector: establece la clave LLM en el panel de variables de entorno del Inspector para usar la ruta del LLM del servidor. Inspector no tiene LLM anfitrión propio, por lo que puede renderizar el prompt
create_csvbox_sheetpero no puede ejecutarlo: para la ruta sin clave, usa un cliente con modelo (Cursor, Claude Desktop, Cline).
Ejecución local
# After building:
npm start
# Or run the built file directly:
node dist/index.js
El servidor habla MCP sobre stdio y registra csvbox-mcp-server running on stdio en stderr (stdout está reservado para el protocolo).
Configuración del cliente
Para una instalación publicada, usa el paquete npm con npx. Establece CSVBOX_API_KEY / CSVBOX_API_SECRET en el bloque env.
Nota: el paquete npm es
@csvbox/mcp-servery el ejecutable escsvbox-mcp-server.
Claude Desktop
Agrega lo siguiente a tu configuración MCP de Claude Desktop:
{
"mcpServers": {
"csvbox": {
"command": "npx",
"args": [
"-y",
"--package=@csvbox/mcp-server",
"csvbox-mcp-server"
],
"env": {
"CSVBOX_API_KEY": "your_api_key",
"CSVBOX_API_SECRET": "your_api_secret"
}
}
}
}
Cursor
Edita ~/.cursor/mcp.json (global) o .cursor/mcp.json (por proyecto):
{
"mcpServers": {
"csvbox": {
"command": "npx",
"args": [
"-y",
"--package=@csvbox/mcp-server",
"csvbox-mcp-server"
],
"env": {
"CSVBOX_API_KEY": "your_api_key",
"CSVBOX_API_SECRET": "your_api_secret"
}
}
}
}
Windsurf
Edita ~/.codeium/windsurf/mcp_config.json:
{
"mcpServers": {
"csvbox": {
"command": "npx",
"args": [
"-y",
"--package=@csvbox/mcp-server",
"csvbox-mcp-server"
],
"env": {
"CSVBOX_API_KEY": "your_api_key",
"CSVBOX_API_SECRET": "your_api_secret"
}
}
}
}
Roo Code
En la configuración MCP de Roo Code (mcp_settings.json):
{
"mcpServers": {
"csvbox": {
"command": "npx",
"args": [
"-y",
"--package=@csvbox/mcp-server",
"csvbox-mcp-server"
],
"env": {
"CSVBOX_API_KEY": "your_api_key",
"CSVBOX_API_SECRET": "your_api_secret"
}
}
}
}
Cline
En la configuración MCP de Cline (cline_mcp_settings.json):
{
"mcpServers": {
"csvbox": {
"command": "npx",
"args": [
"-y",
"--package=@csvbox/mcp-server",
"csvbox-mcp-server"
],
"env": {
"CSVBOX_API_KEY": "your_api_key",
"CSVBOX_API_SECRET": "your_api_secret"
}
}
}
}
VS Code MCP
Agrega a .vscode/mcp.json (o al global mcp.json):
{
"servers": {
"csvbox": {
"command": "npx",
"args": [
"-y",
"--package=@csvbox/mcp-server",
"csvbox-mcp-server"
],
"env": {
"CSVBOX_API_KEY": "your_api_key",
"CSVBOX_API_SECRET": "your_api_secret"
}
}
}
}
Ejemplos de llamadas a herramientas
Generar una hoja completa a partir de un prompt (LLM, sin llamada a la API de CSVBox):
// generate_sheet_json (requires ANTHROPIC_API_KEY or OPENAI_API_KEY)
{ "prompt": "Create employee importer with name, email, salary, joining date; destination as testapi; allow only xlsx files" }
Devuelve { "sheet": { "title": ..., "sheet_columns": [...], "destinations": [...], "steps": {...} }, "source": "llm:anthropic:claude-haiku-4-5", "validation": { "valid": true, ... } }. Los campos de datos se convierten en columnas (salary → currency, joining date → date); el destino y la configuración de xlsx van a destinations / steps, no a columnas. Sin clave LLM, devuelve un error que apunta al prompt create_csvbox_sheet.
Validar un esquema antes de enviarlo:
// validate_schema
{ "sheet": { "title": "Customers", "sheet_columns": [
{ "column_name": "email", "display_label": "Email", "type": "email" }
] } }
Devuelve { "valid": true, "errors": [], "warnings": [ ... ] }.
Crear una hoja:
// create_sheet
{ "sheet": { "title": "Customer Import", "sheet_columns": [
{ "column_name": "name", "display_label": "Name", "type": "text" },
{ "column_name": "email", "display_label": "Email", "type": "email" }
] } }
Generar + crear en un solo paso:
// create_importer_from_prompt (requires an LLM key + CSVBox credentials)
{ "prompt": "Create customer importer with name, email, phone; allow for example.com" }
Devuelve { "generated_schema": { ... }, "source": ..., "validation": { ... }, "api_response": { ... } }. Se aborta sin llamar a la API si no hay proveedor LLM configurado o si el esquema generado falla la validación.
Reemplazar una hoja:
// update_sheet
{ "sheet_license_key": "abc123", "sheet": { "title": "Updated", "sheet_columns": [ ... ] } }
Destructivo para cualquier colección que envíes: consulta PUT vs PATCH.
Parchear una hoja:
// patch_sheet
{ "sheet_license_key": "abc123", "changes": { "title": "New Title" } }
Eliminar una función sin tocar el resto:
// patch_sheet
{ "sheet_license_key": "abc123",
"changes": { "virtual_columns": [ { "column_name": "full_name", "_delete": true } ] } }
Generar código de integración:
// generate_import_code
{ "framework": "react" }
Tipos de columna admitidos
text, number, email, date, time, boolean, regex, ip, url, credit_card, phone_number, currency, list, dependent_list, dynamic_list, dependent_dynamic_list, multiselect_list, multiselect_dynamic_list.
Desarrollo
npm run build # compile TypeScript → dist/
npm start # run the built server
npm run lint # type-check without emitting
npm test # compile and run the unit suite (alias: npm run test:unit)
Pruebas
npm test compila src/tests/ y lo ejecuta con el ejecutor de pruebas integrado de Node — sin
framework de pruebas, sin librería de mocks.
La suite es hermética. Nunca contacta un host externo, nunca lee tu
CSVBOX_API_* / ANTHROPIC_API_KEY / OPENAI_API_KEY ambiental, y nunca toca
una cuenta real de CSVBox, por lo que pasa de manera idéntica tengas o no
credenciales configuradas. HTTP se intercepta en el adaptador de axios; el LLM es un
fake con guion; la única prueba que necesita codificación real de solicitudes inicia un listener
efímero en 127.0.0.1 y lo cierra después. Las pruebas que leen variables de entorno
establecen lo que necesitan explícitamente y restauran los valores anteriores.
Pruebas E2E
npm run test:e2e # run the Playwright suite
npm run test:e2e:report # open the HTML report from the last run
Los specs viven en e2e/, configurados por playwright.config.ts. Como la suite
unitaria, esta suite es hermética: inicia servidores mock de CSVBox y LLM en loopback
(e2e/support/mock-csvbox-server.ts, e2e/support/mock-llm-server.ts) y
conduce el servidor real compilado (dist/index.js) a través de MCP Inspector con
credenciales falsas apuntando a esos mocks — nunca contacta una cuenta real de CSVBox
o un proveedor de LLM, y nunca lee tu .env. Una instancia separada de
Inspector sin credenciales cubre las rutas de error de "credenciales faltantes". Requiere
npm run build primero (las entradas de test:e2e webServer se construyen
automáticamente).
Incrustar el servidor
createServer() se exporta desde el módulo de entrada. Registra cada herramienta y
prompt y devuelve el McpServer sin adjuntar un transporte, para que puedas
conectarlo a uno propio:
import { createServer } from "@csvbox/mcp-server";
const server = createServer();
await server.connect(myTransport);
Importar el módulo no inicia nada; el servidor stdio se ejecuta solo cuando
dist/index.js se ejecuta directamente.
Licencia
MIT