Atlas / MCP servers / senoff / xlsx-for-ai

xlsx-for-aiBLOCK

mcp/senoff/xlsx-for-ai

MCP server + CLI giving AI agents 50 spreadsheet tools for .xlsx — live-recalc formulas (~390 Excel functions), repair broken references & external links, read/write, diff, and audit. Works in Claude Code, Cursor, Codex, and any MCP client.

Verdict
BLOCK
Grade
D
Trust score
61 /100
Exposed tools
55 50r · 4w · 1d
Transport
stdio
License
MIT
Stars
6
01

Overview

From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.

[](https://glama.ai/mcp/servers/senoff/xlsx-for-ai)

Short name: xfa — a real CLI command (`xfa `, `xfa samples`, `xfa --version`) and the prompt shorthand (e.g. "use xfa to read this file"). Same entrypoint as `xlsx-for-ai`; matches the internal `xfa_ / XFA_` brand surface.

Verified values, preserved structure, up to 100MB

The missing reliability layer for spreadsheet work in LLM agents. Read, write, diff, validate, and analyze .xlsx files end-to-end — with merged cells, formulas, named ranges, conditional formatting, pivots, and charts preserved.

xlsx-for-ai makes Claude reliable on real-world Excel files. Forty-plus tools cover the structural surface that pandas-style sandboxes drop on the floor: merged cells, named ranges, formulas with results, conditional formatting, pivots, slicers, charts, comments, data validations, hyperlinks, cross-sheet topology, external links, form controls, VBA macros, document properties, and protection settings. A soundness check (xlsx_validate) flags corruption other readers silently mask. A hosted recalc engine computes served values in-house — no third-party formula engine in the serve path.

npm install -g xlsx-for-ai

The global install puts the xlsx-for-ai-mcp binary on your PATH — that's what the canonical configs below point at. A pinned global install launches fast (it still needs an internet connection, because the files are read by the hosted service); upgrade with npm install -g xlsx-for-ai@latest when a new version ships.

Upgrading from 1.5.x? This is a re-architecture, not a feature bump: the heavy local engine is gone from the npm package. All rendering happens server-side. The cursor-reads-xlsx alias still works. See Migration below.

MCP configuration

Add the server to your agent runtime under the name `xfa` (so "use xfa to rea

Read from source at commit fc3294919ea1OBSERVED · 2026-10-10
02

Connect

Built from this server's own package name, version and transport as found in its source — not copied from anyone's documentation, so it cannot drift against a page we do not control. Replace the environment placeholders with a token scoped to the least it needs.

claude-code (npm)
claude mcp add xlsx-for-ai -- npx -y [email protected]
03

Exposed tools (55)

50 read · 4 write · 1 destructive. Blast radius: 1 tool can delete or overwrite — an agent that can be talked into calling a tool can be talked into calling this one.

ToolRiskDescription
server_only_pingreadNo file.
xlsx_aggregatereadpandas-style df.groupby([cols]).agg({col: func}) on a LOCAL .xlsx file. funcs: sum / mean / min / max / count / count_distinct.\n
xlsx_brand_newreada new server-side tool
xlsx_cached_onlyreadonly in cache
xlsx_chartsreadList every chart in a LOCAL .xlsx file with type (bar / line / pie / scatter / area / doughnut / radar / stock / surface / bubble), title, axis titles, and per-series formula refs (the cell ranges the chart pulls from). Sheet attribution via the OOXML drawing rel chain.\n\n
xlsx_commentsreadlist every cell comment in a workbook — both legacy notes (yellow stickies, cell.note) AND modern threaded comments (multi-author conversations stored separately in the OOXML zip). Per entry: kind, sheet, cell, author, text, plus any reply thread.\n
xlsx_conditional_formatsreadlist every conditional formatting rule in a workbook — color scales, data bars, icon sets, formula-based highlights, top-N, duplicate / unique values, contains-text, time-period, above-average. Per rule: range, type, operator, formulae, priority, stopIfTrue.\n
xlsx_convertreaduniversal spreadsheet format converter. Reads ANY of 25+ input formats (xlsx, xlsb, xlsm, xls, ods, fods, numbers, csv, tsv, dbf, lotus 1-2-3, quattro pro, sylk, dif, html, rtf, etc.) and emits ANY supported output format (xlsx, csv, json, md, html, etc.).\n
xlsx_data_validationsreadlist every cell-level data validation rule (dropdowns, numeric/date bounds, text-length caps, custom formulas) defined in a workbook — the constraints that Excel enforces when a human types into the cell.\n
xlsx_describereadpandas-style df.describe() per column — count, nulls, unique, min/max/mean/std for numerics, dtype with purity score.\n
xlsx_diffreadcompute a semantic diff between two LOCAL .xlsx files — cell-level deltas, formula changes, added/removed rows.\n
xlsx_dupreadfirst wins
xlsx_dynamic_onlyreadlives only on the server
xlsx_evalreadevaluate Excel formulas against a LOCAL .xlsx file with our own recalc engine. xlwings-style.\n
xlsx_external_linksreadlist every external workbook reference this file depends on —
xlsx_filterreadpandas-style row filter on a LOCAL .xlsx file with predicates AND-combined: eq/ne/gt/gte/lt/lte/contains/in/is_null/not_null.\n
xlsx_form_controlsdestructivelist every form control (Check Box, Button, Drop-down, List Box, Option Button, Scroll Bar, Spinner, Label, Group Box) in a workbook with the linked cell, current value, dropdown source range, and min/max/step bounds where applicable.\n
xlsx_formulasreadextract every formula in a LOCAL .xlsx workbook — cell coord (A1), formula text, cached result. openpyxl-style read-only metadata.\n
xlsx_fullreadReal desc
xlsx_future_cachedreadtampered
xlsx_healer_diagnosereadproduce a structured diagnostic report of external references that are broken or at risk in a workbook. Returns five classes of finding: (1) external-workbook references that can\
xlsx_healer_intentreadGoal-driven healing. Caller declares an INTENT (
xlsx_healer_simulatereadsimulate recipient-side accessibility of a workbook\
xlsx_hyperlinksreadlist every hyperlink in a workbook with its anchor cell, target URL/anchor, display text, tooltip, and a kind classifier (external / internal / mailto / unknown).\n
xlsx_imagesreadList every embedded image in a LOCAL .xlsx file with format (png / jpg / gif / svg / bmp / tiff / emf / wmf), size in bytes, sheet attribution, and anchor cell range (the cells the image floats over). Reads xl/media/* + xl/drawings/* directly.\n\n
xlsx_keepreadkeep
xlsx_list_sheetsreadlist sheet names, dimensions, and visibility for a LOCAL .xlsx file.\n
xlsx_macrosreadInspect xlsm / xlsb workbooks for VBA macro presence, vbaProject.bin size, and likely module names (ThisWorkbook / Sheet<N> / Module<N> / Class<N> / UserForm<N> via heuristic UTF-16LE scan). Returns short safety advice the LLM should relay to the user.\n\n
xlsx_merged_cellsreadlist every merged-cell region with master-cell value, range, span dimensions, and kind heuristic (
xlsx_named_rangesreadlist all defined names (named ranges) in a LOCAL .xlsx workbook — name, scope (workbook or sheet), kind (cell / range / formula), reference.\n
xlsx_onlyreadkept
xlsx_only_in_stale_cachereadold but real
xlsx_pivotreadpandas-style pivot_table() on a LOCAL .xlsx file — reshape a flat table into a 2D matrix where rows are unique values of
xlsx_post_slackwriteupload a local .xlsx file to a Slack channel as a file attachment, with an optional accompanying message.\n
xlsx_post_teamswriteUpload a local .xlsx file to a Microsoft Teams channel as a file attachment, with an optional accompanying message.\n\n
xlsx_print_settingsreadsurface
xlsx_propertiesreadSurface the workbook\
xlsx_readreadxfa — read an .xlsx file by path and return a rendered markdown/JSON/SQL representation.\n\n
xlsx_read_handlereadread a workbook that has already been uploaded to the server via the chunked upload flow, by its server-side cache handle, WITHOUT re-transferring the bytes. Returns the same shape as xlsx_read (text / json / markdown) but skips the file_b64 round-trip.\n\n
xlsx_receiptreadAttach an AI-generation receipt to a LOCAL .xlsx file — a cryptographic attestation embedded in docProps/custom.xml that says
xlsx_redactreadredact PII and sensitive values from a LOCAL .xlsx file before sharing or archiving.\n
xlsx_schemareadinfer column schema of a LOCAL .xlsx file — types, nullable flags, header row, sample values.\n
xlsx_session_set_validationswriteconfigure per-session data-validation rules the server will apply to subsequent calls in the same session (e.g., reject rows missing required columns, enforce enum values on a category column, range-bound numeric inputs). Stateful — affects this session only.\n\n
xlsx_slicers_timelinesreadList every slicer (interactive filter button) and timeline (date-range filter visual) in a LOCAL .xlsx file with their captions, source bindings (table column or pivot table), and timeline granularity (years / quarters / months / days) plus the currently-selected date range.\n\n
xlsx_sortreadpandas-style df.sort_values() on a LOCAL .xlsx file with multi-column sort and per-column direction (asc/desc, default asc).\n
xlsx_stampreadSign a LOCAL .xlsx file with a
xlsx_stubreadhas desc but no schema
xlsx_tablesreadlist every Excel ListObject (
xlsx_topologyreadone-call workbook orientation. Returns sheets × dimensions × formulas × named ranges × tables × validations × hyperlinks × merges in one shot, plus feature flags (macros / external refs / pivots / LAMBDA / dynamic arrays).\n
xlsx_unknown_future_toolreadd
xlsx_validatereadsoundness check on a LOCAL .xlsx file — parses the workbook with the server\
xlsx_value_countsreadpandas-style Series.value_counts() on one column of a LOCAL .xlsx file — count each unique value, sorted by frequency desc, with percentage.\n
xlsx_verify_receiptreadverify a workbook\
xlsx_verify_stampreadverify a workbook\
xlsx_writewritecreate or update a LOCAL .xlsx file from a structured spec.\n\n
04

Trust audit

BLOCKgrade D · trust 61/100 Do not install this without reading the findings. The audit found something that could harm you or your machine.

LayerWhat it checksResult
L0Provenance & inventoryPASS
L1Static analysis of the codeFAIL
L2Instruction surface (what it tells the agent)WARN
L3Class-specific surfaceWARN
L4Behavioural (sandbox)SKIPPED

What the source does

Filesystem
declared (2 observation(s))
Network
declared (7 observation(s))
Shell
declared (1 observation(s))
Dependencies
not all pinned
Secrets in source
found

Findings (25)

HIGHNetwork egress · net.tls_off · CWE-200, CWE-319
scripts/review_attest_marker_resolve.py:119
cmd.append("--insecure-ignore-tlog")  # degraded --no-tlog-upload path (sysarch-approved)
Why it matters. certificate verification is disabled
Fix. leave verification on
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
lib/register.js:58
api_key: 'xfa_ci_skip_registration',
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
test/v2/friendly-error.test.js:255
const secret = 'xfa_live_abcdefghijklmnop1234567890';
MEDIUMHard-coded secrets · secret.slack · CWE-798, CWE-321
test/v2/friendly-error.test.js:268
payload: { error: { message: 'invalid token xoxb-1234567890-abcdefghij' } },
MEDIUMHard-coded secrets · secret.slack · CWE-798, CWE-321
test/v2/friendly-error.test.js:271
assert.ok(!out.includes('xoxb-1234567890'),
MEDIUMHard-coded secrets · secret.slack · CWE-798, CWE-321
test/v2/inline-4xx.test.js:224
['t xoxb-1234567890-abcdef x', 'xoxb-1234567890', '<slack-token>'],
MEDIUMPrompt injection · prompt.hidden_style · CWE-94, CWE-1427
docs/KNOWN-BUGS.md:264
7. **Hidden trailing columns** (#1953). Fixture: hide cols X:Z when last data is column J. Assert: `<col hidden="1" min="24" max="26"/>` survives.
MEDIUMFilesystem / path · mcp.destructive_tools · CWE-22, CWE-59
xlsx_form_controls
Why it matters. 1 tool(s) can delete or overwrite
Fix. prefer a read-only mode or scoped tokens; the page states the blast radius
LOWInventory / provenance · inv.binary · CWE-1104
samples/reporting-pack-v1.xlsx
reporting-pack-v1.xlsx
Why it matters. a compiled or binary member cannot be reviewed from source
Fix. ship source, or explain the binary in the README
LOWInventory / provenance · inv.binary · CWE-1104
samples/reporting-pack-v2.xlsx
reporting-pack-v2.xlsx
Why it matters. a compiled or binary member cannot be reviewed from source
Fix. ship source, or explain the binary in the README
LOWInventory / provenance · inv.hidden_file · CWE-1104
.grace-refutes.yml
.grace-refutes.yml
Why it matters. hidden member outside the usual dotfiles
Fix. review its purpose
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
test/plugin/server-key.test.js:6
const { SERVER_KEY, TOOL_PREFIX, OUTPUT } = require('../../scripts/plugin/generate-session-start.js');
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
test/plugin/session-start.test.js:6
const { generate, allTools, MANIFEST, OUTPUT } = require('../../scripts/plugin/generate-session-start.js');
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
test/plugin/session-start.test.js:64
const { firstSentence, validateList } = require('../../scripts/plugin/refresh-tool-manifest.js');
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
test/v2/annotations-completeness.test.js:20
const { TOOLS } = require('../../mcp.js');
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
test/v2/annotations-completeness.test.js:21
const { TOOL_ANNOTATIONS, applyAnnotations } = require('../../lib/annotations');
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
CLAUDE.md:45
- Spawn with `OTEL_SERVICE_NAME=<agent-name>` exported so traces land in Phoenix (http://127.0.0.1:6006) tagged by agent.
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
data-cleaning/agent/SPEC.md:144
- `OTEL_SERVICE_NAME=cleaner` — traces land in Phoenix at http://127.0.0.1:6006 tagged `cleaner`.
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
data-cleaning/agent/TEST_PLAN.md:73
- **OTEL traces tagged `cleaner`.** Spawn cleaner; complete a diagnose + execute against `na-variants-mixed`. Query Phoenix at http://127.0.0.1:6006 for traces tagged `service.name=cleaner` in the las
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
data-cleaning/agent/TEST_PLAN.md:111
- Phoenix observability: `http://127.0.0.1:6006` (Phase 1 harness)
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
test/v2/api.test.js:130
process.env.XLSX_FOR_AI_API   = `http://127.0.0.1:${serverPort}`;
LOWObfuscation / stealth · obf.decode_call · CWE-506, CWE-94
scripts/review_attest_marker_resolve.py:141
blob = base64.b64decode(m["blob_b64"])
LOWObfuscation / stealth · obf.decode_call · CWE-506, CWE-94
scripts/review_attest_marker_resolve.py:142
bundle = base64.b64decode(m["bundle_b64"])
LOWObfuscation / stealth · obf.decode_call · CWE-506, CWE-94
scripts/review_gate_marker_present.py:80
base64.b64decode(bundle_b64, validate=True)  # bundle must be real base64 (not consumed here)
LOWObfuscation / stealth · obf.decode_call · CWE-506, CWE-94
scripts/review_gate_marker_present.py:81
blob = base64.b64decode(blob_b64, validate=True)

Gates applied: no_behavioural_pass.

Audited 2026-10-10 · audit v0.4.1 · source sha fc3294919ea1full audit observations/trust-audit/mcp-server/senoff__xlsx-for-ai.json · Report an issue / request a re-scan
05

Audit history

Every audit this server has had. A grade with a past is a grade somebody is still checking.

DateSourceVerdictGradeScoreChange
2026-10-10fc3294919ea1BLOCKD61first audit
06

Questions

What is the xlsx-for-ai MCP server?

MCP server + CLI giving AI agents 50 spreadsheet tools for .xlsx — live-recalc formulas (~390 Excel functions), repair broken references & external links, read/write, diff, and audit. Works in Claude Code, Cursor, Codex, and any MCP client.

What tools does xlsx-for-ai expose?

55 in total: 50 read-only, 4 that write, and 1 that can delete or overwrite (xlsx_form_controls). Every one is listed on this page with its risk.

Is xlsx-for-ai safe to connect to an agent?

No — not without reading the findings first. The audit graded it D (61/100) and found 1 critical or high issue in the source. Each one is listed on this page with the file and line it is on. Separately from the audit: 1 of its tools can destroy data, so scope the token you give it to what you actually need.

What credentials does xlsx-for-ai need?

It reads SLACK_BOT_TOKEN, TEAMS_GRAPH_TOKEN and XLSX_FOR_AI_KEY from the environment. Give it a token scoped to the least it needs — an agent that can be talked into calling a tool can be talked into calling it with your credentials.

How does xlsx-for-ai run?

It speaks stdio, so it runs as a local process your client starts. It is published on npm as xlsx-for-ai at 4.2.4.

How current is this page?

The grade is for one exact copy of the source (fc3294919ea1), read on 2026-10-10. The repository is watched and re-audited when it changes.

Advertisement