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.

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
| Ferramenta | O que ela faz |
|---|---|
sheet_info | Nomes das planilhas, tamanho, linha de cabeçalho adivinhada, tipo por coluna, valores de amostra, contagens de células vazias |
sheet_read | Lê linhas como tabela de texto, registros JSON ou CSV; paginação limit/offset ou um range A1 |
sheet_query | Filtra 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_stats | contagem, vazio, distinto, mínimo, máximo, soma, média, mediana por coluna (valores principais para colunas de texto) |
sheet_find | Encontra texto em qualquer lugar da pasta de trabalho; retorna endereços de células e uma prévia da linha |
sheet_write | Escreve linhas (objetos ou arrays) como um novo arquivo, uma adição ou uma sobrescrita explícita |
sheet_add_column | Adiciona 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_convert | Converte uma planilha para csv, xlsx ou json |
license_status | Gratuito ou Pro, e onde atualizar |
license_activate | Ativa 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ê diz | Ferramenta |
|---|---|
| "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,Qtycaso contrário. A busca não diferencia maiúsculas de minúsculas. - Comparações:
=!=>>=<<=containsstartswithendswith - Lógica:
ANDORNOTe parênteses.ANDliga mais forte queOR. - 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
| Gratuito | Pro | |
|---|---|---|
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 linhas | Sem limite (até o teto de 50 MB de arquivo) |
sheet_write, sheet_add_column, sheet_convert | Até 500 linhas gravadas por arquivo; acima disso nada é gravado e a ferramenta informa | Sem limite |
| Planilhas, formatos, linguagem de expressão | Tudo | Tudo |
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_writecomappendouoverwritelê a pasta de trabalho inteira, troca a planilha que você nomeou e grava todas as outras planilhas de volta, entãoSheet2e seus dados sobrevivem a uma adição emSheet1. 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,56eEUR 1 250,00todos 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-04para uma data,2026-09-03T15:30:00quando 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
npxtrava ou não encontra o pacote: a publicação do npm para este pacote está pendente. Use o pacote.mcpbou 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.jsapósnpm run build. Aponte ocommanddo seu cliente paranodecom 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_queryprimeiro, 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_columnesheet_convertgravam em um novo arquivo e recusam sobrescrever um existente, a menos que você passeout_pathvocê mesmo.sheet_writecommode: "new_file"recusa sobrescrever um arquivo existente. Apenasmode: "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
- mcp-time-tracker — exporte um CSV com
export_csve depois consulte e reformate aqui. - mcp-invoice — extraia itens de linha de uma planilha antes de transformá-los em uma fatura.
- mcp-price-tracker — analise o histórico de preços exportado como uma planilha.
- office-suite — todos os quatro servidores em uma única instalação, uma entrada de configuração.
- Guia: Faça perguntas sobre um arquivo Excel ou CSV do Cursor ou Claude
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