MCP Spreadsheet

Leia, consulte, edite e converta arquivos xlsx e csv com segurança.

Documentação

mcp-spreadsheet

Entregue uma planilha ao seu assistente de IA e converse com ela. Aponte-o para qualquer arquivo .xlsx, .xlsm, .xlsb, .xls, .ods, .csv ou .tsv na sua máquina e pergunte o que há nele, filtre-o, calcule uma nova coluna ou salve-o em outro formato. Ele lida com as partes complicadas de arquivos reais para você: ele adivinha qual linha contém os cabeçalhos, detecta se um CSV é separado por vírgulas, ponto e vírgula ou tabulações, mantém vírgulas e quebras de linha entre aspas intactas, lê números de texto no estilo $1,250.00 e relata tipos por coluna e contagens de células vazias. Ele nunca edita seu arquivo original: cada gravação vai para um novo caminho, a menos que você escolha explicitamente overwrite. Nada sai da máquina e não há chave de API para obter.

spreadsheet demo

Leia, consulte e estenda planilhas reais a partir do chat sem nunca tocar no arquivo original.

Instalação em 60 segundos

A publicação no npm para @theluckystrike/mcp-spreadsheet está pendente. Até lá, o pacote de um clique .mcpb ou um clone + build é o caminho funcional — ambos verificados abaixo.

Um clique (.mcpb): baixe spreadsheet.mcpb do lançamento mais recente e clique duas vezes nele no 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"]
    }
  }
}

O formulário npx acima começa a funcionar no momento em que o pacote for publicado. Até lá, use o pacote .mcpb acima, ou compile a partir do código-fonte com exatamente estes três 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

Em seguida, aponte o command do seu cliente para node com um argumento: o caminho absoluto para servers/spreadsheet/dist/index.js.

Para executar no modo Pro, defina MCP_LICENSE_KEY no mesmo bloco de configuração, ou chame license_activate uma vez com sua chave.

Ferramentas

FerramentaO que ela faz
sheet_infoNomes das planilhas, tamanho, linha de cabeçalho adivinhada, tipo por coluna, valores de amostra, contagens de células vazias
sheet_readLê linhas como tabela de texto, registros JSON ou CSV; paginação limit/offset ou um range A1
sheet_queryFiltra com where, group_by + aggregate (soma, contagem, média, mínimo, máximo), seleciona colunas com select, sort (também aliases de agregação), limit
sheet_statscontagem, vazio, distinto, mínimo, máximo, soma, média, mediana por coluna (valores principais para colunas de texto)
sheet_findEncontra texto em qualquer lugar da pasta de trabalho; retorna endereços de células e uma prévia da linha
sheet_writeEscreve linhas (objetos ou arrays) como um novo arquivo, uma adição ou uma sobrescrita explícita
sheet_add_columnAdiciona uma coluna calculada a partir de uma fórmula, salva em um novo arquivo. Resultados numéricos são arredondados como suas entradas (2 decimais na entrada, 2 decimais na saída); decimals substitui
sheet_convertConverte uma planilha para csv, xlsx ou json
license_statusGratuito ou Pro, e onde atualizar
license_activateAtiva uma chave Pro (verificada offline)

Modelo de recurso: sheet://<path> retorna o resumo sheet_info para esse arquivo. Recurso: sheet://recent lista os arquivos que este servidor abriu desde que iniciou, mais recentes primeiro (somente em memória — nada é gravado em disco, então a lista fica vazia novamente após uma reinicialização).

Prompt: explore_sheet percorre um arquivo desconhecido — sheet_info primeiro, depois chamadas concretas de sheet_query construídas a partir das colunas que ele realmente encontrou.

O que você pode dizer

Você dizFerramenta
"Abra sales.xlsx e me diga o que há nele."sheet_info
"Mostre-me as primeiras 50 linhas."sheet_read
"Qual representante vendeu mais unidades na região Norte? Top 5 com totais."sheet_query (group_by + aggregate)
"Quantas células vazias há na coluna Email, e qual é o tamanho mediano do pedido?"sheet_stats
"Encontre todas as linhas que mencionam 'reembolso'."sheet_find
"Escreva isso como uma nova planilha chamada Resultados Q3."sheet_write
"Adicione uma coluna Receita que seja Unidades vezes Preço Unitário, salve como CSV ao lado do original."sheet_add_column
"Converta este xlsx para JSON."sheet_convert
"Estou no plano gratuito ou Pro?"license_status
"Aqui está minha chave de licença, ative-a."license_activate

Exemplo prático

De docs/USER_VALUE_R2.md, um fixture de 400 linhas com uma linha de título e uma linha em branco acima do cabeçalho real (linha 3), planilhas Sales / Reps / Notes, preços armazenados como strings como "1,516.16". Uma chamada, verdade confirmada contra o gerador: 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

A resposta agora ecoa a consulta exata que foi executada (a linha Query:) antes dos números, então um filtro que você não pediu — um AND [Status] = "Closed" acidental, por exemplo — fica visível em vez de silenciosamente estreitar a resposta.

Um segundo exemplo, adicionando uma coluna e salvando sem tocar na fonte:

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.

A linguagem where e formula

Uma pequena linguagem de expressão, analisada e avaliada diretamente. Não há eval e nenhuma execução de código: uma palavra simples é sempre um nome de coluna, nunca um valor JavaScript.

  • Colunas: [Unit Price] para nomes com espaços, Qty caso contrário. A busca não diferencia maiúsculas de minúsculas.
  • Comparações: = != > >= < <= contains startswith endswith
  • Lógica: AND OR NOT e parênteses. AND liga mais forte que OR.
  • Aritmética em fórmulas: + - * % / com a precedência usual.
  • Strings: aspas 'single' ou "double"; dobre uma aspas para escapá-la.
[Qty] >= 5 AND ([Status] = "open" OR [Region] contains "north")
[Amount] > 1000 AND NOT [Customer] startswith 'Test'

Exemplo de fórmula para sheet_add_column: [Qty] * [Unit Price]. Quando cada coluna que a fórmula lê tem no máximo 2 decimais, o resultado é arredondado para 2 decimais, então [Amount] * 1.23 em dinheiro dá 40.79 em vez de 40.7868. Passe decimals (0-10) para escolher a precisão você mesmo.

Números escritos como texto em um CSV são convertidos por padrão, não por comprimento: 1250.00, 12.00 e 1,250.00 todos se tornam números na saída xlsx, então a própria SUM do Excel os conta. Valores com formato de identificador e ambíguos permanecem texto: 007 mantém seus zeros à esquerda e 1.250,00 é deixado como está em vez de ser adivinhado.

Comparações de texto ignoram maiúsculas/minúsculas e espaços ao redor. Valores como $1,250.00, 1 250 e 12% comparam como números, então [Amount] > 1000 funciona em uma coluna que sua planilha armazenou como texto.

Gratuito vs Pro

GratuitoPro
Toda ferramenta que lê um arquivo (sheet_info, sheet_read, sheet_query, sheet_stats, sheet_find, sheet_add_column, sheet_convert)Arquivos até 5 MB e 5.000 linhasSem limite (até o teto de 50 MB de arquivo)
sheet_write, sheet_add_column, sheet_convertAté 500 linhas gravadas por arquivo; acima disso nada é gravado e a ferramenta informaSem limite
Planilhas, formatos, linguagem de expressãoTudoTudo

Acima do limite gratuito de leitura, a ferramenta ainda faz o trabalho e retorna a parte que tem permissão para retornar (as primeiras 5.000 linhas), com uma nota dizendo o que foi omitido. Acima do limite gratuito de gravação, nada é gravado: um arquivo parcial que parece completo é pior do que nenhum arquivo, então a ferramenta recusa, informa a contagem de linhas e o limite, e sugere uma solução gratuita (filtre as linhas primeiro ou grave em lotes de 500 linhas). Nada falha silenciosamente.

Obtenha o Pro

$19 pagamento único para este servidor, $39 para todos os servidores, vitalício: https://mcp.zovo.one/buy/spreadsheet

Como ele armazena dados

Este servidor não mantém banco de dados próprio — ele lê e grava os arquivos de planilha para os quais você o aponta, diretamente no seu disco, e nada mais. Cada gravação (sheet_write, sheet_add_column, sheet_convert no modo overwrite) vai primeiro para um arquivo temporário no mesmo diretório e depois é renomeada para o lugar, então uma gravação interrompida deixa ou o original intocado ou o novo arquivo completo, nunca um truncado. Como não há arquivo de estado compartilhado, não há bloqueio consultivo a tomar: duas chamadas gravando em dois caminhos de saída diferentes não podem colidir, e uma chamada para overwrite o mesmo arquivo duas vezes seguidas é simplesmente duas gravações em sequência. Para fazer backup dos seus dados, faça backup dos próprios arquivos de planilha — não há nada mais para copiar.

Limites e ressalvas honestas

  • Leituras gratuitas limitam a 5.000 linhas e 5 MB; gravações gratuitas limitam a 500 linhas por arquivo e recusam em vez de truncar — você recebe um erro nomeando a contagem de linhas e o limite, nunca um arquivo mais curto que pareça completo.
  • O teto rígido é 50 MB independentemente do nível; um arquivo acima disso é recusado diretamente com uma mensagem clara em vez de arriscar esgotamento de memória.
  • A linguagem where/formula é intencionalmente pequena: sem expressões regulares, sem funções personalizadas, sem referências entre planilhas em uma única fórmula. Ela cobre comparações, lógica booleana e aritmética, nada mais.
  • Gravar um xlsx substitui uma planilha, não a pasta de trabalho. sheet_write com append ou overwrite lê a pasta de trabalho inteira, troca a planilha que você nomeou e grava todas as outras planilhas de volta, então Sheet2 e seus dados sobrevivem a uma adição em Sheet1. O que não é preservado é a planilha sendo gravada: ela é reconstruída a partir de valores, então fórmulas, formatação de células, formatação condicional, gráficos, validação de dados e células mescladas nessa única planilha se tornam valores simples. Outras planilhas mantêm suas células como foram lidas. Faça uma cópia primeiro se a planilha de destino tiver formatação que você não pode recriar.
  • Números escritos como texto são lidos com regras sensíveis à localidade. 1,250.00, 1 250.00, $1,250.00, 12,99, 1.234,56 e EUR 1 250,00 todos são lidos como números; uma vírgula decimal só é aceita na forma inequívoca (uma vírgula com exatamente dois dígitos no final, pontos ou espaços agrupando). Qualquer coisa que misture separadores de outra forma (1,2500.00) permanece texto em vez de ser adivinhada. Valores com zeros à esquerda (007) e inteiros grandes demais para aritmética exata (acima de 9.007.199.254.740.991) permanecem texto para nunca serem alterados silenciosamente.
  • Datas mantêm seu tipo de célula. Uma célula de data lida de um xlsx permanece uma data através de consultas e através de uma conversão de volta para xlsx. Em texto, saída CSV e JSON, ela é renderizada como ISO: 2026-09-04 para uma data, 2026-09-03T15:30:00 quando a célula carrega uma hora.
  • A adivinhação de linha de cabeçalho do sheet_info é uma heurística (procura a primeira linha com menor vazio e maior densidade de texto do que as linhas acima dela). Ela lida com uma linha de título e uma linha em branco acima do cabeçalho; não é à prova de todos os layouts, e você sempre pode confirmar o que ela escolheu antes de consultar.

Solução de problemas

  • npx trava ou não encontra o pacote: a publicação do npm para este pacote está pendente. Use o pacote .mcpb ou o caminho de clonagem e compilação acima até que ele seja publicado.
  • Usando o pacote .mcpb: ele instala diretamente no Claude Desktop; não há etapa de configuração separada.
  • Usando o caminho de clonagem: o binário do servidor é servers/spreadsheet/dist/index.js após npm run build. Aponte o command do seu cliente para node com esse caminho absoluto como único argumento.
  • Versão do Node: requer Node >= 18. Verifique com node -v.
  • "Caminho não existe": a mensagem inclui o caminho absoluto resolvido (com ~ expandido) — verifique se ele corresponde ao local real do arquivo, especialmente dentro de um cliente em sandbox ou containerizado.
  • Uma gravação é recusada com uma mensagem de contagem de linhas: você atingiu o limite gratuito de 500 linhas de gravação. Filtre os dados com sheet_query primeiro, grave em lotes ou ative o Pro.
  • Nada aparece / falhas silenciosas: os logs vão apenas para stderr, nunca para stdout. No Claude Desktop, verifique Configurações -> Desenvolvedor -> o arquivo de log do servidor; no Claude Code, verifique o terminal ou --mcp-debug.

Segurança

  • Caminhos que não existem são recusados com o caminho resolvido na mensagem; ~ é expandido.
  • Arquivos acima de 50 MB são recusados com uma mensagem clara, em vez de esgotar a memória.
  • sheet_add_column e sheet_convert gravam em um novo arquivo e recusam sobrescrever um existente, a menos que você passe out_path você mesmo.
  • sheet_write com mode: "new_file" recusa sobrescrever um arquivo existente. Apenas mode: "overwrite" substitui o conteúdo do arquivo.
  • Os arquivos de saída são gravados com um nome temporário e renomeados para o local final, então uma gravação interrompida não pode truncar um arquivo.

Privacidade

Todos os dados permanecem locais. Os arquivos são lidos e gravados no seu próprio disco, as chaves de licença são verificadas offline com uma chave pública incorporada, e o servidor não faz nenhuma solicitação de rede.

Combina com

FAQ

Ele lida com uma planilha que tem uma linha de título acima dos cabeçalhos? Sim. sheet_info adivinha a linha de cabeçalho e informa qual linha escolheu, então uma exportação com uma linha de título e uma linha em branco acima dos cabeçalhos reais abre corretamente sem que você especifique nada.

Ele pode agrupar e somar, ou apenas filtrar? Ele agrupa. sheet_query aceita group_by mais aggregate com soma, contagem, média, mínimo ou máximo, e pode ordenar por um alias de agregação, então perguntas de top-N-por-categoria são uma única chamada.

Ele vai sobrescrever meu arquivo original? Não, a menos que você passe explicitamente um caminho de saída que aponte para a origem. sheet_add_column e sheet_convert gravam um novo arquivo ao lado do original por padrão.

O que acontece no plano gratuito com um arquivo maior que o limite? As leituras retornam as primeiras 5.000 linhas com uma nota indicando o que foi omitido. Gravações acima de 500 linhas são recusadas diretamente, em vez de produzir um arquivo truncado, e a mensagem informa a contagem de linhas, o limite e uma forma gratuita de contornar.

Meus dados são enviados para algum lugar? Não. O servidor roda localmente na sua máquina e lê seus arquivos diretamente. Ele não faz solicitações de rede e não armazena nada próprio além dos arquivos que você pede para gravar.

Criado por theluckystrike. Suporte: support@zovo.one