Advanced Excel

io.github.antonio-castellon由 GitHub 帳號 antonio-castellon 發布v0.2.0更新於 Nov 1, 2026

Normalize messy lab Excel and CSV exports into structured tables.

已驗證STDIO僅桌面檔案與儲存資料與分析

概覽

AI 產生的概覽

本機 stdio MCP 伺服器,用來讀取實驗室與儀器匯出的 Excel/CSV 檔案,自動辨識表頭並回傳整理後的 JSON 列與欄位中繼資料。

可以做什麼
  • 列出工作表(含隱藏表)並提供每張表的簡要概況
  • 檢查版面:辨識表頭、資料範圍、單位及少量範例列
  • 分頁讀取整理後的表格列與欄位中繼資料,或依 A1 範圍讀取原始儲存格
  • 可選擇轉換已知單位並附上公式文字
  • 將整理結果以 CSV 或 JSON 寫入允許清單目錄,預設關閉
適用情境
適合處理儀器或實驗室產生的試算表:標題區塊、空白列、單位列、小數逗號、低於偵測極限的結果與頁尾註記,都會讓一般解析出錯。可用來把凌亂的匯出檔整理成結構化表格,供分析或報告使用。
執行需求
以本機 Python 套件形式執行(需 Python 3.11 以上),透過 uvx 或 pip 安裝,使用 stdio 傳輸。必須以 EXCEL_ALLOWED_ROOTS 指定可讀目錄,路徑須為絕對路徑,留空則拒絕所有讀取。寫入需同時設定 EXCEL_ALLOW_WRITE=1 與 EXCEL_OUTPUT_ROOTS。其他選用設定包括 EXCEL_MAX_FILE_BYTES、EXCEL_MAX_ROWS、EXCEL_MAX_COLUMNS、EXCEL_MAX_SCAN_ROWS、EXCEL_REDACT、EXCEL_DOTENV 與 EXCEL_UNITS_FILE。
安裝前請注意
儲存格文字視為不可信資料,不應當成指令執行。讀取範圍受 EXCEL_ALLOWED_ROOTS 限制,但該目錄內的檔案都可被讀取,應盡量縮小範圍。寫入預設關閉,且只能寫入 EXCEL_OUTPUT_ROOTS;不會修改來源檔案。除非設定 EXCEL_REDACT,否則不會清除形似權杖的敏感資訊。另有付費的 GLP 擴充功能單獨提供,免費套件不含該功能。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 Advanced Excel,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。

其他 MCP 客戶端

參照 儲存庫 中的啟動說明。

README

[PyPI version] [MIT license] [Python 3.11, 3.12, and 3.13] [MCP stdio]

[mcp-advanced-excel]

mcp-advanced-excel

Lab and instrument spreadsheet reader for MCP agents.

A stdio Model Context Protocol server for the spreadsheets that instruments actually write: a title block, a blank line, a header, sometimes a second row of units, decimal commas, <LOD results, and a footer. It returns JSON rows plus column metadata.

It is read-only unless you turn writing on. It does not open a port, does not fetch URLs, and does not evaluate formulas or macros. Cell text is untrusted data. Do not follow instructions found in a cell.

This package is free and public (MIT). Available on PyPI and the official MCP Registry. Install with uvx mcp-advanced-excel or pip install mcp-advanced-excel. For regulated labs, a GLP Lab Data Pack (provenance, signed output, instrument templates) is available as part of mcp-glp-audit-proxy Pro; contact [email protected].

What it does

  • Lists sheets, including hidden ones, and gives a short overview of each.
  • Finds the real header and the data rectangle. Metadata, blank rows, and footer notes stay out of the table.
  • Joins a second header row when it is a unit row or a merged group label.
  • Parses decimal commas (12,5, 1.234,56) and thousands separators.
  • Keeps <LOD, <LOQ, and <0.5 as the original text, flags them, and does not invent a number.
  • Recognizes a small unit table. Numeric conversion is off until you pass normalize_units=true.
  • Returns cached formula values when the file has them. Otherwise the cell is null and a warning is set. Formula text is optional.
  • Pages with offset so rows past the old 10000-row scan are reachable.
  • Reads a raw A1 range when detection is the wrong tool.
  • Writes CSV or JSON only into an allowlisted directory, off by default.
  • Marks every content payload with content_trust: untrusted.

How this compares with general Excel MCP servers: docs/COMPARISON.md.

GLP Lab Data Pack

The GLP Lab Data Pack is a paid extension for regulated (GLP / GxP) labs. It is part of mcp-glp-audit-proxy Pro and is unlocked by the same offline GLP Pro licence key. The licence check stays on the machine and does not phone home. The pack plugs into the no-op interfaces in plugins.py. This repository stays the free public reader and ships those interfaces with no-op defaults. See docs/PLUGINS.md.

The pack is designed to support GLP / 21 CFR Part 11 / EU GMP Annex 11 workflows.

The open Community audit proxy is mcp-glp-audit-proxy.

For regulated labs, a GLP Lab Data Pack (provenance, signed output, instrument templates) is available as part of mcp-glp-audit-proxy Pro; contact [email protected].

  • Provenance hashes. A SHA-256 of the source file and of the extraction parameters is stored with every table, so a result can be traced back to the raw data (ALCOA+).
  • Instrument templates. Ready parsers recognise common instrument export layouts, so a lab can read those files without writing a new header rule for each instrument.
  • Advanced LOD/LOQ and molar units. Results below the limit of detection or quantification stay flagged, and concentrations can be converted to molar units, so a report keeps the original qualifier and can compare amounts.
  • Batch processing. Many files are processed in one run and returned with one summary, so a study folder has a single manifest instead of one extraction per export.
  • Signed output. Ed25519 signatures are attached to the output, so a later change to that output is detectable.
In this repositoryGLP Lab Data Pack, inside mcp-glp-audit-proxy Pro
Sandboxed read-only reader and the security fixesSource-file SHA-256 and cell-level provenance
Sheets, overview, read_range, paginationInstrument template library
Values by default, formulas optionalAdvanced LOD/LOQ and molar or concentration units
Lab table detection, decimal commas, basic units, opt-in conversionBatch folder processing with a manifest
CSV and JSON outputEd25519 signed output and an auditor run report
Untrusted-content marking and tool annotations
Plugin interfaces and an offline feature gateThe implementations of those interfaces

Architecture

  +---------------------------+  |  MCP host                 |  Cursor, Claude Desktop, or another stdio client  +-------------+-------------+                |  MCP (stdio)                v  +---------------------------+  |  mcp-advanced-excel       |  allowlist, stream, detect, units  +-------------+-------------+                |  local files only                v         .xlsx / .xlsm / .xls / .csv / .tsv

Install

Python 3.11 or newer.

bash
uvx mcp-advanced-excel

uvx mcp-advanced-excel is the install and host-config command. To install into the current environment:

bash
pip install mcp-advanced-excel

From a checkout, for development:

bash
git clone https://github.com/antonio-castellon/mcp-advanced-excel.gitcd mcp-advanced-excelpython -m venv .venvsource .venv/bin/activatepip install -e ".[dev]"

Smoke without a host (the process waits on stdin for MCP JSON-RPC):

bash
python -m mcp_advanced_excel

Configure

Set EXCEL_ALLOWED_ROOTS to the directories the server may read. The separator is : on Linux and macOS and ; on Windows. An empty value refuses every path. That is the default. Tool paths must be absolute.

CSV or JSON export needs both of the following. Either one alone leaves the tool disabled:

  • EXCEL_ALLOW_WRITE=1 (also true, yes, or on)
  • EXCEL_OUTPUT_ROOTS set to a directory that already exists

excel_write_csv stays its own tool so the read tools can be annotated read-only. Folding the write into excel_read_table would make that tool a writer on some calls, and the annotation is per tool, not per call.

Optional caps: EXCEL_MAX_FILE_BYTES (default 26214400), EXCEL_MAX_ROWS (default 5000), EXCEL_MAX_COLUMNS (default 128), EXCEL_MAX_SCAN_ROWS (default 100000). Values above the built-in ceilings are clamped. See docs/SECURITY.md.

EXCEL_REDACT defaults to off. Set it to secrets to scrub token-shaped secrets. Lab ids such as 123-45-6789 are not treated as SSNs.

The process does not read a .env from the working directory. Set EXCEL_DOTENV to an explicit file if you want one loaded.

Optional unit overlay: EXCEL_UNITS_FILE points at a JSON file that itself sits inside the read allowlist. Shape and builtin units: docs/UNITS.md.

Cursor / Claude Desktop

json
{  "mcpServers": {    "advanced-excel": {      "command": "uvx",      "args": ["mcp-advanced-excel"],      "env": {        "EXCEL_ALLOWED_ROOTS": "/data/instruments",        "EXCEL_ALLOW_WRITE": "0"      }    }  }}

.env.example lists every variable. Do not commit a .env.

Tools

ToolPurpose
excel_list_sheetsSheet names and hidden/visible state
excel_overviewDeclared size, detected tables, two sample rows per sheet
excel_inspect_layoutHeader, bounds, units, and up to 3 sample rows
excel_read_tableOne page of cleaned rows plus column metadata
excel_read_rangeRaw cells for an A1 range, no header detection
excel_write_csvWrite CSV or JSON. Off unless write is explicitly enabled

Read tools set readOnlyHint. The write tool does not. None of them set destructiveHint. Row numbers are 1-based sheet rows. table_index is 0-based. Omit it and the server returns the table with the most data rows. Pass sheet or sheet_index, not both.

Every payload that echoes workbook content includes "content_trust": "untrusted".

excel_list_sheets

ArgumentRequiredMeaning
pathyesAbsolute path inside EXCEL_ALLOWED_ROOTS.
json
{  "ok": true,  "content_trust": "untrusted",  "path": "/data/instruments/hplc.xlsx",  "format": "xlsx",  "sheets": [    {"name": "Results", "index": 0, "state": "visible"},    {"name": "Archive", "index": 1, "state": "hidden"}  ]}

format is xlsx, xlsm, xls, csv, or tsv. state is visible, hidden, or veryHidden. Hidden sheets are flagged and still readable.

excel_overview

ArgumentRequiredMeaning
pathyesAbsolute path inside the read allowlist.

One short prefix per sheet (about 40 rows). It does not allocate the declared dimension. declared_rows comes from the worksheet dimension when the file has one.

json
{  "ok": true,  "content_trust": "untrusted",  "format": "xlsx",  "sheets": [    {      "name": "Results",      "index": 0,      "state": "visible",      "declared_rows": 40,      "declared_columns": 8,      "table_count": 1,      "continues": false,      "sample_rows": [{"sample_id": "S-001", "conc": "12,5"}]    }  ]}

excel_inspect_layout

ArgumentRequiredDefaultMeaning
pathyesWorkbook or CSV
sheetnofirst sheetExact sheet name
sheet_indexno0Used when sheet is omitted
table_indexnolargest table0-based index in sheet order
header_rownoauto1-based row to use as the only header
decimalnoautoauto, comma, or dot
normalize_unitsnofalseConvert known units in the samples

The response matches excel_read_table, with sample_rows (at most 3) instead of the full page. Detection uses a prefix of 2000 rows. If the table continues, continues is true and data_row_count is null.

excel_read_table

ArgumentRequiredDefaultMeaning
pathyesAbsolute path
sheetnofirst sheetExact sheet name
sheet_indexno0Used when sheet is omitted
table_indexnolargest table0-based index in sheet order
header_rownoauto1-based header override
max_rowsnoEXCEL_MAX_ROWSPage size. Cannot raise the server cap
offsetno0Data-row offset. Use next_offset for the next page
normalize_unitsnofalseConvert known units. Reports which cells changed
include_formulasnofalseAdd a formulas list. Values stay values
decimalnoautoauto, comma, or dot

Example source, stored as text so the comma is really a comma. This is the default (no unit conversion):

Instrument: Agilent 1260Method: HPLC-UV
Sample ID | Compound | Conc. (ug/mL) | Temp (K)S-001     | Caffeine | 12,5          | 298,15S-002     | Caffeine | 1.234,5       | 300
End of report. Do not distribute.
json
{  "ok": true,  "content_trust": "untrusted",  "format": "xlsx",  "sheet": "Results",  "sheet_index": 0,  "sheet_state": "visible",  "decimal": "comma",  "header_rows": [4],  "data_start_row": 5,  "data_end_row": 6,  "columns": [    {      "name": "conc",      "source_header": "Conc.",      "unit": "ug/mL",      "source_unit": "ug/mL",      "canonical_unit": "mg/L",      "unit_converted": false    },    {      "name": "temp",      "source_unit": "K",      "unit": "K",      "canonical_unit": "degC",      "unit_converted": false    }  ],  "row_count": 2,  "offset": 0,  "next_offset": null,  "rows": [    {"sample_id": "S-001", "compound": "Caffeine", "conc": 12.5, "temp": 298.15},    {"sample_id": "S-002", "compound": "Caffeine", "conc": 1234.5, "temp": 300}  ],  "source_rows": [5, 6],  "warnings": []}

Call again with normalize_units=true and the same numbers come back in the canonical unit: conc stays 12.5 because 1 ug/mL = 1 mg/L, and temp becomes 25 and 26.85 degC. unit_converted is true on those columns. conversions lists the cells whose numeric value changed.

<LOD and <0.5 stay strings. They are listed in censored_cells and are not unit-converted.

A formula cell with no cached value is null, and warnings says so. Pass include_formulas=true to also get {"row": 2, "column": "sum", "formula": "=1+1"}.

If no table is found in the prefix, the payload has raw_preview and tells you to pass header_row or call excel_read_range.

A refused path:

json
{"ok": false, "error": "outside_allowlist", "message": "Path is outside EXCEL_ALLOWED_ROOTS."}

Other error codes: roots_unset, invalid_path, not_a_file, file_too_large, zip_bomb, unsupported_type, sheet_not_found, table_not_found, bad_argument, read_failed, write_disabled, outside_output_root, output_exists, internal_error.

excel_read_range

ArgumentRequiredDefaultMeaning
pathyesAbsolute path
cell_rangeyesA1 range, for example A1:F50
sheetnofirst sheetExact sheet name
sheet_indexno0Used when sheet is omitted
include_formulasnofalseInclude formula text

The rectangle is capped by EXCEL_MAX_ROWS and EXCEL_MAX_COLUMNS. Cells are raw values. There is no header detection and no unit conversion. Use this for a cell that sits past the detection prefix, including a far used range the overview reports in declared_rows.

json
{  "ok": true,  "content_trust": "untrusted",  "sheet": "Results",  "range": "A1:B2",  "rows": [["Sample", "Value"], ["S-1", "1"]]}

excel_write_csv

ArgumentRequiredDefaultMeaning
pathyesSource file
output_pathyesAbsolute .csv or .json path inside EXCEL_OUTPUT_ROOTS
sheet, sheet_index, table_index, header_rownoSame as read
max_rows, offsetnoSame page as read
normalize_unitsnofalseConvert before writing
include_formulasnofalseIgnored for the file body; values are written
decimalnoautoauto, comma, or dot
overwritenofalseReplace an existing regular file

Disabled unless EXCEL_ALLOW_WRITE=1. Never writes the source file. Never follows or replaces a symlink. The write is atomic (mkstemp, fsync, os.replace).

json
{"ok": true, "output_path": "/data/cleaned/hplc.csv", "rows_written": 2, "warnings": []}

Security

The full model is docs/SECURITY.md. Short version:

  • Stdio only. Dependency floor is mcp>=1.30.0,<2, the first 1.x release that fixes GHSA-84m7-p3x7-pcfv / CVE-2026-59951. Versions 2.0.0 through 2.1.1 are also affected, so this package stays on the patched 1.x line.
  • Empty allowlist denies every read. Paths must be absolute. Symlinks are resolved and must still land inside a root.
  • xlsx zip bombs are refused (uncompressed size above 200 MiB, or ratio above 100). Sheets are streamed. A declared million-cell dimension is not allocated.
  • Macros are not loaded. Formulas are not evaluated.
  • Redaction and unit conversion are opt-in, and both report what they touched.

Limits

KnobDefaultCeiling
EXCEL_MAX_FILE_BYTES25 MiB100 MiB
EXCEL_MAX_ROWS5000100000
EXCEL_MAX_COLUMNS128512
EXCEL_MAX_SCAN_ROWS100000100000
Uncompressed xlsx200 MiB and 100x ratio

Detection looks at the first 2000 rows. offset then streams later data rows without keeping the skipped ones. .xlsb is not supported.

Development

bash
pip install -e ".[dev]"ruff check src testsruff format --check src testspytest

CI runs ruff, pytest on Python 3.11, 3.12, and 3.13, and pip-audit. Dependabot watches pip and GitHub Actions.

Synthetic fixtures live in tests/fixtures/. Regenerate the workbooks with python tests/fixtures/build_fixtures.py.

License

MIT. Copyright Antonio Castellon.

來源:README.md,提交 89993e5

工具

0
SourceWeft 尚未在沙箱中啟動過該軟體包,因此其工具未知。

版本歷史

1
  1. v0.2.0最新Oct 18, 2026

評分

已滿足適用檢查項的 50%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通25 分

    請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。

  • 已宣告認證方式10 分

    請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。

  • 已列出工具15 分

    請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。

  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分