Zovo Spreadsheet MCP Server

Create and edit spreadsheets with AI agents: tables, formulas, exports to xlsx and CSV. Local-first, free tier, $19 one-time Pro.

Documentation

All servers · Buy Pro $19 · All 46 for $39 · Source

Two ways to run it, both free to start. Open mcp.zovo.one/mcp/connect, copy the spreadsheet URL and paste it into any client that takes a URL. It already carries a free token, so there is nothing to install, no account and no header to set. The URL is https://mcp.zovo.one/mcp/spreadsheet/t/<token>. The token is not optional: the bare https://mcp.zovo.one/mcp/spreadsheet connects and lists its tools and then answers every tool call with HTTP 401, so use the link from /mcp/connect or send Authorization: Bearer <token>. Or download spreadsheet.mcpb and double-click it in Claude Desktop.

mcp-spreadsheet

Featured on Awesome MCP Servers — directory listing | live hosted endpoint, free tier, no signup.

Hand your AI assistant a spreadsheet and talk to it. Point it at any .xlsx, .xlsm, .xlsb, .xls, .ods, .csv or .tsv file on your machine and ask what is in it, filter it, compute a new column, or save it in another format. It handles the messy parts of real files for you: it guesses which row holds the headers, sniffs whether a CSV is separated by commas, semicolons or tabs, keeps quoted commas and newlines intact, reads numbers out of $1,250.00 style text, and reports per-column types and empty counts. It never edits your original file: every write goes to a new path unless you explicitly choose overwrite. Nothing leaves the machine, and there is no API key to get.

In the official MCP Registry (io.github.theluckystrike/excel-spreadsheet-xlsx-csv).

Listed on the AI Product Index — live remote endpoint at mcp.zovo.one/s/spreadsheet, free tier, no signup.

spreadsheet demo

Read, query and extend real spreadsheets from chat without ever touching the original file.

60-second install

npm publish for @theluckystrike/mcp-spreadsheet is pending. Until then, the .mcpb one-click bundle or a clone+build is the working path, both are verified below.

One-click (.mcpb): download spreadsheet.mcpb from the latest release and double-click it in Claude Desktop: https://github.com/theluckystrike/mcp-servers/releases/latest

(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/mcp.json):

{
  "mcpServers": {
    "spreadsheet": {
      "command": "npx",
      "args": ["-y", "@theluckystrike/mcp-spreadsheet"]
    }
  }
}

The npx form above starts working the moment the package is published. Until then, use the.mcpb bundle above, or build from source with exactly these three commands:

git clone https://github.com/theluckystrike/mcp-servers.git && cd mcp-servers
npm install
npm run build -w packages/mcp-license -w servers/spreadsheet

Then point your client's command at node with one arg: the absolute path to servers/spreadsheet/dist/index.js.

To run in Pro mode set MCP_LICENSE_KEY in the same config block, or call license_activate once with your key.

Tools

ToolWhat it does
sheet_infoSheet names, size, guessed header row, per-column type, sample values, empty counts
sheet_readRead rows as a text table, JSON records or CSV; limit / offset paging or an A1 range
sheet_queryFilter with where, group_by + aggregate (sum, count, avg, min, max), pick columns with select, sort (aggregate aliases too), limit
sheet_statscount, empty, distinct, min, max, sum, mean, median per column (top values for text columns)
sheet_findFind text anywhere in the workbook; returns cell addresses and a row preview
sheet_writeWrite rows (objects or arrays) as a new file, an append, or an explicit overwrite
sheet_add_columnAdd a computed column from a formula, saved to a new file. Numeric results are rounded like their inputs (2 decimals in, 2 decimals out); decimals overrides
sheet_convertConvert a sheet to csv, xlsx or json
license_statusFree or Pro, and where to upgrade
license_activateActivate a Pro key (verified offline)

Resource template: sheet://<path> returns the sheet_info summary for that file. Resource: sheet://recent lists the files this server has opened since it started, most recent first (in memory only, nothing is written to disk, so the list is empty again after a restart).

Prompt: explore_sheet walks an unfamiliar file, sheet_info first, then concrete sheet_query calls built from the columns it actually found.

What you can say

You sayTool
"Open sales.xlsx and tell me what's in it."sheet_info
"Show me the first 50 rows."sheet_read
"Which rep sold the most units in the North region? Top 5 with totals."sheet_query (group_by + aggregate)
"How many empty cells are in the Email column, and what's the median order size?"sheet_stats
"Find every row that mentions 'refund'."sheet_find
"Write this as a new sheet called Q3 Results."sheet_write
"Add a Revenue column that's Units times Unit Price, save it as a CSV next to the original."sheet_add_column
"Convert this xlsx to JSON."sheet_convert
"Am I on the free plan or Pro?"license_status
"Here's my license key, activate it."license_activate

Worked example

From docs/USER_VALUE_R2.md, a 400-row fixture with a title row and a blank row above the real header (row 3), sheets Sales / Reps / Notes, prices stored as strings like "1,516.16". One call, ground truth confirmed against the generator: 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

The response now echoes the exact query it ran (the Query: line) before the numbers, so a filter you did not ask for, an accidental AND [Status] = "Closed", say, is visible instead of silently narrowing the answer.

A second example, adding a column and saving without touching the source:

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.

The where and formula language

A small expression language, parsed and evaluated directly. There is no eval and no code execution: a bare word is always a column name, never a JavaScript value.

  • Columns: [Unit Price] for names with spaces, Qty otherwise. Lookup is case insensitive.
  • Comparisons: = != > >= < <= contains startswith endswith
  • Logic: AND OR NOT and parentheses. AND binds tighter than OR.
  • Arithmetic in formulas: + - * % / with the usual precedence.
  • Strings: 'single' or "double" quotes; double a quote to escape it.
[Qty] >= 5 AND ([Status] = "open" OR [Region] contains "north")
[Amount] > 1000 AND NOT [Customer] startswith 'Test'

Formula example for sheet_add_column: [Qty] * [Unit Price]. When every column the formula reads holds at most 2 decimals, the result is rounded to 2 decimals, so [Amount] * 1.23 on money gives 40.79 rather than 40.7868. Pass decimals (0-10) to choose the precision yourself.

Numbers written as text in a CSV are converted by pattern, not by length: 1250.00, 12.00 and 1,250.00 all become numbers in the xlsx output, so Excel's own SUM counts them. Identifier-shaped and ambiguous values stay text: 007 keeps its leading zeros and 1.250,00 is left alone rather than guessed at.

Text comparisons ignore case and surrounding whitespace. Values like $1,250.00, 1 250, and 12% compare as numbers, so [Amount] > 1000 works on a column your spreadsheet stored as text.

Free vs Pro

FreePro
Every tool that reads a file (sheet_info, sheet_read, sheet_query, sheet_stats, sheet_find, sheet_add_column, sheet_convert)Files up to 5 MB and 5,000 rowsNo limit (up to the 50 MB file ceiling)
sheet_write, sheet_add_column, sheet_convertUp to 500 rows written per file; over that nothing is written and the tool says soNo limit
Sheets, formats, expression languageAllAll

Over a free read limit the tool still does the work and returns the part it is allowed to return (the first 5,000 rows), with a note saying what was left out. Over the free write limit nothing at all is written: a partial file that looks complete is worse than no file, so the tool refuses, tells you the row count and the cap, and suggests a free workaround (filter the rows down first, or write in 500-row batches). Nothing fails silently.

Get Pro

$19 one-time for this server, $39 for every server, lifetime: https://mcp.zovo.one/buy/spreadsheet Or the 46-server bundle for $39.

How it stores data

This server keeps no database of its own, it reads and writes the spreadsheet files you point it at, directly on your disk, and nothing else. Every write (sheet_write, sheet_add_column, sheet_convert in overwrite mode) goes to a temporary file in the same directory first, then is renamed into place, so an interrupted write leaves either the untouched original or the complete new file, never a truncated one. Because there is no shared state file, there is no advisory lock to take: two calls writing to two different output paths cannot collide, and a call to overwrite the same file twice in a row is simply two writes in sequence. To back up your data, back up the spreadsheet files themselves, there is nothing else to copy.

Limits and honest caveats

  • Free reads cap at 5,000 rows and 5 MB; free writes cap at 500 rows per file and refuse rather than truncate, you get an error naming the row count and the cap, never a shorter file that looks complete.
  • The hard ceiling is 50 MB regardless of tier; a file over that is refused outright with a clear message rather than risking memory exhaustion.
  • The where / formula language is intentionally small: no regular expressions, no custom functions, no cross-sheet references in a single formula. It covers comparisons, boolean logic and arithmetic, nothing more.
  • Writing an xlsx replaces one sheet, not the workbook. sheet_write with append or overwrite reads the whole workbook, swaps the sheet you named and writes every other sheet back, so Sheet2 and its data survive an append to Sheet1. What is not preserved is the sheet being written: it is rebuilt from values, so formulas, cell formatting, conditional formatting, charts, data validation and merged cells on that one sheet become plain values. Other sheets keep their cells as read. Take a copy first if the target sheet carries formatting you cannot recreate.
  • Numbers written as text are read with locale-aware rules. 1,250.00, 1 250.00, $1,250.00, 12,99, 1.234,56 and EUR 1 250,00 all read as numbers; a decimal comma is only accepted in the unambiguous shape (a comma with exactly two digits at the end, dots or spaces grouping). Anything that mixes separators another way (1,2500.00) stays text rather than being guessed at. Values with leading zeros (007) and integers too large for exact arithmetic (over 9,007,199,254,740,991) stay text so they are never silently altered.
  • Dates keep their cell type. A date cell read from an xlsx stays a date through queries and through a conversion back to xlsx. In text, CSV and JSON output it is rendered as ISO: 2026-09-04 for a date, 2026-09-03T15:30:00 when the cell carries a time.
  • sheet_info 's header-row guess is a heuristic (looks for the first row with lower emptiness and higher text density than the rows above it). It handles a title row and a blank row above the header; it is not proof against every layout, and you can always confirm what it picked before querying.

Troubleshooting

  • npx hangs or fails to find the package: npm publish for this package is pending. Use the .mcpb bundle or the clone-and-build path above until it lands.
  • Using the .mcpb bundle: it installs into Claude Desktop directly; there is no separate config step.
  • Using the clone path: the server binary is servers/spreadsheet/dist/index.js after npm run build. Point your client's command at node with that absolute path as the only argument.
  • Node version: requires Node >= 18. Check with node -v.
  • "Path does not exist": the message includes the resolved absolute path (with ~ expanded), check it against where the file actually lives, especially inside a sandboxed or containerized client.
  • A write is refused with a row-count message: you hit the free 500-row write cap. Filter the data down with sheet_query first, write in batches, or activate Pro.
  • Nothing shows up / silent failures: logs go to stderr only, never stdout. In Claude Desktop check Settings -> Developer -> the server's log file; in Claude Code check the terminal or --mcp-debug.

Safety

  • Paths that do not exist are refused with the resolved path in the message; ~ is expanded.
  • Files over 50 MB are refused with a clear message rather than exhausting memory.
  • sheet_add_column and sheet_convert write to a new file and refuse to clobber an existing one unless you pass out_path yourself.
  • sheet_write with mode: "new_file" refuses to write over an existing file. Only mode: "overwrite" replaces file contents.
  • Output files are written to a temporary name and renamed into place, so an interrupted write cannot truncate a file.

Privacy

All data stays local. Files are read from and written to your own disk, license keys are verified offline with an embedded public key, and the server makes no network requests at all.

Pairs with

FAQ

Yes. sheet_info guesses the header row and reports which row it picked, so an export with a title line and a blank line above the real headers opens correctly without you specifying anything.

It groups. sheet_query takes group_by plus aggregate with sum, count, avg, min or max, and can sort by an aggregate alias, so top-N-by-category questions are a single call.

No, not unless you explicitly pass an output path that points at the source. sheet_add_column and sheet_convert write a new file next to the original by default.

Reads return the first 5,000 rows with a note naming what was omitted. Writes over 500 rows are refused outright rather than producing a truncated file, and the message tells you the row count, the cap and a free way round.

No. The server runs locally on your machine and reads your files directly. It makes no network requests, and it stores nothing of its own beyond the files you ask it to write.

Built by theluckystrike. Support: support@zovo.one

First five minutes

Three prompts that scored 3 of 3, measured in round 14, 2026-09-04. Paste one in as it is written.

Here is a CSV of my August sales. Load it as sales. [357-byte CSV pasted]

Paste this into Claude with the server connected.

What it did, measured in round 14, 2026-09-04: One sheet_load {name, csv} through the sheet-load shim.

Describe that sheet: columns, row count, and what type each column is.

Paste this into Claude with the server connected.

What it did, measured in round 14, 2026-09-04: One sheet_info: 8 rows x 6 cols, 7 data rows, six typed columns (date/text/number) with samples and an empty-cell count each.

Show me only the rows where the amount is over 500, highest first.

Paste this into Claude with the server connected.

What it did, measured in round 14, 2026-09-04: One sheet_query {where: '[amount] > 500', sort desc}.

On the free tier for this path: Read, query (filters, group by, sum/avg/min/max), stats and find on files up to 5,000 rows; writes up to 500 rows, never a partial file above that.

Set it up in your client

Exact config path, entry and caveats: Claude Desktop · Claude Code · Cursor · VS Code · Windsurf · Cline · Claude.ai and Claude Desktop connectors · all clients

Compared with the alternatives

MCP Spreadsheet vs agent-spreadsheet and mcp-server-spreadsheet - which MCP server to pick · all comparisons

Guides

How to track billable hours inside Claude Code and Cursor · Create an invoice PDF from a chat message with an MCP server · Ask questions about an Excel or CSV file from Cursor or Claude · Watch a product price with Claude and get told when it drops · What the free tier includes and what Pro adds · Log expenses and mileage in Claude, split VAT, rebill to an invoice · Convert currencies in Claude with real ECB rates, no API key · Generate Word proposals and contracts from a chat message · Find a meeting time across time zones without doing the arithmetic · Write a resume and a cover letter from chat, without inventing anything · Bill a retainer on a schedule without a billing SaaS · Assemble a contract from your own clause library, in chat · Connect MCP servers to Claude.ai, Claude Desktop, Cursor and VS Code without installing anything · Merge, split and stamp PDFs from chat, and why some come back as glyph numbers · Read a.ics calendar in Claude: free and busy, conflicts, and billable meetings · Run a kanban board in Claude, with time tracking on the same task · Resize, compress and watermark images from a chat message · Categorize and reconcile a bank CSV export from chat · Send a quote from chat, then turn the yes into an invoice · Put a SEPA payment QR code on an invoice from chat · Zip and unzip archives safely from Claude or Cursor · Client deposits and retainers from chat, applied to your real invoices · Fixed assets and depreciation from chat, on the rates the tax authorities publish · Per diem and travel allowances from chat, on the rate tables the tax authorities publish · One double-entry ledger out of every server you already run · Loan and lease schedules from chat, closing exactly on zero · Work orders and job cards from chat, and why the markup goes on the unit cost · Price lists and rate cards from chat, and the 100x scale gap between the invoice and the quote · Change orders and the running contract value from chat, and why a changed line is two items · A petty cash float from chat, and why the cheque is not the sum of the vouchers · Client statements and payment chasers from chat, aged as at any date you name · Credit notes and purchase orders from chat, against your real invoices · One install, every server: the office-suite bundle · Close a month in chat: invoice, credit note, retainer, bank reconciliation, statement · MCP server not showing up in Claude Desktop: the six checks that find it · Where is claude_desktop_config.json, and what goes in it · claude mcp add: every flag, and the scope that silently loses your server · MCP servers on Windows: spawn npx ENOENT, backslashes and the PATH · Installing these MCP servers when npx does not work yet · Cursor MCP setup: mcp.json, the required type field, and where the servers appear · Which MCP servers work with no network at all · Invoicing an EU client with reverse charge, from a chat message · Quote, deposit, invoice, statement: the whole cycle in one conversation · Is this project making money? Hours against costs, without a spreadsheet · Building a tax year pack for your accountant from chat · Keeping a mileage log in chat, with the rate you actually claim · Reconciling a bank CSV against what you invoiced and spent · Rebilling client expenses, with a markup and the VAT handled honestly · Chasing an unpaid invoice: aging, then the letter · A bill of sale from chat, with the identifiers checked and the signature lines printed · Pricing a job from a rate card, and what to do when the scope changes · Working out your hourly rate from what you actually billed · Converting CSV to xlsx and back without opening Excel · Asking a spreadsheet questions in plain language · Merging a folder of receipts into one PDF from chat · Splitting one big scan into separate documents · Sending a month of paperwork as one archive, safely · MCP servers in VS Code: the one-word mistake that breaks every config · MCP servers in Windsurf and Cline: two defaults that waste an afternoon · Local MCP server or hosted URL: which one, and what you give up · What these MCP servers actually do on the free tier · Choosing an MCP server for invoicing: the seven questions worth asking · When you need an MCP server, and when a prompt is enough · MCP config file locations and JSON keys, every client · Why an MCP server does not appear, in order of likelihood · How MCP registry search actually works, measured · What is actually in the MCP registry: 6,000 rows counted · stdio or streamable HTTP: which MCP transport, and what breaks · MCP protocol versions: what each one changed · Every field in an MCP server config entry, by client · MCP config scopes: which definition wins when a server is defined twice · Where each MCP client writes its logs · Shipping an MCP server: a bundle to download or a URL to paste · What is inside a.mcpb MCP bundle · Charging for an MCP server: how licensing actually works · How much text an MCP server may return, and how much it may describe · What to check before letting an MCP server run · Why a directory says your hosted MCP server is not responding · The MCP registry binds one remote URL to one server name · Capital letters in your GitHub username change your MCP registry rank · How many MCP servers already have your word in the name · server.json field reference for the MCP registry · When an MCP tool fails, do not return a JSON-RPC error · structuredContent and outputSchema in MCP, and what MUST hold · Rules for naming an MCP tool, and the collision nobody plans for · MCP has no session, so how do two tool calls share state · x-mcp-header: mirroring tool parameters into HTTP headers · How a directory scores an MCP server, and why your worst tool decides it · What AI crawlers fetch that Googlebot does not, measured on 141 URLs · Search Console's URL Inspection API changes its answer between calls · Which MCP servers work by pasting a URL, with nothing installed · Where to find MCP servers that cost money, and how you actually pay · Getting an assistant to fill in a quote or estimate for a customer · Is there an MCP server for a petty cash book or a cash ledger · Currency conversion in an assistant, and which MCP server to use · Zipping and unzipping archives from an assistant, and what the guards do · Producing a delivery schedule or a work order document from a chat · Will an MCP server email the invoice to my client · Can an assistant read a photo of a receipt and log the expense · Which MCP server can generate invoice PDFs from a chat message? · Can an MCP server read a bank statement PDF and categorise the transactions? · Best MCP servers for small business accounting and paperwork in 2026 · MCP Supplier Directory: keep supplier lists from rotting in a spreadsheet · MCP Service Agreement: stop copying a rotting contract template off the internet · MCP Maintenance Log: know what service is due without anyone remembering · MCP Mileage Log: keep the deductible log at the moment of the drive, not in April · Invoice payment terms best practices: Net 30, due date and late fees · How to categorize bank transactions · Petty cash log template · Ask questions about a spreadsheet in chat, no formulas needed · Turn a quote or estimate into an invoice without retyping it · Produce a delivery schedule and a work order from a chat · Use MCP servers without installing anything, by pasting a URL · MCP servers for small business accounting: the roundup · How to find and pay for MCP servers · Track billable hours as timesheet entries instead of a wall-clock timer · Convert a CSV into JSON for an API import or a dev tool · Build an NDA or mutual confidentiality agreement from clauses · Make a packing list or delivery note from the order in chat · Run a stock count with barcodes and update the catalogue in chat · Merge PDF files in Claude or Cursor without uploading them anywhere · Split a PDF into separate documents from the chat window · Track expenses and budgets inside Claude without a SaaS subscription · Run pomodoro focus sessions from Claude and bill the hours after · Track product prices and get drop alerts from your AI chat · Track billable time and export timesheets from your AI chat · Keep invoice numbers sequential and never reuse one · All guides

More servers

MCP Timezone Planner · MCP Resume and Cover Letter · MCP Recurring Invoices · MCP Clause Library · MCP Calendar · MCP PDF Server — Merge, Split, Fill Forms · MCP Image Tools · MCP Bank Statement