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, portanto 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 em 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 quantidade 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 quantidade 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 possui endpoint de leitura, portanto ele deve ser fornecido inline. Sem chave LLM, use o prompt MCP csvbox_sheet_functions.
PUT vs PATCH — leia isto 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. Isso 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— aqui é apenas uma string opaca. JavaScript gerado é saída de modelo não revisada, portanto 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 exigidas apenas para as ferramentas com suporte a API (create_sheet, update_sheet, patch_sheet, create_importer_from_prompt). validate_schema e generate_import_code funcionam sem nenhuma credencial.
Nota sobre cabeçalho de autenticação: o cliente envia
x-csvbox-api-keyex-csvbox-secret-api-key(correspondendo aos payloads de referência do CSVBox). Elas são definidas como constantes emsrc/services/csvbox-api.tsse sua conta usar nomes de cabeçalho diferentes.
Identificação do cliente
Toda solicitação que este servidor envia à API do CSVBox carrega dois cabeçalhos extras:
x-csvbox-client: mcp
x-csvbox-client-version: <the version in package.json>
O CSVBox registra como cada planilha foi criada; sem eles, planilhas e importações feitas via MCP são indistinguíveis de qualquer outro chamador REST. A versão é lida de package.json e é a mesma que o servidor anuncia ao seu cliente MCP, portanto os dois nunca podem divergir.
Eles são sempre enviados — não há variável de ambiente ou entrada de ferramenta que os desative ou altere. Eles não carregam credenciais nem nada derivado das entradas de suas ferramentas. Ferramentas que não fazem chamada de API (generate_sheet_json, generate_sheet_functions, generate_import_code, validate_schema) não enviam solicitação e, portanto, nenhum cabeçalho.
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, portanto pode renderizar o prompt
create_csvbox_sheet, mas 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 à 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 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"
}
}
}
}
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, ... } }. Os campos de dados tornam-se colunas (salary → currency, joining date → date); o destino e a configuração de xlsx vão para destinations / steps, não para colunas. Sem chave de LLM, retorna um erro apontando para o prompt create_csvbox_sheet.
Valide um schema antes de enviá-lo:
// validate_schema
{ "sheet": { "title": "Customers", "sheet_columns": [
{ "column_name": "email", "display_label": "Email", "type": "email" }
] } }
Retorna { "valid": true, "errors": [], "warnings": [ ... ] }.
Crie 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" }
] } }
Gere + crie 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 de LLM estiver configurado ou se o schema gerado falhar na validação.
Substitua uma planilha:
// update_sheet
{ "sheet_license_key": "abc123", "sheet": { "title": "Updated", "sheet_columns": [ ... ] } }
Destrutivo para qualquer coleção que você enviar — veja PUT vs PATCH.
Aplique patch em uma planilha:
// patch_sheet
{ "sheet_license_key": "abc123", "changes": { "title": "New Title" } }
Remova uma função sem tocar no restante:
// patch_sheet
{ "sheet_license_key": "abc123",
"changes": { "virtual_columns": [ { "column_name": "full_name", "_delete": true } ] } }
Gere 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 axios; o LLM é um
fake roteirizado; 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. Como a suíte de
testes unitários, 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 do webServer test:e2e 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