{
  "markdown": "# agent-spreadsheet\n\n[![CI](https://github.com/PSU3D0/agent-spreadsheet/actions/workflows/ci.yml/badge.svg)](https://github.com/PSU3D0/agent-spreadsheet/actions/workflows/ci.yml)\n[![Crates.io](https://img.shields.io/crates/v/agent-spreadsheet-mcp.svg)](https://crates.io/crates/agent-spreadsheet-mcp)\n[![npm](https://img.shields.io/npm/v/agent-spreadsheet.svg)](https://www.npmjs.com/package/agent-spreadsheet)\n[![License](https://img.shields.io/crates/l/agent-spreadsheet-mcp.svg)](https://github.com/PSU3D0/agent-spreadsheet/blob/main/LICENSE)\n\n![agent-spreadsheet](https://raw.githubusercontent.com/PSU3D0/agent-spreadsheet/main/assets/banner.jpeg)\n\n**agent-spreadsheet is the tool interaction service for agent-based spreadsheet usage.**\n\nIt gives agents a safe, inspectable, token-efficient way to **read, analyze, mutate, verify, and operationalize Excel workbooks** without falling back to brittle UI automation.\n\nIf you want an agent to work with spreadsheets like a real system instead of a screenshot puppet, this is the stack.\n\n---\n\n## What this project is\n\nagent-spreadsheet ships a unified spreadsheet interaction layer across three surfaces:\n\n| Surface | Binary / Package | Mode | Best for |\n| --- | --- | --- | --- |\n| **CLI** | `agent-spreadsheet` / `asp` | Stateless | One-shot reads, safe edits, pipelines, CI, agent tool calls |\n| **MCP server** | `agent-spreadsheet-mcp` | Stateful | Multi-turn agent sessions, workbook caching, fork/recalc workflows |\n| **TypeScript SDK** | `agent-spreadsheet-sdk` | Library | App integrations — drives the server's canonical `/v1` route, or runs fully in-process via the embedded WASM engine (no server required) |\n\nThe WASM build (`agent-spreadsheet-wasm`) is the SDK's local runtime, not a separate product surface: JS and TypeScript code targets one object model and the execution substrate (server vs embedded engine) is a configuration choice.\n\nSupported workbook modes:\n\n- `.xlsx` / `.xlsm` — read + write\n- `.xls` / `.xlsb` — discovery/read-oriented workflows only\n\n## Powered by Formualizer\n\nEvery computed value in this stack comes from **[Formualizer](https://github.com/PSU3D0/formualizer)** — a permissively licensed (MIT/Apache-2.0) spreadsheet engine written in Rust: formula parsing, dependency-graph recalculation, 400+ Excel functions, dynamic arrays, and deterministic evaluation built for agents. No Excel COM, no headless LibreOffice.\n\nThat native engine is why this project can offer what most spreadsheet tooling for agents cannot: **recalculate the actual workbook, trace which cells changed and why, and prove it** — not just read cached values or push blind edits.\n\nEmbedding spreadsheet logic in your own product rather than driving workbooks as an agent? Use [Formualizer](https://github.com/PSU3D0/formualizer) directly (Rust, Python, JS/WASM).\n\n---\n\n## Why agents use agent-spreadsheet\n\n### Built for tool use, not just humans\n- deterministic JSON contracts\n- schema and example discovery from the CLI itself\n- explicit pagination and compact output modes\n- machine-readable warnings and error envelopes\n\n### Safe mutation, not blind mutation\n- dry-run first workflows\n- stateless output modes and overwrite safety\n- event-sourced session editing\n- verification surfaces for proving downstream outcomes\n- structural impact analysis before risky workbook changes\n\n### Spreadsheet-aware, not generic file editing\n- region detection\n- table and footer-aware append helpers\n- template row / row band cloning\n- formula-specific replace and diagnostics\n- named range CRUD\n- recalculation + diff + proof flows\n\n### Good agent ergonomics\n- nested command groups with legacy alias compatibility\n- token-efficient reads\n- exact-cell inspection and layout inspection\n- workflow helpers for the repetitive parts agents usually get wrong\n\n---\n\n## What is new / what makes this stack different\n\nThe current surface is much stronger than a plain “read some cells” tool. Major capabilities now include:\n\n- **`asp` as the primary CLI** with `agent-spreadsheet` preserved as a compatibility alias\n- **grouped verification** via `asp verify proof` and `asp verify diff`\n- **preview-first workflow helpers** for:\n  - `write append`\n  - `write clone-template-row`\n  - `write clone-row-band`\n- **formula-safe batch workflows** with parse-policy diagnostics\n- **cell/layout/export/import inspection surfaces**\n- **named range management** (`write name define|update|delete`)\n- **formula-only replacement** (`write formulas replace`)\n- **event-sourced session editing** with log, branch, undo/redo, fork, apply, and materialize\n- **SheetPort manifest lifecycle + execution** for contract-driven spreadsheet automation\n\n---\n\n## Install\n\n### Shell installer\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/PSU3D0/agent-spreadsheet/main/install.sh | sh\n```\n\nThe installer downloads a prebuilt CLI to `~/.local/bin` and creates the `asp` command. Pin a release with `ASP_VERSION=0.15.0`, set `ASP_INSTALL_DIR` to choose another destination, or pass `--mcp` to install the MCP server too:\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/PSU3D0/agent-spreadsheet/main/install.sh | sh -s -- --mcp\n```\n\n### npm\n\n```bash\nnpm i -g agent-spreadsheet\n```\n\nThis installs both `asp` (the primary command) and `agent-spreadsheet` (the compatibility alias) from a prebuilt native binary. No Rust toolchain is required.\n\n### cargo-binstall\n\n```bash\ncargo binstall agent-spreadsheet\n```\n\nThis installs the prebuilt CLI in seconds.\n\n### Cargo\n\n```bash\ncargo install agent-spreadsheet --features recalc --bin asp --bin agent-spreadsheet\n```\n\nThis builds the CLI from source. Formualizer (the native Rust recalc engine) is included by default.\n\n### mise\n\n```bash\nmise use -g \"ubi:PSU3D0/agent-spreadsheet[exe=asp]\"\n\n# Homebrew\nbrew install psu3d0/tap/agent-spreadsheet\n```\n\n### MCP server\n\n```bash\ncargo install agent-spreadsheet-mcp\n```\n\n### Docker\n\n```bash\n# Read-only / slim\ndocker pull ghcr.io/psu3d0/agent-spreadsheet-mcp:latest\n\n# Write + recalc + screenshots\ndocker pull ghcr.io/psu3d0/agent-spreadsheet-mcp:latest-full\n```\n\n### JavaScript SDK\n\n```bash\nnpm i agent-spreadsheet-sdk\n```\n\n### Prebuilt binaries\n\nDownload raw binaries and archives from [GitHub Releases](https://github.com/PSU3D0/agent-spreadsheet/releases).\n\nPublished native assets include:\n- Linux x86_64\n- Linux arm64\n- macOS x86_64\n- macOS arm64\n- Windows x86_64\n\n---\n\n## Start here: the core workflows\n\n## 1) Orient the workbook before reading cells\n\n```bash\n# What sheets are here?\nasp read sheets data.xlsx\n\n# What regions/tables/parameter blocks does this sheet contain?\nasp read overview data.xlsx \"Model\"\n\n# What named items are available?\nasp read names data.xlsx\n\n# Read a structured region as a table\nasp read table data.xlsx --sheet \"Model\"\n```\n\n## 2) Inspect exactly what an agent needs\n\n```bash\n# Raw values for exact ranges\nasp read values data.xlsx Model A1:C20\n\n# Detail-view for targeted cells (value / formula / cached / style triage)\nasp read cells data.xlsx Model B2 D10:F12\n\n# Layout-aware rendering for a bounded range\nasp read layout data.xlsx Model --range A1:H30 --render both\n\n# Export a bounded range to csv or grid json\nasp read export data.xlsx Model A1:H30 --format csv --output model.csv\n```\n\n## 3) Do a safe stateless edit → recalc → proof → diff loop\n\n```bash\nasp workbook copy data.xlsx /tmp/draft.xlsx\nasp write cells /tmp/draft.xlsx Inputs \"B2=500\" \"C2==B2*1.1\"\nasp workbook recalculate /tmp/draft.xlsx\nasp verify proof data.xlsx /tmp/draft.xlsx --targets Summary!B2,Summary!B3 --named-ranges\nasp verify diff data.xlsx /tmp/draft.xlsx --details --limit 50\n```\n\nA representative label-mode lookup:\n\n```bash\nasp analyze find-value data.xlsx \"Net Income\" --mode label --label-direction below\n```\n\n## 4) Preview structural risk before mutating the workbook\n\n```bash\nasp analyze ref-impact data.xlsx --ops @structure_ops.json --show-formula-delta\n```\n\nThis is intentionally read-only. It surfaces shifted spans, absolute-reference warnings, token counts, and optional before/after formula samples.\n\n## 5) Use workflow helpers instead of reinventing row logic\n\n```bash\n# Stateless batch writes\nasp write batch transform data.xlsx --ops @ops.json --dry-run\nasp write batch style data.xlsx --ops @style_ops.json --dry-run\n\n# Append rows into a detected region or table, respecting footer rows when present\nasp write append data.xlsx --sheet Revenue --table-name RevenueTable --from-csv rows.csv --header --dry-run\n\n# Clone one template row with preview-first planning\nasp write clone-template-row data.xlsx --sheet Inputs --source-row 8 --after 8 --count 3 --dry-run\n\n# Clone a contiguous row band repeatedly\nasp write clone-row-band data.xlsx --sheet Forecast --source-rows 12:16 --after 16 --repeat 4 --dry-run\n```\n\n## 6) Use a stateful session when the edit story gets complex\n\n```bash\nasp session start --base data.xlsx --workspace .\nasp session op --session <id> --ops @edit.json --workspace .\nasp session apply --session <id> <staged_id> --workspace .\nasp session materialize --session <id> --output result.xlsx --workspace .\n```\n\nAnd when you need proper history and branching:\n\n```bash\nasp session log --session <id> --workspace .\nasp session fork --session <id> scenario-a --workspace .\nasp session undo --session <id> --workspace .\nasp session redo --session <id> --workspace .\nasp session checkout --session <id> <op_id> --workspace .\n```\n\n## 7) Turn workbook interfaces into contracts with SheetPort\n\n```bash\n# Discover candidate ports from workbook structure\nasp sheetport manifest candidates model.xlsx\n\n# Validate or normalize a manifest\nasp sheetport manifest validate manifest.yaml\nasp sheetport manifest normalize manifest.yaml\n\n# Bind-check a workbook against a manifest\nasp sheetport bind-check model.xlsx manifest.yaml\n\n# Execute the manifest with JSON inputs\nasp sheetport run model.xlsx manifest.yaml --inputs @inputs.json\n```\n\n---\n\n## CLI overview\n\nThe primary CLI is **`asp`**.\n\n`agent-spreadsheet` remains available as a compatibility alias, so both of these are valid:\n\n```bash\nasp read sheets data.xlsx\nagent-spreadsheet read sheets data.xlsx\n```\n\n### Preferred command groups\n\n- `asp read ...`\n- `asp analyze ...`\n- `asp write ...`\n- `asp workbook ...`\n- `asp verify ...`\n- `asp session ...`\n- `asp sheetport ...`\n\n### Legacy aliases\n\nLegacy flat commands are still normalized to the new nested surface where practical. That makes migration easier for older prompts, docs, and automation.\n\n### Discoverability built into the CLI\n\nWhen an agent is unsure of payload shape, it can ask the tool directly:\n\n```bash\nasp operations                  # CLI-supported runtime subset\nasp registry --all              # complete host-independent registry + schemas\nasp schema read_cells\nasp example read_cells\nasp schema write batch transform\nasp example write batch transform\nasp schema session op transform.write_matrix\nasp example session op transform.write_matrix\n```\n\nCanonical machine calls use the same registry and dispatcher as other surfaces. `asp schema <canonical-op>` and `asp example <canonical-op>` project the native adapter contract: `resource_id` and, for verification, `baseline_resource_id` are omitted from required JSON because `--bind` and `--baseline` inject ephemeral resources. The host-independent `asp registry --all` remains unchanged.\n\n```bash\nasp op read_cells --bind data.xlsx --json '{\"sheet_name\":\"Sheet1\",\"selection\":{\"kind\":\"range\",\"ranges\":[\"A1:C10\"]}}'\nasp op verify_workbook --baseline base.xlsx --bind current.xlsx --json '{}'\necho '{\"action\":\"schema\"}' | asp op sheetport_manifest\n```\n\n`--bind` reads the current workbook, while `--baseline` supplies the second workbook only for `verify_workbook`. Canonical mutable CLI calls require exactly one persistence target: `--output <path>` writes a new file or `--in-place` atomically replaces the bound file; pure preview persists nothing and accepts neither. Durable fork, checkpoint, stage, and history operations are intentionally absent from stateless CLI discovery. This is a core design principle: **the surface should explain itself to the agent**.\n\n---\n\n## Command families\n\n## `read` — extraction and inspection\n\n| Command | Purpose |\n| --- | --- |\n| `asp read sheets <file>` | List sheets with summary metadata |\n| `asp read overview <file> <sheet>` | Detect regions, headers, and orientation |\n| `asp read values <file> <sheet> <range> [range...]` | Pull raw values for exact A1 ranges |\n| `asp read export <file> <sheet> <range>` | Export a bounded range to csv or grid json |\n| `asp read cells <file> <sheet> <target> [target...]` | Inspect exact cells/ranges with value/formula/cached/style snapshots |\n| `asp read page <file> <sheet> ...` | Deterministic sheet paging with `next_start_row` |\n| `asp read table <file> ...` | Structured table/region read with deterministic `next_offset` |\n| `asp read names <file>` | Named ranges, named formulas, and table items |\n| `asp read workbook <file>` | Workbook-level metadata |\n| `asp read layout <file> <sheet>` | Layout-aware rendering with widths, merges, borders, and optional ascii output |\n\n### Why these matter for agents\n\nAgents rarely need “the whole spreadsheet.” They need:\n- the right region\n- the right page\n- the right cells\n- just enough layout to understand intent\n\nThat is why the read surface combines **region detection**, **structured reads**, **detail inspection**, and **explicit continuation**.\n\n---\n\n## `analyze` — search, diagnostics, and impact understanding\n\n| Command | Purpose |\n| --- | --- |\n| `asp analyze find-value <file> <query>` | Search by value or by label semantics |\n| `asp analyze find-formula <file> <query>` | Text search within formulas |\n| `asp analyze formula-map <file> <sheet>` | Summarize formulas by complexity/frequency |\n| `asp analyze formula-trace <file> <sheet> <cell> <precedents\\|dependents>` | Dependency tracing with continuation |\n| `asp analyze scan-volatiles <file>` | Find volatile formulas |\n| `asp analyze sheet-statistics <file> <sheet>` | Density and type statistics |\n| `asp analyze table-profile <file>` | Header/type/cardinality profiling |\n| `asp analyze ref-impact <file> --ops @structure_ops.json` | Preflight structural edit impact without mutation |\n\n### Why this matters\n\nHeadless spreadsheet automation wins when it can **explain consequences**, not just execute mutations. `ref-impact`, `formula-trace`, and grouped diagnostics are all part of that story.\n\n---\n\n## `write` — safe mutations and workflow helpers\n\n| Command | Purpose |\n| --- | --- |\n| `asp write cells <file> <sheet> ...` | Direct shorthand cell edits |\n| `asp write import <file> <sheet> ...` | Import grid json or csv into a workbook range |\n| `asp write append ...` | Footer-aware row append into a region or table |\n| `asp write clone-template-row ...` | Clone one template row with preview-first planning |\n| `asp write clone-row-band ...` | Clone a multi-row template band repeatedly |\n| `asp write formulas replace ...` | Formula-only find/replace on a sheet/range |\n| `asp write name define|update|delete ...` | Named range mutation helpers |\n| `asp write batch transform ...` | Stateless transform pipeline |\n| `asp write batch style ...` | Stateless style edits |\n| `asp write batch formula-pattern ...` | Autofill-like formula application |\n| `asp write batch structure ...` | Rows/cols/sheets/copy/move style mutations |\n| `asp write batch column-size ...` | Column width operations |\n| `asp write batch sheet-layout ...` | Freeze panes, zoom, page setup, print area |\n| `asp write batch rules ...` | Data validation + conditional formatting |\n\n### Safety model\n\nMost mutating commands support a strict mode matrix:\n- `--dry-run`\n- `--in-place`\n- `--output <PATH>`\n\nThis matters for agents because it allows:\n- dry-run planning\n- non-destructive execution\n- explicit overwrite control\n\n### Formula maintenance\n\nFormula mutation is now a first-class surface:\n\n```bash\nasp write formulas replace data.xlsx Sheet1 --find '$64' --replace '$65' --dry-run\nasp write formulas replace data.xlsx Sheet1 --find 'Sheet1!' --replace 'Sheet2!' --range A1:Z100 --output fixed.xlsx\n```\n\n### Named range maintenance\n\n```bash\nasp write name define data.xlsx RevenueInput 'Inputs!$B$2'\nasp write name update data.xlsx RevenueInput 'Inputs!$B$2:$B$4' --in-place\nasp write name delete data.xlsx RevenueInput --in-place\n```\n\n---\n\n## `workbook` — file-level flows\n\n| Command | Purpose |\n| --- | --- |\n| `asp workbook create <path>` | Create a new workbook |\n| `asp workbook copy <source> <dest>` | Safe copy for edit workflows |\n| `asp workbook recalculate <file>` | Recalculate formulas via the configured backend |\n\n---\n\n## `verify` — proof, not vibes\n\n| Command | Purpose |\n| --- | --- |\n| `asp verify proof <baseline> <current>` | Prove target deltas and isolate new/resolved/preexisting errors |\n| `asp verify diff <original> <modified>` | Summary-first grouped workbook diff with optional paged details |\n\n### Why verification matters\n\nMost spreadsheet automation tools stop at “the edit applied.”\n\nagent-spreadsheet goes further:\n- did the target cells change the way we expected?\n- did the workbook introduce new errors?\n- which changes were direct edits vs recalculation fallout?\n- what changed overall, grouped in a way an agent can reason about?\n\nThis verification layer is a big part of why this project is a serious agent substrate rather than a utility script.\n\n---\n\n## `session` — event-sourced stateful editing\n\nThe session surface is for workflows that are too complex for a single stateless write.\n\n### What sessions give you\n- persistent editing state\n- staged dry-run operations\n- compare-and-swap apply semantics\n- logs and replayability\n- branch/switch/fork flows\n- undo / redo / checkout\n- explicit materialization back to a workbook file\n\n### Canonical loop\n\n```bash\nasp session start --base model.xlsx --workspace .\nasp session op --session <id> --ops @ops.json --workspace .\nasp session apply --session <id> <staged_id> --workspace .\nasp session materialize --session <id> --output result.xlsx --workspace .\n```\n\n### History and branching\n\n```bash\nasp session log --session <id> --workspace .\nasp session branches --session <id> --workspace .\nasp session fork --session <id> experiment-b --workspace .\nasp session switch --session <id> experiment-b --workspace .\nasp session undo --session <id> --workspace .\nasp session redo --session <id> --workspace .\nasp session checkout --session <id> <op_id> --workspace .\n```\n\nUse sessions when you want **repeatability, auditability, and multi-step safety**.\n\n---\n\n## `sheetport` — spreadsheet interfaces as executable contracts\n\nSheetPort is the workflow surface for turning workbook inputs/outputs into explicit machine contracts.\n\n### Manifest lifecycle\n\n```bash\nasp sheetport manifest candidates model.xlsx\nasp sheetport manifest schema\nasp sheetport manifest validate manifest.yaml\nasp sheetport manifest normalize manifest.yaml\n```\n\n### Bind-check + run\n\n```bash\nasp sheetport bind-check model.xlsx manifest.yaml\nasp sheetport run model.xlsx manifest.yaml --inputs @inputs.json --freeze-volatile\n```\n\nUse this when you want a workbook to behave less like an opaque file and more like a **declared service interface**.\n\n---\n\n## Output contracts for agents\n\n### Canonical vs compact shapes\n\nAll commands default to JSON. Many also support:\n\n```bash\n--shape canonical\n--shape compact\n```\n\nPolicy:\n- **canonical** keeps the full stable schema\n- **compact** removes wrapper noise where the contract allows it while preserving continuation fields and command-specific semantics\n\nShape policy:\n- **Canonical (default):** preserve the full response schema.\n- **range-values:** returns a stable `values: [...]` envelope in both canonical and compact modes.\n- **range-values default encoding:** dense JSON (`dense.encoding = \"dense_v1\"`) with `dictionary` + run-length `row_runs`.\n- **range-values `--include-formulas`:** includes sparse formula coordinates in dense mode (`dense.formulas`), or a matrix in explicit `json` format.\n- **read-table and sheet-page: compact preserves the active branch and continuation fields (`next_offset`, `next_start_row`)**.\n- **formula-trace compact:** omits per-layer `highlights` while preserving `layers` and `next_cursor`.\n\n### Deterministic pagination loops\n\n```bash\n# sheet-page continuation\nasp read page data.xlsx Sheet1 --format compact --page-size 200\nasp read page data.xlsx Sheet1 --format compact --page-size 200 --start-row 201\n\n# read-table continuation\nasp read table data.xlsx --sheet \"Sheet1\" --table-format values --limit 200 --offset 0\nasp read table data.xlsx --sheet \"Sheet1\" --table-format values --limit 200 --offset 200\n```\n\n#### `sheet-page` machine contract\n- Inspect top-level `format` before reading payload fields.\n- `format=full`: read top-level `rows` plus optional `header_row` and `next_start_row`.\n- `format=compact`: read `compact.headers`, `compact.header_row`, `compact.rows` plus optional `next_start_row`.\n- `format=values_only`: read `values_only.rows` plus optional `next_start_row`.\n- Continuation is always driven by top-level `next_start_row` when present.\n- Global `--shape compact` preserves the active `sheet-page` branch; it does not flatten `sheet-page` payloads.\n\nMachine continuation example:\n1. Request page 1 without `--start-row`.\n2. If `next_start_row` is present, call `sheet-page` again with `--start-row <next_start_row>`.\n3. Stop when `next_start_row` is omitted.\n\n### Self-describing payloads\n\nWhen the agent is unsure what to send, ask for a schema or example:\n\n```bash\nasp schema write batch rules\nasp example write batch rules\nasp schema session op structure.insert_rows\nasp example session op structure.insert_rows\n```\n\n### Batch payload examples\n\nAll batch payloads use a top-level envelope object. Most commands require `{\"ops\":[...]}`; `column-size-batch` prefers `{\"sheet_name\":\"...\",\"ops\":[...]}` and also accepts per-op `sheet_name` inside `{\"ops\":[...]}`.\n\n##### transform-batch payloads (`@transform_ops.json`)\n- Minimal: `{\"ops\":[{\"kind\":\"fill_range\",\"sheet_name\":\"Sheet1\",\"target\":{\"kind\":\"range\",\"range\":\"B2:B4\"},\"value\":\"0\"}]}`\n- Advanced: `{\"ops\":[{\"kind\":\"replace_in_range\",\"sheet_name\":\"Sheet1\",\"target\":{\"kind\":\"region\",\"region_id\":1},\"find\":\"N/A\",\"replace\":\"\",\"match_mode\":\"contains\",\"case_sensitive\":false,\"include_formulas\":true}]}`\n\n##### style-batch payloads (`@style_ops.json`)\n- Minimal: `{\"ops\":[{\"sheet_name\":\"Sheet1\",\"target\":{\"kind\":\"range\",\"range\":\"B2:B2\"},\"patch\":{\"font\":{\"bold\":true}}}]}`\n- Advanced: `{\"ops\":[{\"sheet_name\":\"Sheet1\",\"target\":{\"kind\":\"cells\",\"cells\":[\"B2\",\"B3\"]},\"patch\":{\"number_format\":\"$#,##0.00\",\"alignment\":{\"horizontal\":\"right\"}},\"op_mode\":\"merge\"}]}`\n\n##### write batch formula-pattern payloads (`@formula_ops.json`)\n- Minimal: `{\"ops\":[{\"sheet_name\":\"Sheet1\",\"target_range\":\"C2:C4\",\"anchor_cell\":\"C2\",\"base_formula\":\"B2*2\"}]}`\n- Advanced: `{\"ops\":[{\"sheet_name\":\"Sheet1\",\"target_range\":\"C2:E4\",\"anchor_cell\":\"C2\",\"base_formula\":\"B2*2\",\"fill_direction\":\"both\",\"relative_mode\":\"excel\"}]}`\n- `relative_mode` valid values: `excel`, `abs_cols`, `abs_rows`\n\n##### structure-batch payloads (`@structure_ops.json`)\n- Minimal: `{\"ops\":[{\"kind\":\"rename_sheet\",\"old_name\":\"Summary\",\"new_name\":\"Dashboard\"}]}`\n- Advanced: `{\"ops\":[{\"kind\":\"copy_range\",\"sheet_name\":\"Sheet1\",\"dest_sheet_name\":\"Summary\",\"src_range\":\"A1:C4\",\"dest_anchor\":\"A1\",\"include_styles\":true,\"include_formulas\":true}]}`\n\n##### column-size-batch payloads (`@column_size_ops.json`)\n- Minimal (preferred): `{\"sheet_name\":\"Sheet1\",\"ops\":[{\"range\":\"A:A\",\"size\":{\"kind\":\"width\",\"width_chars\":12.0}}]}`\n- Advanced (preferred): `{\"sheet_name\":\"Sheet1\",\"ops\":[{\"target\":{\"kind\":\"columns\",\"range\":\"A:C\"},\"size\":{\"kind\":\"auto\",\"min_width_chars\":8.0,\"max_width_chars\":24.0}}]}`\n- Also accepted (harmonized shape): `{\"ops\":[{\"sheet_name\":\"Sheet1\",\"range\":\"A:A\",\"size\":{\"kind\":\"width\",\"width_chars\":12.0}}]}`\n\n##### sheet-layout-batch payloads (`@layout_ops.json`)\n- Minimal: `{\"ops\":[{\"kind\":\"freeze_panes\",\"sheet_name\":\"Sheet1\",\"freeze_rows\":1,\"freeze_cols\":1}]}`\n- Advanced: `{\"ops\":[{\"kind\":\"set_page_setup\",\"sheet_name\":\"Sheet1\",\"orientation\":\"landscape\",\"fit_to_width\":1,\"fit_to_height\":1}]}`\n\n##### rules-batch payloads (`@rules_ops.json`)\n- Minimal: `{\"ops\":[{\"kind\":\"set_data_validation\",\"sheet_name\":\"Sheet1\",\"target_range\":\"B2:B4\",\"validation\":{\"kind\":\"list\",\"formula1\":\"\\\"A,B,C\\\"\"}}]}`\n- Advanced: `{\"ops\":[{\"kind\":\"set_conditional_format\",\"sheet_name\":\"Sheet1\",\"target_range\":\"C2:C10\",\"rule\":{\"kind\":\"expression\",\"formula\":\"C2>100\"},\"style\":{\"fill_color\":\"#FFF2CC\",\"bold\":true}}]}`\n\n`write batch formula-pattern` clears cached results for touched formula cells; run `workbook recalculate` to refresh computed values.\n\n### Formula parse policy\n\nFormula-aware commands support:\n\n```bash\n--formula-parse-policy fail|warn|off\n```\n\n- `fail` — abort\n- `warn` — continue and attach grouped diagnostics\n- `off` — skip silently\n\nThis lets agents choose between strictness and progress depending on the workflow.\n\n### CLI reference excerpts\n\n- `read values <file> <sheet> <range> [range...] [--format dense\\|json\\|values\\|csv] [--include-formulas]`\n- `read cells <file> <sheet> <target> [target...] [--include-empty]`\n- `read page <file> <sheet> --format <full|compact|values_only> [--start-row ROW] [--page-size N]`\n- `workbook create <path> [--sheets Inputs,Calc,...] [--overwrite]`\n- `analyze find-value <file> <query> [--sheet S] [--mode value\\|label] [--label-direction right\\|below\\|any]`\n- `write batch transform <file> --ops @ops.json (--dry-run\\|--in-place\\|--output PATH)`\n\n#### Formula write-path provenance (`write_path_provenance`)\n\nFormula-writing commands emit optional provenance metadata for troubleshooting:\n- `written_via`: write path (`edit`, `transform_batch`, `apply_formula_pattern`)\n- `formula_targets`: sheet/cell or sheet/range targets touched by formula writes\n\nDebug compare workflow:\n1. Apply the same formula target via two paths.\n2. Compare `write_path_provenance.written_via` and `formula_targets` in responses.\n3. Use `inspect-cells` plus `recalculate` to compare resulting behavior.\n\n#### Financial presentation starter defaults\n- Keep label columns (often column A) explicitly sized (roughly `24–36` chars) to prevent clipping.\n- Apply consistent number formats by semantic type:\n  - Currency: `\"$\"#,##0.00_);[Red](\"$\"#,##0.00)`\n  - Percent: `0.0%`\n  - Integer/count: `#,##0`\n- Apply `sheet-layout-batch` freeze panes after header layout stabilizes.\n\nJSON output is compact by default; use `--quiet` to suppress warnings.\nGlobal `--output-format csv` is currently unsupported; use command-specific CSV options like `read table --table-format csv`.\n\n---\n\n## MCP server quickstart\n\nThe MCP surface is the stateful server version of agent-spreadsheet.\n\nUse it when you want:\n- workbook caching across calls\n- fork lifecycle instead of stateless file replacement\n- multi-turn agent workflows\n- screenshots and richer server-side orchestration\n\n### Claude Code / Claude Desktop\n\nAdd to `~/.claude.json` or project `.mcp.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"spreadsheet\": {\n      \"command\": \"agent-spreadsheet-mcp\",\n      \"args\": [\"--workspace-root\", \"/path/to/workbooks\", \"--transport\", \"stdio\"]\n    }\n  }\n}\n```\n\n### Docker\n\n```json\n{\n  \"mcpServers\": {\n    \"spreadsheet\": {\n      \"command\": \"docker\",\n      \"args\": [\n        \"run\", \"-i\", \"--rm\",\n        \"-v\", \"/path/to/workbooks:/data\",\n        \"ghcr.io/psu3d0/agent-spreadsheet-mcp:latest-full\",\n        \"--transport\", \"stdio\"\n      ]\n    }\n  }\n}\n```\n\n`:latest` is the read-only slim image (write/fork/recalc tools disabled); `:latest-full` includes the write tools and recalculation (LibreOffice-backed).\n\n### HTTP mode\n\n```bash\nagent-spreadsheet-mcp --workspace-root /path/to/workbooks\n# -> http://127.0.0.1:8079  (POST /mcp, and the canonical route under /v1)\n```\n\nThe same process also serves a plain canonical HTTP route for programmatic clients that do not speak MCP:\n\n| Route | Purpose |\n| --- | --- |\n| `POST /v1/op/{operation}` | Run a canonical operation; the body is the canonical input object, the response is the canonical envelope |\n| `GET /v1/operations` | Runtime-filtered operation discovery for this process |\n| `GET /v1/registry` | Full canonical registry projection plus the error schema |\n| `GET /v1/artifacts/{handle}` | Bytes for an `artifact:sha256:<hex>` handle produced by `screenshot_sheet` |\n\n```bash\ncurl -sS -X POST http://127.0.0.1:8079/v1/op/list_workbooks -d '{}'\n```\n\nCanonical errors return the canonical error envelope with the status mapped from the error code (400 invalid request, 404 unknown operation / resource, 409 revision conflict, 500 operation failed, 501 capability unavailable). Like `/mcp`, `/v1` has **no authentication**; the loopback default bind is the security boundary. See [docs/architecture/canonical-http-route.md](docs/architecture/canonical-http-route.md).\n\n### Configuration\n\nEvery setting is available as a CLI flag (`agent-spreadsheet-mcp --help`), an environment variable, or a config file key (`--config file.yaml`). CLI takes precedence over the config file.\n\n| Variable | Default | Description |\n| --- | --- | --- |\n| `SPREADSHEET_MCP_WORKSPACE` | `.` | Workspace root containing spreadsheet files |\n| `SPREADSHEET_MCP_WORKBOOK` | none | Lock the server to a single workbook path |\n| `SPREADSHEET_MCP_EXTENSIONS` | `xlsx,xlsm,xls,xlsb` | Comma-separated list of allowed workbook extensions |\n| `SPREADSHEET_MCP_ENABLED_TOOLS` | all tools | Restrict execution to the provided tool names (comma-separated) |\n| `SPREADSHEET_MCP_TRANSPORT` | `http` | Transport to expose (`http` or `stdio`) |\n| `SPREADSHEET_MCP_HTTP_BIND` | `127.0.0.1:8079` | HTTP bind address when using http transport |\n| `SPREADSHEET_MCP_RECALC_ENABLED` | `false` | Enable write/recalc tools (uses the native Formualizer backend by default) |\n| `SPREADSHEET_MCP_RECALC_BACKEND` | `auto` | Recalc backend preference: `auto`, `formualizer`, or `libreoffice` |\n| `SPREADSHEET_MCP_MAX_CONCURRENT_RECALCS` | `2` | Max concurrent LibreOffice instances |\n| `SPREADSHEET_MCP_VBA_ENABLED` | `false` | Enable VBA introspection tools (read-only) |\n| `SPREADSHEET_MCP_ALLOW_OVERWRITE` | `false` | Allow `save_fork` to overwrite original workbook files |\n| `SPREADSHEET_MCP_CACHE_CAPACITY` | `5` | Maximum number of workbooks kept in memory |\n| `SPREADSHEET_MCP_TOOL_TIMEOUT_MS` | `30000` | Tool request timeout in milliseconds |\n| `SPREADSHEET_MCP_MAX_RESPONSE_BYTES` | `1000000` | Max response size in bytes |\n| `SPREADSHEET_MCP_MAX_PAYLOAD_BYTES` | `65536` | Max tool payload size in bytes before truncation |\n| `SPREADSHEET_MCP_MAX_CELLS` | `10000` | Max cells per tool payload before truncation |\n| `SPREADSHEET_MCP_MAX_ITEMS` | `500` | Max items per tool payload before truncation |\n| `SPREADSHEET_MCP_OUTPUT_PROFILE` | `token_dense` | Output profile for tool responses (`token_dense` or `verbose`) |\n| `SPREADSHEET_MCP_SLIM_SURFACE` | `true` | Canonical-only router; set `false` to add legacy 0.13 tool names |\n| `SPREADSHEET_MCP_SCREENSHOT_DIR` | `<workspace_root>/screenshots` | Directory to write screenshot PNGs |\n| `SPREADSHEET_MCP_PATH_MAP` | none | Path mapping(s) `INTERNAL=CLIENT` to include client-visible paths in responses (comma-separated; useful for Docker volume mounts) |\n\nSetting any of the timeout/limit variables (`TOOL_TIMEOUT_MS`, `MAX_RESPONSE_BYTES`, `MAX_PAYLOAD_BYTES`, `MAX_CELLS`, `MAX_ITEMS`) to `0` disables that limit.\n\n---\n\n## MCP tool surface\n\nThe default MCP router is generated from the canonical operation registry. A write-capable baseline exposes 27 operations: 17 discovery/read/analysis operations and 10 write/lifecycle operations. Capability-backed deployments can add `screenshot_sheet`, `sheetport_manifest`, `execute_sheetport`, and `inspect_vba`, for up to 31. Nineteen canonical operations are read-only.\n\nEach tool uses the registry descriptor's closed input schema and returns the canonical `schema_version` / `operation` / `resource_id` / `revision_id` / `data` envelope. A `revision_id` identifies the complete observable resource state, not only workbook cell-content bytes: recalculation, evaluation/provenance state, or lifecycle metadata can advance it without a content edit. Clients must use the revision from the latest response envelope for compare-and-swap, cursor, and freshness decisions rather than computing or retaining a content hash. Static MCP annotations report the descriptor's worst-case risk; descriptions identify action-specific risk. `close_workbook` is excluded because cache eviction is runtime administration.\n\nFor the complete operation list and contracts, see [Canonical Operation Surface](docs/architecture/canonical-operation-surface.md). To add the legacy 0.13 names for one compatibility window, set `SPREADSHEET_MCP_SLIM_SURFACE=false`; shared names use their legacy schema and envelope in compatibility mode and are registered only once.\n\n## JS SDK\n\n`agent-spreadsheet-sdk` is the app-facing integration layer — the one surface JS/TS code should target.\n\nIt provides generated canonical convenience methods, legacy input aliases, unchanged canonical envelopes, and typed capability errors. The complete 31-operation manifest supplies schemas and methods, while availability always comes from the selected live backend.\n\n**Backends** are a configuration choice, not separate APIs:\n- **MCP backend** — connect to a running `agent-spreadsheet-mcp` server (shared state, forks, multi-client)\n- **Embedded WASM backend** — the engine runs in-process on workbook bytes, no server or filesystem required (browser, Node, serverless). The `agent-spreadsheet-wasm` crate in this repo is that backend's build artifact; it is an internal dependency of the SDK, not a package you consume directly.\n\nInstall:\n\n```bash\nnpm i agent-spreadsheet-sdk\n```\n\nBackend status: MCP backend is stable and negotiates operations through live tool discovery (or an explicit `supportedOperations` list); the embedded WASM backend derives support from its generated binding's `operations()` descriptors and is tested against the real wasm-bindgen Node package in CI.\n\n---\n\n## Recalc backends\n\nFormula recalculation is pluggable.\n\n| Backend | How | Default | Best for |\n| --- | --- | --- | --- |\n| **Formualizer** | Native Rust engine | **Yes** | Fast default recalc with no external dependency |\n| **LibreOffice** | Headless `soffice` | Docker `:latest-full` / explicit builds | Maximum compatibility and screenshot flows |\n\nFeature notes:\n- `recalc-formualizer` is enabled by default\n- `recalc-libreoffice` is available for LibreOffice-backed builds\n- read and many write flows still work without recalc; only recalculate itself requires a backend\n\n---\n\n## Docker images\n\nPublished at `ghcr.io/psu3d0/agent-spreadsheet-mcp`:\n\n| Image | Size | Recalc | Best for |\n| --- | --- | --- | --- |\n| `latest` | ~15 MB | No | Read-only analysis and lightweight agent deployments |\n| `latest-full` | ~800 MB | Yes | Write + recalc + screenshots |\n\nExamples:\n\n```bash\n# Read-only\ndocker run -v /path/to/workbooks:/data -p 8079:8079 ghcr.io/psu3d0/agent-spreadsheet-mcp:latest\n\n# Write + recalc\ndocker run -v /path/to/workbooks:/data -p 8079:8079 ghcr.io/psu3d0/agent-spreadsheet-mcp:latest-full\n```\n\n---\n\n## Workspace layout\n\n```text\nagent-spreadsheet/\n├── crates/\n│   ├── agent-spreadsheet/        # shared engine + asp / agent-spreadsheet CLI\n│   ├── agent-spreadsheet-mcp/        # MCP server adapter\n│   └── agent-spreadsheet-wasm/   # experimental WASM-facing wrapper\n├── npm/\n│   ├── agent-spreadsheet/      # npm CLI wrapper\n│   └── agent-spreadsheet-sdk/    # JS SDK\n├── docs/                       # architecture and design docs\n├── benchmarks/                 # scenario budget regression harnesses\n└── .github/workflows/          # CI, release, docker builds\n```\n\n### Package roles\n\n| Package | Role |\n| --- | --- |\n| `agent-spreadsheet` | shared engine and CLI binaries |\n| `agent-spreadsheet-mcp` | stateful MCP transport + server surface |\n| `agent-spreadsheet-wasm` | WASM-facing byte/session wrapper |\n| `agent-spreadsheet` | npm wrapper for the CLI binary |\n| `agent-spreadsheet-sdk` | JS SDK for MCP/WASM-style integrations |\n\n---\n\n## Architecture notes\n\n![Architecture Overview](https://raw.githubusercontent.com/PSU3D0/agent-spreadsheet-mcp/main/assets/architecture_overview.jpeg)\n\nCore ideas:\n- **one semantic core** shared across CLI, MCP, session, and WASM-facing work\n- **region detection** for structural awareness\n- **token-efficient defaults** so agents do not over-read spreadsheets\n- **verification as a first-class feature** rather than an afterthought\n- **workflow helpers** for the common mutations that spreadsheet agents repeatedly struggle with\n\nToken-efficient workflow reference:\n\n![Token Efficiency Workflow](https://raw.githubusercontent.com/PSU3D0/agent-spreadsheet-mcp/main/assets/token_efficiency.jpeg)\n\nRecommended progression:\n1. discover workbook + sheets\n2. detect regions / table-like structures\n3. inspect only the exact region or cells needed\n4. mutate with dry-run or session staging\n5. recalculate if needed\n6. verify proof and review grouped diffs\n\n---\n\n## Development\n\n```bash\n# Build everything\ncargo build --release\n\n# Run formatting, lint, and tests\ncargo fmt --all -- --check\ncargo clippy --workspace --all-targets -- -D warnings\ncargo test --workspace\n```\n\nLocal MCP iteration:\n\n```bash\nWORKSPACE_ROOT=/path/to/workbooks ./scripts/local-docker-mcp.sh\n```\n\nOr point your MCP client directly at the local binary:\n\n```json\n{\n  \"mcpServers\": {\n    \"spreadsheet\": {\n      \"command\": \"./target/release/agent-spreadsheet-mcp\",\n      \"args\": [\"--workspace-root\", \"/path/to/workbooks\", \"--transport\", \"stdio\"]\n    }\n  }\n}\n```\n\n---\n\n## Read more\n\n- CLI package README: [`npm/agent-spreadsheet`](./npm/agent-spreadsheet/)\n- Core crate README: [`crates/agent-spreadsheet`](./crates/agent-spreadsheet/)\n- MCP crate README: [`crates/agent-spreadsheet-mcp`](./crates/agent-spreadsheet-mcp/)\n- JS SDK README: [`npm/agent-spreadsheet-sdk`](./npm/agent-spreadsheet-sdk/)\n- WASM wrapper README: [`crates/agent-spreadsheet-wasm`](./crates/agent-spreadsheet-wasm/README.md)\n- Packaging/versioning notes: [`docs/PACKAGING.md`](./docs/PACKAGING.md)\n- Heuristics and region detection: [`docs/HEURISTICS.md`](./docs/HEURISTICS.md)\n- Recalc architecture: [`docs/RECALC.md`](./docs/RECALC.md)\n\n---\n\n## License\n\nApache-2.0\n",
  "bytes": 38426,
  "sha": "f3c05d579b11ea764551d6d315c355272865624573b0ef8e7b3b57eeab151474",
  "repo_slug": "psu3d0/agent-spreadsheet",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_psu3d0_agent_spreadsheet_f1c53f96/readme"
}