CSVBox MCP Server
Servidor MCP para criar, validar e gerenciar importadores CSVBox e fluxos de trabalho de dados CSV.
Documentação
csvbox-mcp-server
Um servidor universal Model Context Protocol (MCP) para CSVBox. Ele expõe o gerenciamento de planilhas de importação do CSVBox como ferramentas MCP, permitindo criar, substituir, corrigir, gerar, validar e estruturar importadores a partir de qualquer cliente compatível com MCP — Claude Desktop, Cursor, Windsurf, Roo Code, Cline, VS Code, ChatGPT MCP e outros.
Funciona via stdio, então opera da mesma forma em todos os clientes.
Ferramentas
| Ferramenta | Finalidade | Chamada de API |
|---|---|---|
create_sheet | Criar uma planilha CSVBox | POST /1.1/sheet |
update_sheet | Substituir uma planilha existente | PUT /1.1/sheet/{key} |
patch_sheet | Atualizar parcialmente uma planilha | PATCH /1.1/sheet/{key} |
generate_sheet_json | Prompt em linguagem natural → JSON completo da planilha (via LLM) | nenhuma (chama o LLM) |
create_importer_from_prompt | Prompt em linguagem natural → validar → criar | POST /1.1/sheet (+ LLM) |
generate_import_code | Código de integração (vanilla-js/react/vue/angular) | nenhuma |
generate_sheet_functions | Prompt em linguagem natural → colunas virtuais / funções de validação / transformações de dados (via LLM) | nenhuma (chama o LLM) |
validate_schema | Validação local de esquema | nenhuma |
O CSVBox atualmente não possui endpoints GET ou LIST, portanto não há intencionalmente ferramentas
get_sheet/list_sheet.
Ele também expõe dois prompts MCP:
| Prompt | Finalidade |
|---|---|
create_csvbox_sheet | Fazer o LLM do próprio cliente host construir uma planilha CSVBox completa (sem necessidade de chave LLM no servidor). |
csvbox_sheet_functions | Fazer o LLM do próprio cliente host criar colunas virtuais, funções de validação e transformações de dados (sem necessidade de chave LLM no servidor). |
Geração de prompt → planilha
generate_sheet_json e create_importer_from_prompt usam um LLM para converter uma solicitação de formato livre em uma planilha CSVBox completa — title, sheet_columns, destinations, webhooks, security_settings e steps. Apenas campos de dados reais se tornam colunas; destinos, webhooks, domínios, regiões, configurações de upload de arquivo e etapas são colocados em suas seções de configuração apropriadas, nunca transformados em colunas. Existem três níveis:
- LLM do servidor — quando
ANTHROPIC_API_KEYouOPENAI_API_KEYestá definido, o servidor chama o LLM diretamente. Funciona no MCP Inspector e em modo headless. - Prompt MCP (
create_csvbox_sheet) — quando você não tem chave de servidor, clientes host (Cursor, Claude Desktop, Cline) executam a geração com seu próprio modelo e depois chamamvalidate_schemaecreate_sheet. Gratuito. - Nenhum configurado —
generate_sheet_jsonretorna um erro estruturado de "nenhum provedor LLM configurado" apontando para o prompt MCP, ecreate_importer_from_promptnão chama a API do CSVBox. Não há fallback por regex.
Expansão de categoria / módulo
O gerador opera em um de dois modos, escolhidos automaticamente a partir do prompt:
- Extração (padrão) — o prompt nomeia campos concretos (ex.: "colunas nome, email, telefone"). Apenas esses se tornam colunas; nada é inventado.
- Expansão — o prompt nomeia módulos / categorias de negócio como uma lista (ex.: "módulos para: Informações da Empresa, Fornecedores, Folha de Pagamento, Fatura"), solicita um esquema abrangente/detalhado ou pede uma contagem de colunas ("pelo menos 100 colunas"). Cada módulo nomeado é expandido em várias colunas realistas, prefixadas e com tipos corretos (ex.: Fornecedores →
supplier_id,supplier_name,supplier_gstin,supplier_email, …). Uma contagem mínima explícita é respeitada e cadacolumn_nameé globalmente único.
Tipos de dados e validações são inferidos a partir dos nomes dos campos e de quaisquer tipos solicitados:
| Solicitado / implícito | Coluna type | Validadores |
|---|---|---|
| Dropdown / status / categoria com opções fixas | list | values: [...] opções candidatas |
| Porcentagem / percentual | number | min_value: 0, max_value: 100 |
| Numérico positivo (quantidade, contagem, estoque, custo, idade) | number | min_value: 0 |
| ID / código / número de referência | text | — |
email | — | |
| Telefone / celular | phone_number | — |
| URL / site | url | — |
| Preço / custo / valor / salário | currency | — |
| Campos de data | date | format: "YYYY-MM-DD" |
| Booleano / is_* / ativo | boolean | — |
| GST / GSTIN / id fiscal | regex | padrão GSTIN |
| Código PIN / código postal (Índia) | regex | ^[1-9][0-9]{5}$ |
Esquemas grandes: os modelos padrão (
claude-haiku-4-5,gpt-4o-mini) são baratos, mas produzem esquemas visivelmente melhores com 100+ colunas quando você substitui por um modelo mais forte viaLLM_MODEL(ex.:claude-sonnet-4-6). O limite de saída é elevado para acomodar planilhas grandes; se uma solicitação ainda for grande demais, a resposta é sinalizada comoTRUNCATED(um resultado distinto, não um erro de análise) e a API do CSVBox não é chamada — reduza a contagem de colunas / módulos ou use um modelo com maior orçamento de saída e tente novamente.
Coleções de funções (colunas virtuais, funções de validação, transformações de dados)
Além das seis propriedades da planilha, a API de Planilhas do CSVBox aceita três coleções cujos itens carregam uma string js_code que o CSVBox executa durante uma importação:
| Coleção | Identificada por | Máx. | js_code deve… |
|---|---|---|---|
virtual_columns | column_name | 20 | retornar o valor calculado da célula |
validation_functions | function_name | 10 | retornar um array de strings de erro ([] = válido) |
data_transforms | transform_name | 10 | modificar o objeto csvbox e retorná-lo |
Dentro de js_code, o objeto csvbox expõe row, column, virtual, user, import e environment. Os dois acessadores não são intercambiáveis — uma coluna virtual é por linha e usa csvbox.row.<name> (um escalar), enquanto uma função com escopo de "column" vê a coluna inteira via csvbox.column.<name> (um array).
Campos opcionais compartilhados: scope (column | row; não em colunas virtuais), run_at (before_validation | after_validation; apenas transformações de dados), columns / dynamic_columns, active, dependencies e _delete (apenas PATCH).
Como criá-las
// 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": [ ... ] }
}
Retorna { "virtual_columns": [...], "validation_functions": [...], "source": ..., "validation": {...} }. Coleções que a solicitação não implica são omitidas, nunca retornadas como arrays vazios.
Esta ferramenta não chama a API do CSVBox. Leia o js_code gerado e aplique-o você mesmo com patch_sheet. Passe sheet para que o modelo referencie nomes reais de colunas e o validador possa verificar essas referências — o CSVBox não tem endpoint de leitura, então ele deve ser fornecido inline. Sem chave LLM, use o prompt MCP csvbox_sheet_functions.
PUT vs PATCH — leia antes de aplicar
update_sheet (PUT) | patch_sheet (PATCH) | |
|---|---|---|
| Coleção enviada | autoritativa — qualquer item existente não nomeado é excluído | mesclada — itens não nomeados são mantidos |
"virtual_columns": [] | exclui todos os 20 | sem efeito |
| Chave omitida | intocada | intocada |
_delete: true | não válido | remove esse item (todos os outros campos ignorados) |
Use patch_sheet para aplicar funções geradas. Valide primeiro com o verbo correspondente:
// validate_schema
{ "sheet": { "data_transforms": [ ... ] }, "mode": "patch" }
mode é create (padrão), put ou patch. Afeta apenas as coleções de funções — sob put, um array vazio é um erro grave em vez de um aviso, e _delete é rejeitado fora de patch.
Dependências
Um item pode carregar até 5 scripts de terceiros:
{ "url": "https://cdn.jsdelivr.net/npm/dayjs@1.11.10/dayjs.min.js",
"globals": ["dayjs"],
"integrity": "sha384-..." }
Apenas cdn.jsdelivr.net, unpkg.com e cdnjs.cloudflare.com são permitidos; somente https, caminho .js/.mjs, sem query string, fragmento, userinfo ou porta.
Segurança. Este servidor nunca executa
js_code— é uma string opaca aqui. JavaScript gerado é saída de modelo não revisada, então leia antes de aplicar via PATCH em um importador ativo. Uma dependência sem digestintegritypode mudar sob seus clientes a qualquer momento;validate_schemaavisa quando um está ausente.
Consulte docs/sheet-functions-example.json para um payload completo.
Instalação
npm install @csvbox/mcp-server
Ou compile a partir do código-fonte:
git clone <this-repo> csvbox-mcp-server
cd csvbox-mcp-server
npm install
npm run build
Isso produz dist/index.js — o entrypoint que os clientes MCP iniciam.
Variáveis de ambiente
Copie .env.example para .env e preencha suas credenciais do CSVBox:
CSVBOX_API_KEY=your_api_key
CSVBOX_API_SECRET=your_api_secret
As credenciais do CSVBox são apenas necessárias para as ferramentas com suporte de API (create_sheet, update_sheet, patch_sheet, create_importer_from_prompt). validate_schema e generate_import_code funcionam sem nenhuma credencial.
Nota sobre o cabeçalho de autenticação: o cliente envia
x-csvbox-api-keyex-csvbox-secret-api-key(correspondendo aos payloads de referência do CSVBox). Eles são definidos como constantes emsrc/services/csvbox-api.tsse sua conta usar nomes de cabeçalho diferentes.
Provedor LLM (para geração de prompt → planilha)
generate_sheet_json e create_importer_from_prompt precisam de um LLM. Defina um de:
ANTHROPIC_API_KEY=sk-ant-...
OPENAI_API_KEY=sk-...
O provedor é detectado automaticamente:
| Condição | Provedor | Modelo padrão |
|---|---|---|
LLM_PROVIDER=anthropic (e sua chave definida) | Anthropic | claude-haiku-4-5 |
LLM_PROVIDER=openai (e sua chave definida) | OpenAI | gpt-4o-mini |
ANTHROPIC_API_KEY definido (sem LLM_PROVIDER) | Anthropic | claude-haiku-4-5 |
OPENAI_API_KEY definido (sem LLM_PROVIDER) | OpenAI | gpt-4o-mini |
| nenhuma chave definida | nenhum — as ferramentas retornam um erro apontando para o prompt MCP create_csvbox_sheet | — |
LLM_PROVIDER desambigua quando ambas as chaves estão presentes; LLM_MODEL substitui o modelo para o provedor escolhido. Para esquemas grandes de categoria/módulo (100+ colunas), defina LLM_MODEL para um modelo mais forte (ex.: claude-sonnet-4-6) — consulte Expansão de categoria / módulo.
MCP Inspector: defina a chave LLM no painel de variáveis de ambiente do Inspector para usar o caminho LLM do servidor. O Inspector não tem LLM host próprio, então pode renderizar o prompt
create_csvbox_sheetmas não pode executá-lo — para o caminho sem chave, use um cliente com modelo (Cursor, Claude Desktop, Cline).
Execução local
# After building:
npm start
# Or run the built file directly:
node dist/index.js
O servidor fala MCP via stdio e registra csvbox-mcp-server running on stdio em stderr (stdout é reservado para o protocolo).
Configuração do cliente
Para uma instalação publicada, use o pacote npm com npx. Defina CSVBOX_API_KEY / CSVBOX_API_SECRET no bloco env.
Nota: O pacote npm é
@csvbox/mcp-servere o executável écsvbox-mcp-server.
Claude Desktop
Adicione o seguinte à sua configuração MCP do 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
Edite ~/.cursor/mcp.json (global) ou .cursor/mcp.json (por projeto):
{
"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
Edite ~/.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
Nas configurações MCP do 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
Nas configurações MCP do 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
Adicione a .vscode/mcp.json (ou ao mcp.json global):
{
"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"
}
}
}
}
Exemplos de chamadas de ferramentas
Gerar uma planilha completa a partir de um prompt (LLM, sem chamada à API do 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" }
Retorna { "sheet": { "title": ..., "sheet_columns": [...], "destinations": [...], "steps": {...} }, "source": "llm:anthropic:claude-haiku-4-5", "validation": { "valid": true, ... } }. Campos de dados se tornam colunas (salary → currency, joining date → date); o destino e a configuração xlsx vão para destinations / steps, não para colunas. Sem chave LLM, retorna um erro apontando para o prompt create_csvbox_sheet.
Validar um esquema antes de enviá-lo:
// validate_schema
{ "sheet": { "title": "Customers", "sheet_columns": [
{ "column_name": "email", "display_label": "Email", "type": "email" }
] } }
Retorna { "valid": true, "errors": [], "warnings": [ ... ] }.
Criar uma planilha:
// create_sheet
{ "sheet": { "title": "Customer Import", "sheet_columns": [
{ "column_name": "name", "display_label": "Name", "type": "text" },
{ "column_name": "email", "display_label": "Email", "type": "email" }
] } }
Gerar + criar em uma única etapa:
// create_importer_from_prompt (requires an LLM key + CSVBox credentials)
{ "prompt": "Create customer importer with name, email, phone; allow for example.com" }
Retorna { "generated_schema": { ... }, "source": ..., "validation": { ... }, "api_response": { ... } }. Aborta sem chamar a API se nenhum provedor LLM estiver configurado ou se o esquema gerado falhar na validação.
Substituir uma planilha:
// update_sheet
{ "sheet_license_key": "abc123", "sheet": { "title": "Updated", "sheet_columns": [ ... ] } }
Destrutivo para qualquer coleção enviada — consulte PUT vs PATCH.
Corrigir uma planilha:
// patch_sheet
{ "sheet_license_key": "abc123", "changes": { "title": "New Title" } }
Remover uma função sem tocar no restante:
// patch_sheet
{ "sheet_license_key": "abc123",
"changes": { "virtual_columns": [ { "column_name": "full_name", "_delete": true } ] } }
Gerar código de integração:
// generate_import_code
{ "framework": "react" }
Tipos de coluna suportados
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.
Desenvolvimento
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)
Testes
npm test compila src/tests/ e o executa com o executor de testes integrado do Node — sem
framework de testes, sem biblioteca de mocks.
A suíte é hermética. Ela nunca contata um host externo, nunca lê suas
variáveis de ambiente CSVBOX_API_* / ANTHROPIC_API_KEY / OPENAI_API_KEY e nunca toca
em uma conta CSVBox real, portanto passa de forma idêntica, independentemente de você ter
credenciais configuradas. O HTTP é interceptado no adaptador do axios; o LLM é um
fake com script; o único teste que precisa de codificação real de requisição inicia um listener
efêmero em 127.0.0.1 e o fecha em seguida. Testes que leem variáveis de ambiente
definem o que precisam explicitamente e restauram os valores anteriores.
Testes E2E
npm run test:e2e # run the Playwright suite
npm run test:e2e:report # open the HTML report from the last run
As especificações ficam em e2e/, configuradas por playwright.config.ts. Assim como a suíte
de unidades, esta suíte é hermética: ela inicia servidores mock de CSVBox e LLM em loopback
(e2e/support/mock-csvbox-server.ts, e2e/support/mock-llm-server.ts) e
aciona o servidor real compilado (dist/index.js) por meio do MCP Inspector com
credenciais falsas apontadas para esses mocks — ela nunca contata uma conta CSVBox
real ou provedor de LLM, e nunca lê seu .env. Uma instância separada do
Inspector, sem credenciais, cobre os caminhos de erro de "credenciais ausentes". Requer
npm run build primeiro (as entradas de test:e2e webServer são construídas
automaticamente).
Incorporando o servidor
createServer() é exportado do módulo de entrada. Ele registra todas as ferramentas e
prompts e retorna o McpServer sem anexar um transporte, para que você possa
conectá-lo a um dos seus próprios:
import { createServer } from "@csvbox/mcp-server";
const server = createServer();
await server.connect(myTransport);
Importar o módulo não inicia nada; o servidor stdio é executado apenas quando
dist/index.js é executado diretamente.
Licença
MIT