logisheets-mcp
This server is an MCP interface to a real spreadsheet engine, letting an agent build, query, and maintain Excel workbooks as named, schema-driven blocks rather than raw cell coordinates.
Workbook lifecycle: Open a fresh or existing
.xlsxfrom disk or base64, save back to a real file (optionally resolving block references to plain A1 for Excel compatibility), or export as base64.Structured tables (blocks): Create named tables with typed fields (string, number, boolean, enum, date/datetime), define the row-key column, add/delete/reorder rows, and write cells by
(block, row_key, field).Adopt existing tables: Convert a raw cell range into a block in place, inferring field names from a header row and auto-detecting the key column.
Declarative field rules: Set a column-wide formula (
#FIELDreferences, named-row lookups), validation rules, and editability rules — computed fields are engine-owned and reject direct writes.Analyze and inspect: List all blocks and their schemas, describe a block in detail (rules, keys, values), and scan for validation violations.
Formulas & evaluation: Evaluate any Excel-style formula in a scratch cell (including
BLOCKREFlookups) without writing to the sheet.Scenario exploration: Dry-run a single change or a grid of scenarios via
preview_changeswith optional watched cells, and solve backwards for an input withgoal_seek— both run on temporary branches without modifying the workbook.Dependency tracing: Trace what a cell reads and what reads it, using the engine's dependency graph, with semantic block/cell naming.
Derived summaries: Create and edit analysis blocks (totals rows) and pivots that stay live with their source; refresh pivots to include new groups.
Charts: Create charts from blocks (bound by field names, so they follow row/column changes) or from arbitrary A1 ranges; list, update (type, series, axes, labels, scaling), and delete charts.
Raw cell access: Escape hatch to read/write arbitrary cells via
get_cells/set_cellsfor unstructured data.Workbook organization: Create named sheets on demand.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@logisheets-mcpCreate a 'MonthlySales' block with rows for Jan–Mar, add a total column as =units*price, and save it to sales.xlsx"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
logisheets-mcp
A real spreadsheet engine your agent can think in. Excel-compatible formulas
it doesn't have to do in its head, a table it addresses by name instead of by
coordinate, and a genuine .xlsx at the end that a person can open, audit and
keep using.
An MCP server over LogiSheets, a spreadsheet engine written in Rust. MIT, runs on your machine, opens no sockets.
The trouble with a grid
Ask a model for a five-year projection and it writes twenty formulas, each with
the row number adjusted by hand. That is where the silent mistake lives: one of
them reads B7 where it meant B8, the total looks plausible, and nothing
raises an error.
Then the sheet moves. Someone inserts a row at the top, deletes a year, adds a column. Every coordinate the model was holding is now off by one and it has no way to notice, so it spends the next turns re-reading cells to work out where things went instead of on the question you asked.
And every "what if" costs a round trip — write the input, recalculate, read the output, put it back. Sixteen scenarios is sixteen of those, and a scan that dies half way leaves a scenario behind in your model.
Related MCP server: Excel MCP Server
Blocks
A block is a named table on the sheet. Rows have keys, columns have names, and everything is addressed by those rather than by position.
A field's formula is stated once, for the whole column — not per cell. Add a row and it computes. There is no twentieth formula to get wrong.
A reference names what it means: the
pvfield of the row keyedY3. Insert a row above it and the reference still says the same thing, because it never said "row 8".The engine owns computed values. A formula field cannot be overwritten with a number the model worked out itself.
create_block proj fields: year, fcf, df, pv
set_field_rule proj.pv = fcf × df ← once, for the column
add_block_rows Y1 … Y5
describe_block proj
→ Y1 147.2727 Y2 144.5950 Y3 141.9660 Y4 139.3848 Y5 136.8506
… the sheet is then reshaped: two rows inserted at the top, a column at the left …
describe_block proj
→ Y3 141.9660 ← same answer, same address, nothing re-derivedBlocks are created by the agent as it works, so nothing needs preparing. Point it
at a blank workbook or at a spreadsheet someone emailed you — convert_to_block
adopts a table that is already in ordinary cells, reading the field names off the
header row and working out which column is the key.
The second session
The conversation that builds a spreadsheet is almost never the conversation that has to answer a question about it. A week later there is a new session, with none of the context, holding only the file — and what the file records is what that session can know.
A grid records coordinates. =B11*$B$3*(1-$B$4) is correct and means nothing
until the agent fetches the label column and infers that A3 describes B3.
The schema is where the meaning goes instead, and it is written into the
.xlsx: field names, the key column, which fields the engine computes, and the
rule behind each one. One list_blocks call and the workbook introduces itself;
one describe_block and the rules come back as
#FIELD("revenue")*BLOCKREF("assum","margin","v") — an explanation rather than
a second lookup problem.
The schema still only says what shape the records are. What they mean is
prose, so a block carries a description: a sentence or two on create_block, or
set_block_description for a table adopted later, saying what one row is, what
the non-obvious fields hold, and what a later reader must not touch. It is
stored in the file and comes back from describe_block, which is the difference
between the next session reading the intent and inferring it from column names.
src/cold-read.test.ts pins that down rather than
asserting it. It builds a model in one session, saves it, and reopens the file
in a second session sharing nothing with the first — own server, own workbook,
no memory. Then: list_blocks recovers every block's fields, key field,
computed fields and row count in one call; every returned rule is checked to
contain #FIELD or BLOCKREF and no A1 coordinate at all; the fresh
session writes a BLOCKREF formula from orientation alone and the engine agrees
with arithmetic done independently in the test; and trace names what reads an
assumption before anyone edits it. Cost is metered on the wire, over the same
text a host shows the model: 540 B for a five-row model, 545 B for a
hundred-and-five-row one, one call each. Reading a schema is O(columns);
reading a grid to understand it is O(cells). Asking for the data still costs
what the data costs — 11 kB for those 105 rows — and the point is that the
second session gets to choose.
Longer version, with the reasoning: docs/the-second-session.md.
Charts that recompute
An agent asked for a chart usually renders an image. The image is right once, and then the human changes an assumption and it is a picture of a number that is no longer true.
chart_from_block writes a chart into the workbook instead, and a chart there
stores references, never values:
chart_from_block rev value_fields: q1, q2 category_field: region
→ <c:val><c:numRef><c:f>Rev!$B$1:$B$3</c:f></c:numRef>That is a native Excel c:chartSpace in the saved .xlsx — the same object
Excel writes itself. Edit a source cell and the chart follows, in Excel or here.
Add a region to the block and it appears in the chart on its own, because the
series is bound to the field, not to the cells the field happened to occupy
when the chart was made: inserting rows or columns cannot leave it pointing
somewhere wrong. chart_insert does the same for arbitrary A1 ranges, for data
that never became a block.
src/agent-loop.test.ts asserts this from the file's
bytes rather than from the tool's return value: build a block, chart it, save,
unzip the .xlsx and check that the chart part exists and that its series are
<c:f> references into the sheet.
Benchmarks
Measured, not asserted. Against the two other MCP servers that work on a local
.xlsx — spreadsheet-kit 0.11.1,
which has its own Rust recalc engine, and
excel-mcp-server 0.1.8, the
most-installed one, on openpyxl:
this | spreadsheet-kit | excel-mcp-server | |
Write a formula, read its value | 30 | 30 |
|
Five-year DCF, value per share | 20.803603 · 15 calls | 20.803603 · 6 calls | formula text |
4×4 sensitivity, 16 answers | 1 call, 950 B | 16 calls, 1245 B | can't |
Solve backwards for an input | 1 call, 202 B | 18 calls, 1399 B | can't |
Reopen it later and explain it | 4 calls, 2.4 kB | 5 calls, 21 kB | 2 calls, 24 kB |
Answer again after the shape changed | 19.383943 |
| formula text |
Keep a handed-over file's features | 8 of 8 | 8 of 8 | 8 of 8 |
Reproduce it — one file per task, and each one runs all three servers:
npm run build # ours is driven as dist/cli.js
python3 bench/t1_compute.py # bench/t*.pyThe other two contestants have to be reachable first: spreadsheet-kit as an
amd64 Docker image, excel-mcp-server in a virtualenv at $BENCH_WORK/.venv
(default /tmp/bench-work). See bench/contestants.py
for exactly how each is started.
The tasks were committed before any other server's tool list was read
(bench/TASKS.md), every expected value is derived
independently in Python rather than read off a server's output, and tasks we
expected to lose are in the list on purpose.
Three caveats, so the table is not read for more than it says. "=SUM(A1:A2)" is
not a bug: openpyxl stores formulas without evaluating them, so that server
writes correct models but cannot answer a question about one. spreadsheet-kit is
a genuine peer, correct on everything it can attempt, and builds the model in
fewer calls than we do — our extra calls declare a schema, which is the trade
that pays off in the rows below. And on the reading row each server was reading
back a file it wrote, so only half of that margin transfers to a spreadsheet
that came from a person. The last row started at 0 of 8; writing the task is what
found that saves were dropping everything the engine had no opinion about.
Install
Requires Node 20+.
npm install -g logisheets-mcpFor Claude Desktop, add to claude_desktop_config.json (macOS:
~/Library/Application Support/Claude/claude_desktop_config.json; Windows:
%APPDATA%\Claude\claude_desktop_config.json), then restart:
{
"mcpServers": {
"logisheets": {
"command": "npx",
"args": ["-y", "logisheets-mcp"]
}
}
}Any MCP host that spawns a stdio server works the same way — Cursor reads the
same block from ~/.cursor/mcp.json.
Try it
Build me a three-year revenue model: 100 units at $9.50 growing 40% a year, with a 30% cost of goods. Then save it to ~/model.xlsx.
The numbers come back from the engine rather than from the model's guesses, and
the .xlsx has live formulas in it — change an assumption in Excel and watch it
recompute. To see the same thing with no LLM involved,
npm run build && npm run demo drives the real server over stdio and checks
every claim as it goes.
Tools
Thirty-one by default. Tool-selection accuracy falls as the list grows and every description costs context on every turn.
Tool | What it does |
| Start a fresh workbook, or load an existing |
| Write a real |
| The file as base64, for hosts with no shared filesystem. |
| Every sheet and block, plus where the next block should go. |
| A block's schema, keys, field rules, description, and optionally its values. |
| Evaluate a formula and return the value. Nothing is stored. |
| Create a named table. First field is the row key. |
| Adopt a table that is already in ordinary cells, in place. |
| Write what a block is for, in prose, into the file. |
| Add records — at the end, or |
| Remove records. |
| Reorder rows by key. Presentation only: no value changes. |
| Write cells by |
| Give a field a formula, a validation rule, or an editability rule. |
| A totals row under a table, generated from a recipe rather than written. |
| Change which fields it aggregates and how, keeping the ref name. |
| Cross-tabulate a block: one row per group, one column per value, live. |
| Reshape a pivot in place — and the only way to repair a broken one. |
| Bring a pivot's rows and columns back in line with its source. |
| Which cells break their field's validation rule, and why. |
| What edits would do, without doing them — one hypothetical, or a whole grid of scenarios in a single call. |
| What a cell reads, and what reads it, from the dependency graph. |
| What input makes an output hit a target. Searches inside the engine. |
| Add a sheet. |
| Chart a block by naming its fields. Follows rows added later. |
| Chart arbitrary A1 ranges — the raw-cell counterpart. |
| The charts on a sheet: type, title, and the ranges each series reads. |
| Reconfigure a chart in place — type, series, axes, labels. |
| Remove a chart. |
| Raw-cell escape hatch for data with no structure. |
Formulas are Excel-compatible plus BLOCKREF(block, key, field) for reading a
block cell by name. Inside a field rule, #FIELD("name") is the same row's
sibling and #FIELD("name", "key") is another row of the same block — the row
carrying that key, never a positional offset.
preview_changes and goal_seek are the two that change how a model gets
explored: each scenario runs on its own temp branch and is discarded, so a 4×4
sensitivity grid is one call returning sixteen numbers with nothing written to
the workbook, and an inverse solve is one call rather than one per bisection
step. trace answers the question formula text cannot — not what a cell reads,
but what reads it, which is what you want before touching an assumption.
Analysis blocks and pivots are summaries the engine derives. The agent
declares a recipe — which block, which fields, which function — and the engine
generates every formula from it, so renaming a source field rebuilds the summary
instead of breaking it, and a row added later is already counted. Both land in
ordinary blocks, so BLOCKREF("by_region", "East", "Q2") is one cell of a
cross-tab and can feed the next calculation. The alternative an agent reaches
for otherwise is reading the table into its context, adding it up and writing
the answer down, which produces a constant that is wrong from the next row on.
One thing about pivots is worth knowing before trusting one: the numbers are
live, but the shape is not. No formula can add a row, so a group that first
appears in the source after the pivot was built is simply absent — every number
correct, the table incomplete, nothing that looks wrong. describe_block names
the missing groups and refresh_pivot reinstates them, which is why the pair
ships in the core surface rather than behind the flag.
Set LOGISHEETS_MCP_TOOLS=full for 69: undo/redo, formatting, merges, comments,
checkpoints, block move/resize, cross-block links, block permissions,
chart_suggest, raw row/column structure. Mutating tools carry MCP's
readOnlyHint / destructiveHint annotations so a host can gate them behind
approval.
Chart tools keep a namespace prefix where every other tool drops one. Inside
their namespace they are called list, insert, update and delete, and a
bare delete sitting next to delete_rows and delete_block_rows is a coin
flip for the model — which is the cost this whole section exists to avoid.
The file you get back
save_workbook writes a real .xlsx and returns an MCP resource link — a
uri, media type and size — rather than the bytes, which would cost ~280 KB of
context for a 200 KB workbook and teach the model nothing. Hosts that want the
file read it from workbook://current.xlsx; export_xlsx returns base64 for
hosts implementing no resources at all.
Formulas can be written out as BLOCKREF("proj","Y3","pv") for a person to read,
or resolved to plain coordinates for Excel to chew on.
One MCP session holds one active workbook, alive across tool calls — that persistence is what makes it memory rather than a calculator.
Reads and writes go wherever the server process can reach, which is normal for a local stdio server and the same posture as the official filesystem server. Run it as a user with only the access you intend it to have.
No network
No sockets, no ports, no telemetry. Your host spawns this as a child process and
they exchange newline-delimited JSON-RPC over stdin and stdout; the engine is
WASM in that same process, so a formula is a function call rather than a request.
An air-gapped machine is a supported way to run this. Checked rather than
asserted: after a full session — create a block, attach a field rule, evaluate a
formula, save an .xlsx — the process holds six pipes and no sockets, on no
listening port.
Development
A thin shell over three LogiSheets packages:
logisheets-runtime (the
headless engine), logisheets-logician (the tool definitions), and the
Rust/WASM core.
npm install && npm testTo work on the engine at the same time, check out
LogiSheets as a sibling directory, build
its packages, and run npm run link:local — that symlinks the three into
node_modules so local engine changes take effect without reinstalling. Re-run
it after any npm install.
To use it as a library, createServer returns the MCP Server, the
WorkbookSession and the tool map, so you can host it over any transport:
import {createServer} from 'logisheets-mcp'
const {server, session, tools} = createServer({mode: 'full'})License
MIT. Part of the LogiSheets project.
Available Tools
31 toolsadd_block_rowsA
Add rows to an existing block. Appends at the end by default; pass after_key or before_key to insert at a position instead. Each row needs a key; values is an object keyed by field name. Fields with a value_formula are auto-materialized by the engine — don't pass them in values. Validation/editability shadows for the new rows are auto-installed by the engine at InsertRowsInBlock time, so no follow-up is needed. Also inserts the matching sheet rows (one block per sheet-row assumption — extends the sheet so downstream rows shift down).
| Name | Required | Description | Default |
|---|---|---|---|
| rows | Yes | ||
| block | Yes | Block ref name. | |
| after_key | No | Insert directly after the row with this key, instead of appending at the end. Mutually exclusive with before_key. | |
| before_key | No | Insert directly before the row with this key. Use the first key to insert at the top. Mutually exclusive with after_key. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond annotations (readOnlyHint=false, destructiveHint=false), the description discloses key behaviors: auto-materialization of value_formula fields, auto-installation of validation/editability shadows, and the side effect of inserting sheet rows that shift downstream rows. These are significant behavioral details not captured in the schema or annotations, fully meeting the transparency burden.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but efficient, covering all essential aspects in three sentences. It front-loads the core purpose and then logically proceeds to positioning, key requirements, engine behavior, and side effects. No fluff or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's moderate complexity (4 params, no output schema), the description is thorough: it explains default behavior, alternate insertion modes, value constraints, automatic shadow installation, and sheet row impact. The only minor omission is a stated return value, but that is not critical for a write operation and is not required since no output schema exists.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 75%, so the description adds value by clarifying that rows require a key and values are keyed by field name—though this partly repeats schema. The crucial addition is the caution about value_formula fields ('don't pass them in values'), which is not in the schema. This elevates understanding of the values parameter beyond the basic schema description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Add rows to an existing block' – a specific verb (add) + resource (block) that clearly distinguishes from siblings like delete_block_rows and move_block_row. It also explains the default append behavior and positional insertion via after_key/before_key, leaving no ambiguity about the tool's function.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides practical guidance: append is default, insertion can be placed with after_key/before_key, and value_formula fields should be omitted. However, it does not explicitly contrast with alternative tools (e.g., set_block_cells) or state when not to use this tool, so it falls short of perfect guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
chart_deleteADestructive
Delete a chart. Get the chart_id from chart__list. Undoable, but it removes the chart and its formatting.
| Name | Required | Description | Default |
|---|---|---|---|
| chartId | Yes | From chart__list. | |
| sheetIdx | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, so the agent knows this is destructive. The description adds that it is 'Undoable' but removes the chart and its formatting, providing extra context about reversibility and side effects. This goes beyond the annotations and adds value without contradicting them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two concise sentences with zero fluff. The action is front-loaded, and the prerequisite instruction is directly relevant. No redundant phrasing.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple delete tool, the description covers the main intent and the chartId source, but it fails to explain the sheetIdx parameter, which is required. No output schema exists, so return behavior is not specified, but that might be acceptable for a delete operation. The missing sheetIdx explanation is a notable gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 50%: only chartId has a description ('From chart__list'), while sheetIdx has none. The description clarifies chartId by repeating the schema hint, but it offers no explanation for sheetIdx. Since half of the parameters are undocumented in both schema and description, the description only partially compensates for the gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a clear action: 'Delete a chart.' This is specific to a chart resource and distinctly different from siblings like chart_insert, chart_list, chart_update, and chart_from_block. An agent can immediately identify this as the deletion operation without confusion.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description instructs to 'Get the chart_id from chart__list,' which provides a clear prerequisite for usage. It doesn't explicitly mention alternatives or exclusions, but the context of deletion is unambiguous. It implies that chart_list should be used first, which is helpful guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
chart_from_blockA
Chart a block by naming its fields, instead of working out which cells they occupy.
The chart stays bound to the block: it plots whatever the named fields hold, so records added to the block later appear on their own and inserting rows or columns cannot leave it pointing at the wrong cells. A col-schema block works the same way as a row-schema one.
Use edit__describe_block or inspect first if you do not know the field names. Blocks with a "random" schema have no field axis and cannot be charted this way — chart their cell range with chart__insert instead.
Fields are held by name. Renaming one breaks the link (the series goes empty); moving its column does not.
| Name | Required | Description | Default |
|---|---|---|---|
| title | No | Defaults to the block's schema name. | |
| anchor | No | Top-left cell of the chart. Defaults to two rows below the block. | |
| blockId | Yes | ||
| sheetIdx | Yes | Zero-based sheet index. | |
| chartType | No | Defaults to col. | |
| sizeInCells | No | ||
| valueFields | Yes | Field names to plot, one series each, in order. | |
| categoryField | No | Field whose values label the categories (the X axis). The block's key column is not addressable as a range, so name the field that reads as a label. Omitted, the categories are just 1..n. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses binding behavior beyond annotations: the chart stays bound to the block, updates with new records, survives column moves, but breaks if a field is renamed. Annotations only say readOnlyHint=false and destructiveHint=false, so this adds valuable context about how the chart behaves over time.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a compact paragraph that leads with the core purpose, then adds behavioral detail, usage guidance, and a caveat – all in a logical order with no wasted words. Every sentence contributes distinct, actionable information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 8 parameters and no output schema, the description covers the key contextual aspects: what it does, how to prepare, when not to use it, and how the chart behaves. It also addresses schema variations (col vs. row) and the random-schema limitation, leaving nothing essential for an agent to infer.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 75%, so the baseline is 3. The description adds conceptual context about field-name binding that relates to valueFields and categoryField, but it does not systematically explain each parameter beyond what the schema already provides. It adds some value, but not enough to raise the score.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a clear, specific statement: 'Chart a block by naming its fields' – a concrete verb and resource. It also distinguishes itself from the sibling chart_insert by explicitly noting that random-schema blocks should use chart_insert instead, so an agent can tell them apart immediately.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit prerequisites ('Use edit__describe_block or inspect first if you do not know the field names') and an explicit exclusion: 'Blocks with a random schema... cannot be charted this way — chart their cell range with chart__insert instead.' This leaves no ambiguity about when to use this tool versus the alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
chart_insertA
Insert a chart that reads its values live from the given ranges — editing those cells later updates the chart.
Look at the data first so the series are right: a column of labels belongs in categoriesRef, each column of numbers is one series, and its header is that series' name.
References are A1 (B2:B10, or Sheet2!B2:B10 to read another sheet). The chart is placed below the data unless anchor says otherwise.
| Name | Required | Description | Default |
|---|---|---|---|
| title | No | Chart title. | |
| anchor | No | Top-left cell of the chart, e.g. 'H2'. Defaults to two rows below the data. | |
| series | Yes | One entry per data series. Each valueRef is an A1 range of the values to plot. | |
| sheetIdx | Yes | Sheet the chart is placed on (zero-based). | |
| chartType | Yes | col = vertical bars, bar = horizontal. pie/doughnut plot one series. scatter/bubble take numeric X from categoriesRef. stock needs 4 series (open/high/low/close) or 3 (high/low/close). surface plots a grid, one series per row. | |
| sizeInCells | No | Chart size in cells. Defaults to 15 × 8. | |
| categoriesRef | No | A1 range of the category labels (the X axis), e.g. A2:A10. For scatter/bubble these are the numeric X values. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=false and destructiveHint=false. The description adds key behavioral traits: the chart is live-linked to the ranges (editing cells updates the chart) and default placement below data. These are useful beyond the annotations, though it does not disclose behavior on invalid ranges or chart type constraints (which are in the schema).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences with no fluff. The core purpose is front-loaded, then data preparation guidance, then reference syntax and placement. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex tool with 7 parameters and nested objects, the description covers the most critical aspects: data mapping, references, and placement. It does not explain all chart type nuances (e.g., bubble sizeRef, combo seriesType), but those are documented in the schema. The essential guidance for correct invocation is present.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, but the description adds significant semantics beyond the schema. It explains the relationship between data columns and series/categoriesRef, gives A1 reference syntax including cross-sheet, and clarifies the default anchor placement. This is practical guidance an agent needs beyond raw parameter descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb (insert) and resource (a chart) and distinguishes its key feature: values read live from given ranges. It also explains the placement behavior. This is specific and distinguishes from siblings like chart_from_block, which would use a block rather than ranges.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context for how to use the tool: look at data first, map label column to categoriesRef, number columns to series, and use A1 references. It does not explicitly mention alternative tools like chart_from_block, but the live-range behavior implies when this tool is appropriate. No exclusions are given, but the context is strong.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
chart_listARead-only
List the charts on a sheet — id, kind, title, the ranges each series reads, and where the chart sits. Call this before updating or deleting one.
| Name | Required | Description | Default |
|---|---|---|---|
| sheetIdx | Yes | Zero-based sheet index. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and destructiveHint, so the description adds value by specifying the exact content returned (ranges, position). It implies no side effects beyond what annotations cover, and provides useful detail about the listing.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single, front-loaded sentence that states the action, the resource, and the key details, followed by a usage hint. Every word earns its place; no fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple list tool with one parameter, no output schema, and read-only annotations, the description provides enough information for an agent to call it correctly and understand the return fields. It lacks explicit mention of edge cases like empty sheets, but that is a minor gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The sole parameter sheetIdx is fully documented in the schema (100% coverage) with a clear description. The tool description adds no additional semantic detail about this parameter, so baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb 'List' with a clear resource 'charts on a sheet' and enumerates the returned fields (id, kind, title, ranges, position). This distinguishes it from sibling tools like chart_from_block or chart_update, making its function unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states 'Call this before updating or deleting one,' giving a clear when-to-use directive. It does not name alternative tools or state when not to use it, but the guidance is actionable and context-specific.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
chart_updateA
Reconfigure an existing chart in place, keeping its position. Anything left out keeps its current value; an empty string clears a text field (title, axis title, number format). Get the chart_id from chart__list first.
| Name | Required | Description | Default |
|---|---|---|---|
| title | No | Empty string clears it. | |
| numFmt | No | Excel number-format code for the value axis and labels, e.g. "#,##0.00" or "0%". Empty falls back to the source cells' own format. | |
| series | No | One entry per data series. Each valueRef is an A1 range of the values to plot. | |
| chartId | Yes | From chart__list. | |
| stacked | No | Stack the series. Ignored by pie and scatter. | |
| sheetIdx | Yes | ||
| chartType | No | ||
| legendPos | No | ||
| catAxisTitle | No | ||
| valAxisScale | No | Replaces the whole value-axis scale — fields left out become automatic, which is how a fixed bound is cleared. | |
| valAxisTitle | No | ||
| categoriesRef | No | Re-point the category labels (A1 range). | |
| showDataLabels | No | Print each point's value next to it. | |
| showPercentLabels | No | Add the percentage to labels (pie-like charts). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds critical behavioral details beyond annotations: 'Anything left out keeps its current value' and 'an empty string clears a text field'. It also mentions position is kept. Annotations only indicate non-read-only and non-destructive, so the description carries the burden and fulfills it well.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the core behavior, then the prerequisite. No wasted words; the most important operational detail (keep/clear behavior) comes first.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex 14-parameter tool with nested objects, the description covers the key behavioral aspects that aren't in the schema. It explains the general update model, how to obtain the ID, and references the 'clearing' mechanism. No critical gaps remain for an agent to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 64%, so the description must compensate. It provides the overarching semantics: omitted fields retain current values, empty strings clear text fields, and valAxisScale replacement semantics are clarified. This goes beyond the schema's per-field descriptions and is essential for correct invocation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action ('Reconfigure an existing chart in place') on a specific resource ('existing chart'), and distinguishes it from siblings by noting it keeps position. This clearly differentiates it from chart_insert (new) and chart_delete.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly instructs to get chart_id from chart__list first, a clear prerequisite. It implies use only on existing charts, and the sibling list includes chart_insert for creation, so the when-to-use guidance is strong.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
convert_to_blockA
Turn a table that already exists in ordinary cells into a block, in place, without touching its values.
This is how you adopt a workbook someone hands you. create_block is for new tables and refuses to write over existing data; this one takes the data as it stands and gives it a name, fields and row keys, so you can address it as (block, row_key, field) and reference it from formulas by name instead of by coordinate.
Give position and the counts for the DATA only, leaving out any header row. Field names come from the header row — pass header_row, or leave it out and the row directly above the data is used when it looks like titles. fields states them outright instead.
The row key is inferred: the first column whose values are all present and all different. Pass key_field to choose. Whatever is inferred is reported back, so check it — the key is how formulas and later edits name a row.
Converting is a one-time cost: the block and its schema survive saving and reloading, and afterwards the region behaves exactly like one created as a block.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Ref name for the new block — BLOCKREF's first argument. Must be unique. | |
| sheet | Yes | Sheet the table is on. | |
| fields | No | Field names, when there is no header row. Length must equal col_count. | |
| position | Yes | Top-left cell of the data, excluding the header row. | |
| col_count | Yes | Number of columns. | |
| key_field | No | Which field identifies a row. Omit and the first column whose values are all present and all different is used. | |
| row_count | Yes | Number of data rows. | |
| header_row | No | Row holding the column titles; field names are read from it. Omit it and the row directly above `position` is used when it looks like a header — all text, over data that is not. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate readOnlyHint=false and destructiveHint=false. The description adds meaningful behavioral context: it is in-place, does not alter values, the conversion is a one-time cost, the schema persists, and the row key inference is reported back. It does not mention potential error conditions or reversibility, but given the annotation coverage, it is adequate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured and front-loaded with the core purpose. It is somewhat lengthy but every sentence adds meaningful information about usage, parameter relationships, or persistence. It could be trimmed slightly, but it remains focused and organized.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity (8 parameters, nested objects, no output schema), the description is thorough. It covers the main use case, parameter semantics, inference behavior, and the fact that the inferred key is reported back. No critical information for invoking the tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Even though the schema covers all parameters (100% coverage), the description adds substantial semantic value beyond the schema. It clarifies that position and counts refer to data only, explains the relationship between header_row and fields, and details how key_field inference works. This goes beyond simple parameter descriptions to explain how to use them together effectively.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action: turning an existing table into a block in place without altering values. It distinguishes itself from the sibling create_block by explicitly noting that create_block is for new tables and refuses to overwrite existing data, making the purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides explicit guidance on when to use this tool versus create_block: 'This is how you adopt a workbook someone hands you. create_block is for new tables and refuses to write over existing data.' It also explains the context of adopting existing data and how this tool fits the workflow.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_analysis_blockA
Add a block that analyses another one — a totals row, sitting directly below the table it summarises.
It is an ordinary block that declares which block it analyses, so its result is addressable like any other: BLOCKREF("<name>", "<label>", "<field>"). That is the point of it being separate — a total you can only look at is much less useful than one you can reference.
What the engine does with the declaration: it GENERATES each field's formula from it, so renaming a field of the source rebuilds the total instead of breaking it, and the total tracks the source as rows are added. Do not write the formulas yourself.
By default every number field of the source gets a SUM and everything else is left blank; pass aggregates to choose. Removing the source removes this block with it.
Read it back with describe_block: the analysis reports analyzes, the source reports analyzed_by. Never sum an analysis block alongside its source — that counts the same numbers twice.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Ref name for the new block. Defaults to "<source>_analysis". | |
| label | No | What goes in the key column, and therefore the key the result is addressed by. Defaults to "TOTAL". | |
| source | Yes | Ref name of the block to analyse. | |
| aggregates | No | Which source fields to aggregate and how. Omit to SUM every field the source declares as `number`. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only provide readOnlyHint=false and destructiveHint=false, so the description carries the behavioral burden. It richly discloses that formulas are auto-generated, that renames rebuild the total, that rows are tracked, that default aggregates are SUM for number fields, that removing the source cascades removal, and that double-counting is a risk. This is far beyond the minimal annotation coverage.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose and stays on-topic, but it is somewhat lengthy. Every sentence contributes (formula generation, defaults, cascade deletion, describe_block hint, double-counting warning), yet the multiple paragraphs could be tightened without losing critical information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, but the description explains how the result is addressed via BLOCKREF and how to inspect it via describe_block. It covers the behavioral essentials: generated formulas, tracking, defaults, and cascade removal. For a creation tool with four parameters, this is complete enough for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Input schema coverage is 100%, so the baseline is 3. The description adds meaningful semantics: it explains the default aggregation behavior (SUM on number fields) and how the `aggregates` parameter overrides it, and clarifies the `source` relationship. It doesn't add detail for `name` and `label` beyond the schema, but the added value pushes it to 4.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Add a block that analyses another one — a totals row'. It distinguishes this from generic block creation by mentioning it sits below the table and that its result is addressable via BLOCKREF, which clearly separates it from siblings like create_block and create_pivot.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context: use this to create a totals row, don't write formulas yourself, and read it back with describe_block. It also warns against summing it alongside its source. However, it never explicitly names alternatives (e.g., create_block, create_pivot) or states when NOT to use this tool, so it stops short of full exclusion guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_blockA
Create a structured block (table) on a sheet. fields[0] is the row-key column — the value BLOCKREF matches on, so it has to be unique per record; it is ordinary data you can write. Block ref name (name) is used as the first arg to BLOCKREF/BLOCKREFS in formulas.
Field types supported:
'string' / 'number' — plain text/numeric cells.
'boolean' — cell stores 0/1 or TRUE/FALSE; UI renders ✅/❌ if host has the widget set.
'enum' (+ enum_id) — cell stores variant id; UI renders dropdown if host has the widget set. Watson auto-injects a variant-whitelist validation formula on the field so out-of-set writes light up as warnings even without widget rendering. Requires a prior define_enum_set call with matching id.
Rules (value_formula / validation / editability) are set separately via set_field_rule — this call only declares structure + initial rows. Auto-creates the target sheet if missing.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Block ref name. Used as the first arg to BLOCKREF/BLOCKREFS in formulas. Must be unique within the workbook. | |
| sheet | Yes | Target sheet name. | |
| fields | Yes | Column definitions in order. fields[0] is the row-key column. | |
| position | Yes | Top-left cell of the block (0-indexed). | |
| description | No | What this table is for, in a sentence or two: what a row represents, what the fields mean where the names are not obvious, and anything a later reader must not do to it (e.g. a field the craft maintains). Saved with the block and returned by describe_block, so write it for whoever opens the file next rather than for this conversation. | |
| initial_rows | No | Optional initial rows. | |
| unique_together | No | Field groups whose values must not repeat in COMBINATION — a rule about the TABLE, not about one cell. `unique` on a field covers one column; this covers several together, which nothing else can say. Reach for it on a fact table: a repeated (region, quarter) is an error nowhere, it just makes every total over that table quietly count twice. Violations show up in inspect__list_violations like any other rule. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes far beyond the sparse annotations by disclosing non-obvious behavior: auto-creation of the target sheet, auto-injection of an enum validation formula, and inference rules for field_type when omitted. It also explains UI rendering differences and the prerequisite define_enum_set, giving the agent a realistic model of side effects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long, but it is front-loaded with a one-sentence purpose and organized into field-type and rule sections that justify the length. A small duplication of the `name` argument's BLOCKREF role between schema and prose keeps it from being perfectly lean.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 7 parameters, nested field objects, and no output schema, the description covers the tricky decisions: type inference, unique constraints, initial-row formatting, and the separation of rules. An agent has enough information to construct a valid block, including edge cases like enum fields and date ISO strings.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Even with 100% schema description coverage, the prose adds meaningful semantics: row-key uniqueness of fields[0], enum_id's dependency on define_enum_set, unique_together's purpose via the (region, quarter) example, and the handling of ISO date strings in initial_rows. This materially helps an agent fill the parameters correctly.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a concrete action — 'Create a structured block (table) on a sheet' — and immediately defines the block's key structural trait (fields[0] as the row-key column). It is clearly distinct from sibling tools like set_field_rule and add_block_rows because it says what this call does and does not do.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly tells the agent that value_formula/validation/editability rules belong to set_field_rule, not this tool, and that this call only declares structure plus initial rows. This is a clear when/where-to-go-next instruction, and the auto-create-sheet caveat prevents a false prerequisite.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_pivotA
Cross-tabulate a table: one row per distinct value of rows, one column per distinct value of columns, each cell aggregating measure.
The result is an ordinary block, so every cell is addressable: BLOCKREF("<name>", "<a rows value>", "<a columns value>"). That is what lets you put one number from it in a sentence or feed it to another calculation.
You declare the recipe; the engine generates every cell from it. Do not write formulas, and do not write into the block — renaming a field of the source rebuilds the pivot rather than breaking it, which is only true because nothing is hand-written.
rows and columns must be fields whose values REPEAT (a region, a quarter, a status). Pointing either at an id gives one row per record, which is the source table again, not a pivot.
IMPORTANT: a pivot's numbers are live but its SHAPE is not. When new values appear in the source, its rows and columns fall behind while every number in it stays correct — call build__refresh_pivot. describe_block reports when that has happened.
| Name | Required | Description | Default |
|---|---|---|---|
| func | No | How to aggregate. Defaults to SUM. COUNT counts matching RECORDS and ignores `measure`; COUNTA counts the records whose `measure` is filled in, which is how you ask how complete a column is. | |
| name | No | Ref name for the new block. Defaults to "<source>_pivot". | |
| rows | Yes | Field of the source whose distinct values become the ROWS. Its values must repeat. | |
| order | No | Order of the rows. `ascending` (default) sorts; `firstSeen` keeps the source's own sequence; `custom` uses `order_values`. | |
| source | Yes | Ref name of the table to pivot. | |
| columns | No | Field whose distinct values become the COLUMNS. Omit for a simple group-by with one value column. | |
| filters | No | Which source records count at all. Omit to count every one. Applied to the rows AND the numbers, so a group left with no records gets no row rather than a row reading 0. | |
| measure | Yes | Field being aggregated. Normally a number field. | |
| row_total | No | Name for a column totalling each row across EVERY value of `columns` — e.g. "Total". Omit for no total column. | |
| order_values | No | The row sequence for `order: custom`. A value you omit is placed after the listed ones, never hidden. | |
| extra_measures | No | Extra columns with their own function and measure, for showing more than one number per group. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only indicate readOnlyHint=false and destructiveHint=false, so the description carries the burden of behavioral disclosure. It does so richly: the result is an ordinary block with addressable cells, renaming a source field rebuilds the pivot, numbers are live but the shape is not, and describe_block reports staleness. This goes well beyond the annotations and reveals genuine quirks an agent must know.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is longer than average, but each paragraph earns its place: core definition, cell addressability, the no-write constraint, field cardinality caution, and the staleness warning. It is front-loaded with the essential cross-tabulation definition. Slight verbosity around the 'declare the recipe' analogy could be tightened without loss.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex 11-parameter creation tool with no output schema, the description covers behavior, constraints, result type, and follow-up actions. The main gaps are not explaining what happens if the source is missing and the inconsistent refresh tool name. Overall, an agent has enough context to call it correctly and know what to expect.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description adds value beyond the schema by explaining the conceptual consequences of pointing rows/columns at IDs: 'gives one row per record, which is the source table again, not a pivot.' It also clarifies the live-numbers/static-shape behavior tied to the generated result. Minor but meaningful extra meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a precise definition: 'Cross-tabulate a table: one row per distinct value of `rows`, one column per distinct value of `columns`, each cell aggregating `measure`.' It clearly differentiates creation from the edit/refresh operations by explaining the generated recipe model and explicitly warning against writing formulas or writing into the block.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives strong contextual guidance: use repeating fields for rows/columns, avoid ids, and call a refresh tool when the shape falls behind. However, it refers to 'build__refresh_pivot' while the sibling list contains 'refresh_pivot', creating a potential invocation mismatch. It also never explicitly contrasts this tool with edit_pivot, so an agent gets no direct guidance on when to prefer creation over editing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_sheetA
Create a new sheet in the workbook. Returns the new sheet index. Idempotent: if a sheet with the same name exists, returns its index without creating a duplicate. Typically the agent does NOT call this directly — create_block will call it implicitly when the target sheet is missing. Use it only when you want an empty named sheet up front.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Sheet name. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond annotations (readOnlyHint=false, destructiveHint=false), the description discloses idempotent behavior (returns existing index without duplicate), return value, and implicit invocation context. This adds significant behavioral context that annotations alone do not provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences, each earning its place: function, idempotency/return, and usage guidance. No redundant information, and it is well-structured with a clear sequence.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter tool with no output schema, the description is complete. It covers purpose, return value, idempotency, and when to call directly vs. implicitly. Nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema covers 100% of the single parameter 'name' with a clear description ('Sheet name.'). The tool description does not add additional parameter semantics, but the schema already suffices, so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function: 'Create a new sheet in the workbook' and mentions the return value (sheet index). It effectively distinguishes this from sibling tools like create_block by focusing on sheet creation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit guidance is given: 'Typically the agent does NOT call this directly — create_block will call it implicitly when the target sheet is missing. Use it only when you want an empty named sheet up front.' This clearly states when to use and when not to, and names the alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_block_rowsADestructive
Delete rows from a block by their key. Missing keys are silently ignored. Also deletes the matching sheet rows (one block per sheet-row assumption). If you try to delete every row, the last one is kept and its cells are cleared instead — the engine doesn't allow rowCnt=0 blocks.
| Name | Required | Description | Default |
|---|---|---|---|
| keys | Yes | ||
| block | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and readOnlyHint=false. The description adds significant behavioral detail: missing keys are silently ignored, sheet rows are also deleted (with the assumption of one block per sheet-row), and the special behavior when deleting all rows (last row kept and cells cleared) explained by an engine constraint. This goes far beyond the annotations to disclose real-world behavior and edge cases.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences, front-loaded with the primary purpose, followed by key behavioral notes and an edge case. Every sentence contributes value without redundancy or fluff, making it optimally concise and structured.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with two simple params and no output schema, the description covers essential aspects: what it deletes, how deletion works (by key), side effects on sheet rows, and the critical edge case of deleting all rows. This is sufficient for an agent to understand scope and limitations without further documentation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has no descriptions (coverage 0%), so the description must supply meaning. It clarifies that 'keys' are row keys used to select rows for deletion, but does not explain the format or structure of these keys (e.g., whether they are numeric IDs or string labels). The 'block' parameter is only implied as the target block identifier, with no additional detail. The description adds some meaning but leaves gaps.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Delete rows from a block by their key', specifying the action (delete), resource (block rows), and method (by key). This distinguishes it from siblings like add_block_rows, move_block_row, and set_block_cells, which perform different operations on block rows.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides context about side effects (deletes matching sheet rows) and an important edge case (keeps the last row when deleting all), which helps users understand when this tool is appropriate. However, it does not explicitly name alternative tools or state when not to use this tool, leaving the usage boundaries implicit rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
describe_blockARead-only
Return a block's full structure for the LLM: identity (name, sheet, position), per-field schema, and row keys in order. Every field reports both what it IS — type, description, required, unique, default_value, and references for a field pointing at another block — and what currently guards it: the value_formula, validation and editability templates. All of it comes from the Rust schema, the engine's authoritative source, so the answer is the same in every host and survives a save/load.
Read a field's type and description BEFORE writing a value to it: the description is where the unit, the convention, or the thing-not-to-do is written down, and it is the only record of it. A type of null means nobody has claimed one yet.
analyzes and analyzed_by say whether this block is a table or a conclusion drawn from one. A block with analyzes set is an ANALYSIS block — a total row, a set of statistics, a pivot — and its rows are its own, not the source's. Never sum an analysis block alongside the block it analyses: that counts the same numbers twice. A field with aggregates set is engine-computed from the source; writes to it are dropped, and you change it by changing the declaration.
Pass include_rows: true to additionally include current cell values as rows[].values[fieldName]. Off by default to save tokens — use it when the agent actually needs to inspect data, not when it only needs the shape.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Block ref name (the `name` of create_block). | |
| include_rows | No | When true, include current cell values. Off by default to save tokens. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already mark this as read-only and non-destructive, and the description adds substantial behavioral context: results come from the authoritative Rust schema and survive save/load, analysis blocks must not be summed with their sources, and writes to aggregate fields are dropped. This goes well beyond the structured annotations and genuinely informs agent behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long, but every sentence carries distinct, actionable information: purpose, schema semantics, analysis-block warnings, aggregate behavior, and token-saving guidance. The purpose is front-loaded in the first sentence, and the rest is organized into readable thematic paragraphs with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema present, the description fully covers what the tool returns, including identity fields, per-field guards, row keys, analysis relationships, and the optional rows payload. It also covers caveats an agent needs to avoid double-counting or attempting writes to computed fields, so the description is complete for safe and correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds real value by explaining the output relation of include_rows ('rows[].values[fieldName]') and by clarifying that 'name' is the block ref name from create_block. It enriches both parameters without repeating much schema text.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description begins with a specific verb and resource: 'Return a block's full structure'. It spells out exactly what that structure contains (identity, per-field schema, row keys), which separates it from list-like siblings such as list_blocks or get_cells. The resource and scope are unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear practical guidance: read type and description before writing, and pass include_rows only when data values are needed rather than just shape. It does not explicitly name alternative tools or state when not to use describe_block, but the context is strong enough for an agent to decide correctly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
edit_analysis_blockA
Change what an existing analysis block computes: which of the source's fields it aggregates, with which function, and the label its row is addressed by.
Use this to arrive at an analysis in STEPS. Summing every number is often nearly right and wrong in one column — a rate wants AVERAGE, a text column wants COUNTA, an id column wants nothing at all. Adjust rather than rebuild: the block keeps its ref name, so formulas pointing at it keep working, and it is one undo.
aggregates REPLACES the set outright — a field you leave out stops being computed and its cell goes blank. Read the current set from describe_block first if you mean to add to it.
This is the simple kind of analysis: one row, one number per column. For one number per GROUP, use build__create_pivot / build__edit_pivot instead.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Ref name of the analysis block. | |
| label | No | New row label, which is also the key the result is addressed by. Omit to keep it. | |
| aggregates | No | Replaces the whole set. Omit to leave the functions alone and change only `label`. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses behavioral traits well beyond the annotations: aggregates replaces the set outright, omitted fields stop being computed and their cells go blank, the ref name is preserved so dependent formulas keep working, and the operation is one undo. This is exactly the side-effect transparency needed for a mutation tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but well organized: purpose statement up front, then usage rationale, a critical replacement warning, and a routing comment about pivot alternatives. Every sentence contributes either action semantics, a caution, or decision guidance.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutating tool with no output schema and minimal annotations, the description covers the important operational context: how to preserve existing aggregates (describe_block first), what happens when fields are omitted, that the block is ref-stable, and when to route to pivot tools. An agent has enough to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 100% schema coverage, the baseline is 3, and the description still adds real semantic value: label doubles as the result key, aggregates is a wholesale replacement rather than an append operation, and field refers to the source block. The enum functions are not individually explained, but the schema already enumerates them.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb phrase, 'Change what an existing analysis block computes,' and names the three mutable aspects: fields, aggregate function, and row label. It also distinguishes itself from pivot tools and from rebuilding by emphasizing the existing block and ref-name preservation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly says 'Use this to arrive at an analysis in STEPS' and advises adjusting rather than rebuilding because the ref name survives and the change is one undo. It also tells the agent when not to use it: for grouped aggregation, use create_pivot/edit_pivot instead. The alternative names appear with a 'build__' prefix, but the routing intent is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
edit_pivotA
Change an existing pivot's recipe — what it groups by, what it measures, how, in what order, over which records — and reshape it to match.
Use this rather than deleting and recreating: the block keeps its ref name, so every formula pointing at it keeps working, and the whole change is one undo.
This is also the way to REPAIR a pivot whose recipe stopped resolving (describe_block reports pivot_is_broken) — for instance after a source field was renamed. A broken pivot reads 0 in every cell rather than erroring, so it must be fixed, not refreshed: a refresh fails the same way.
Everything you omit is UNCHANGED. What you pass replaces that part outright — filters: [] clears the filters, columns: null turns a cross-tab into a simple group-by.
| Name | Required | Description | Default |
|---|---|---|---|
| func | No | New aggregate. Omit to keep the current one. | |
| name | Yes | Ref name of the pivot block. | |
| rows | No | New row dimension. Its values must repeat. Omit to keep the current one. | |
| order | No | New row order. Omit to keep the current one. | |
| columns | No | New column dimension. Pass null to drop the columns and make it a simple group-by. Omit to keep the current one. | |
| filters | No | Replaces the current filters outright. Pass an empty array to count every record again. | |
| measure | No | New field to aggregate. Omit to keep the current one. | |
| row_total | No | Name for a column totalling each row across every column value. Replaces the declared columns along with `extra_measures`. | |
| order_values | No | The row sequence for `order: custom`. | |
| extra_measures | No | Replaces the declared extra columns outright, together with `row_total`. Omit BOTH to keep the ones the pivot has. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations are minimal (readOnlyHint=false, destructiveHint=false), so the description carries the full burden. It discloses the behavior of omitted vs. passed parameters ('Everything you omit is UNCHANGED. What you pass replaces that part outright'), explains the undo capability, and details the broken-pivot behavior (reads 0 in every cell, must be fixed not refreshed). This goes well beyond the annotations and is highly transparent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured: it opens with purpose, then usage rationale, then repair scenario, then semantics. Every sentence serves a distinct function, with no fluff. It front-loads the core action and quickly moves to decision-relevant details, making it easy for an agent to parse.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 10 parameters and no output schema, the description covers all critical operational context: when to use vs. alternatives, how to repair a broken pivot, the exact behavior of omission vs. replacement, and the interaction with refresh. It does not describe return values, but for a mutation tool that's acceptable and not a gap. The description is sufficiently complete for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and every parameter already includes 'Omit to keep the current one' and specific semantics like 'Pass null to drop the columns'. The description adds a global principle ('Everything you omit is UNCHANGED') but this largely reiterates what the schema already states. Thus it provides no additional meaning beyond the schema, so the baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Change an existing pivot's recipe' and enumerates the aspects it can modify (grouping, measure, order, filters, columns). It also differentiates from siblings by naming the alternative approaches (deleting/recreating, refresh) and specifying when this tool is the right choice.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says 'Use this rather than deleting and recreating' and explains why (keeps ref name, one undo). It also provides a specific use case for repairing broken pivots and contrasts with refresh ('a refresh fails the same way'). This gives clear guidance on when to use and when not to.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
eval_formulaARead-only
Evaluate an Excel-style formula in a private scratch cell and return the computed value. Nothing is written to user-visible cells. Returns {type, value} where type is one of:
"number" — value is a JS number
"str" — value is a string
"bool" — value is a JS boolean
"error" — value is the Excel error code (e.g. "#REF!", "#NAME?")
"empty" — value is null (formula returned an empty cell)
Use for:
Quick checks: "=SUMIFS(OrderStatus, "amount", "*")" → total
Sanity-test a candidate template before set_field_rule
BLOCKREF / BLOCKREFS lookups against any block in the workbook
Leading "=" is optional — it is added automatically if missing.
| Name | Required | Description | Default |
|---|---|---|---|
| expr | Yes | Formula, with or without leading "=". E.g. "SUM(A1:A10)" or "=BLOCKREF(\"orders\", \"O001\", \"amount\")". |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, which is reinforced by the description's statement that 'Nothing is written to user-visible cells' and 'private scratch cell'. The description adds detail on the return format (type and value) and enumerates possible types, which goes beyond annotations. No contradictions exist.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured and front-loaded: the first sentence states the core action and result, followed by a list of return types, then use cases, and a final note on the '='. It is relatively concise for the information conveyed, with no redundant sentences. Each part adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given a single parameter, no output schema, and existing annotations for read-only, the description covers the essential context: purpose, return format, use cases, and syntax details. It is complete enough for an agent to call the tool correctly without additional information. Minor gaps like error handling details are covered by the return type list.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema covers the sole parameter 'expr' at 100% with a description that already mentions 'with or without leading =' and provides an example. The description repeats the '=' note and gives additional examples but does not add substantial new semantics beyond the schema. Since schema coverage is complete, the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool evaluates Excel-style formulas in a private scratch cell and returns a computed value. It distinguishes itself from siblings like get_cells (reads cells) and set_cells (writes cells) by specifying its unique function. The use of 'Evaluate' and 'return the computed value' makes the purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit 'Use for' scenarios: quick checks, sanity-testing templates before set_field_rule, and BLOCKREF/BLOCKREFS lookups. This gives clear guidance on when to use the tool, and it implicitly differentiates from set_field_rule by mentioning 'before' it. It also notes the optional leading '=' handling, which is a usage detail.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
export_xlsxARead-only
Return the workbook as base64-encoded .xlsx bytes.
Last resort. The bytes land in your context and cost roughly 1.4 KB of text per KB of file. Prefer save_workbook, which writes a real file and hands the host a link to it — the host can give the human the workbook without any of it passing through you.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, but the description adds crucial behavioral context: the bytes are injected into the agent's context and cost roughly 1.4 KB of text per KB of file. This warns about significant resource consumption and explains why the sibling tool is preferred.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the core purpose, followed by a concise cost/alternative explanation. Every sentence carries essential information; there is zero filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter, read-only tool with no output schema, the description fully covers what the agent needs: what it returns, the cost to the agent, and when to use the sibling instead. No gaps remain.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the schema leaves nothing undocumented. Per the rubric, 0 params gets a baseline of 4; the description adds no parameter-specific detail because none is needed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description opens with a specific, unambiguous purpose: 'Return the workbook as base64-encoded .xlsx bytes.' It clearly identifies the verb, resource, and output format, and distinguishes itself from sibling save_workbook by framing this as the 'last resort' option.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states when NOT to use it ('Last resort') and names the preferred alternative: 'Prefer `save_workbook`'. It explains the key tradeoff (bytes passing through context vs. real file+link), giving the agent actionable decision criteria.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_cellsARead-only
Read the values (and formulas) in a rectangular range of cells, addressed by zero-based (sheetIdx, startRow, startCol, endRow, endCol). Returns only the non-empty cells, each with its A1 ref, value, and formula (if any). Use this for ordinary "what is in these cells" questions; for a single computed result you can also use build eval_formula. Reads at most 500 cells per call — narrow the range if it is bigger.
| Name | Required | Description | Default |
|---|---|---|---|
| endCol | Yes | Zero-based last column (inclusive). | |
| endRow | Yes | Zero-based last row (inclusive). | |
| sheetIdx | Yes | Zero-based sheet index. | |
| startCol | Yes | Zero-based first column. | |
| startRow | Yes | Zero-based first row. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the description builds on that by adding key behaviors: returns only non-empty cells, includes A1 ref, value, and formula, and enforces a 500-cell per call limit. This is useful beyond the annotations, though it doesn't cover edge cases like error handling or empty results.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, each earning its place: what the tool does, what it returns and how to use it, and the operational limit. No filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only tool with no output schema, the description adequately explains the return shape (non-empty cells with A1 ref, value, formula) and the 500-cell cap. It could mention behavior for out-of-range indices or fully empty ranges, but these are minor gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with each parameter already described as zero-based and inclusive. The description reiterates the parameter order but adds no new meaning beyond the schema, so the baseline score of 3 for high schema coverage applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool reads values and formulas in a rectangular cell range, with a specific verb ('Read') and resource ('rectangular range of cells'). It also distinguishes itself from the sibling eval_formula by noting that for a single computed result you'd use that tool instead.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says 'Use this for ordinary "what is in these cells" questions' and directs to eval_formula for a single computed result. This provides clear when-to-use and when-not-to-use guidance with a named alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
goal_seekARead-only
Find the input value that makes a chosen output equal a target — "what discount rate gives a value per share of 30".
Runs entirely on the engine's temp branch, so the workbook is never modified: this is a question, not an edit. The search happens inside the engine rather than as a conversation, so it costs one tool call instead of one per iteration.
Name both cells semantically as (block, row_key, field) or by coordinate as (row, col). Give between when you know a bracket; otherwise it expands outward from the current input value to find one.
Bisection, so it needs the output to move monotonically between the bracket ends and it finds one crossing. If the bracket does not straddle the target it says so rather than returning a number — a non-answer you can act on beats a plausible one you cannot.
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | The value `target` should reach. | |
| set | Yes | The input cell to vary. | |
| target | Yes | The output cell to drive to `to`. | |
| between | No | Search bracket [low, high]. Omit to expand outward from the current input value. | |
| tolerance | No | How close to `to` counts as solved. Default 1e-6 relative. | |
| max_iterations | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds significant behavioral detail beyond the readOnlyHint and destructiveHint annotations: it explains the temp-branch execution, the bisection algorithm, the monotonicity requirement, and the behavior when the bracket does not straddle (returns a non-answer). This is exactly the kind of context that helps an agent predict outcomes.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and well-structured: it starts with a clear purpose, then a short note on safety, then usage details, then algorithm behavior. Every sentence earns its place without fluff or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (goal seek with bisection, optional bracket, monotonicity assumption) and lack of an output schema, the description covers all essential aspects: purpose, non-destructive nature, cell naming, bracket behavior, monotonicity requirement, and failure handling. It is fully sufficient for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is high (83%), so the baseline is 3. The description goes further by explaining the semantics of the `between` parameter (optional, expand outward if omitted) and how to name cells (semantic vs. coordinate). It clarifies the search process and the meaning of the bracket, adding value beyond the schema's short descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states the tool's purpose precisely: 'Find the input value that makes a chosen output equal a target' with a concrete example. It distinguishes itself from sibling tools by framing it as a question rather than an edit, which is unique among the listed mutation/set tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides clear guidance on when to supply a bracket ('Give `between` when you know a bracket') and how to reference cells. It also explains why to use this over iterative conversation (one call vs. many). However, it does not explicitly name alternative tools or state when NOT to use this tool, so it falls short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_blocksARead-only
Orient yourself in a workbook: every sheet, every block, and for each block the fields you can reference. One call is enough to start writing formulas.
Per block you get its ref name (BLOCKREF's first argument), its fields in column order (the third argument), key_field — the column whose values BLOCKREF matches as its second argument — and derived_fields, which are computed by a rule and reject writes.
Use describe_block when you need a field's actual rule, or the row keys and values. next_block_start clears everything already on the sheet, blocks and loose cell content alike, so passing it as create_block's position will not land on top of data.
Omit sheet to scan the whole workbook; passing it restricts to one sheet.
| Name | Required | Description | Default |
|---|---|---|---|
| sheet | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, covering safety. The description adds context about derived_fields rejecting writes and the orientation purpose, without contradicting annotations. It doesn't describe side effects, but annotations suffice; the added detail about returned data is a bonus.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the main purpose and returns a clear structure of paragraphs, but includes tangential information about next_block_start and create_block that isn't directly needed for using list_blocks. This slightly dilutes conciseness, though each sentence carries some value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With only one optional parameter and no output schema, the description adequately explains the tool's output: per block it returns ref name, fields, key_field, and derived_fields. It also points to describe_block for further details, making the tool self-contained for an agent to understand its output and usage.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Parameter schema coverage is 0%, so the description is the sole source of meaning. It fully explains the sheet parameter: omitting it scans the whole workbook, passing it restricts to one sheet. This provides complete semantic clarity beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool lists every sheet, every block, and the fields per block, with specific details about returned metadata (ref name, fields, key_field, derived_fields). It distinguishes itself from describe_block by positioning itself as a high-level orientation tool, so purpose is specific and unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly provides when-to-use guidance: use describe_block when needing field rules or row keys/values, and explains sheet parameter behavior (omit for whole workbook, pass for single sheet). This clearly differentiates usage from alternatives and gives contextual direction.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_violationsARead-only
Scan validation shadow cells and return every cell whose validation formula currently evaluates FALSE. Validation is advisory — the cell still holds its value, but the host UI renders a warning marker and you should treat it as "something the user/AI got wrong".
A field's rule is what its DECLARATION implies — required, unique, enum membership, reference existence — ANDed with whatever rule its author wrote. rule in the output names the declaration rather than quoting the generated formula, because the generated one is not something anyone typed. So a field with no rule text of its own can still appear here, which is the point: before the engine derived these, a required-but-empty cell raised nothing at all.
Also returns duplicate_keys: blocks where two records carry the same row key. That is not an advisory rule but a broken address — BLOCKREF resolves a key to the FIRST matching record, so the others are unreachable and every aggregate over the block double-counts, silently and without an error anywhere. The engine refuses to create a duplicate, so anything reported here came in with the file. Fix it by giving one of the records a distinct key before trusting any total over that block.
Also returns pivots_needing_attention. A pivot fails in a way no validation rule can see: stale means its numbers are each correct while whole groups are MISSING, and broken means its recipe stopped resolving so every cell reads 0 rather than erroring. Neither shows up as a red cell anywhere. Treat a broken pivot's numbers as unusable and fix the recipe; refresh a stale one before quoting any total from it.
Use this when answering 'why is something red?', 'what's broken after my last edit?', or before quoting any number you did not just compute yourself. It is the one call that answers 'is anything here untrustworthy' — the alternative is describe_block on every block, which is easy to skip and easy to forget.
Filters compose: omit both block and sheet to scan the whole workbook; pass either to narrow.
Pull-based on purpose: the LLM is turn-based, polling at decision points is cheaper than maintaining a live subscription. The host UI has its own per-cell push subscription for canvas warning markers.
| Name | Required | Description | Default |
|---|---|---|---|
| block | No | Block ref name. Omit to scan all blocks. | |
| limit | No | ||
| sheet | No | Sheet name. Omit to scan all sheets. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, and the description adds deep behavioral context: advisory nature of validation, duplicate_keys as broken addresses with silent double-counting, pivot stale/broken distinctions, and pull-based rationale. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but front-loaded with purpose and each paragraph adds substantive value (validation semantics, duplicate_keys, pivots, usage, filters, rationale). It is structured and not repetitive, though it could be tightened slightly without losing meaning.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, so the description fully explains all returned components (validation violations, duplicate_keys, pivots_needing_attention) with their semantics and implications. It also covers filter behavior and when to call, making it self-sufficient for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 67% (block and sheet have descriptions; limit does not). The description clarifies how block and sheet compose ('omit both... pass either to narrow'), adding meaning beyond the schema. It does not describe limit, but that is minor given its default and bounds.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb+resource: 'Scan validation shadow cells and return every cell whose validation formula currently evaluates FALSE.' It also names the alternative (describe_block) and clarifies it is the one call for trustworthiness, distinguishing it from siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states when to use: 'why is something red?', 'what's broken after my last edit?', or before quoting any number not just computed. It contrasts with describe_block and explains why it's the right choice.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
move_block_rowA
Reorder a block by moving one row to a new position, addressing both the row and its destination by key. Moves to the end when neither after_key nor before_key is given (same default as add_block_rows). Row order inside a block is presentation only — formulas address rows by key, so reordering never changes a single computed value. Use it to match a reading order someone expects, not to change the model.
| Name | Required | Description | Default |
|---|---|---|---|
| key | Yes | Row key of the row to move. | |
| block | Yes | Block ref name. | |
| after_key | No | Land the row directly after the row with this key. Mutually exclusive with before_key. | |
| before_key | No | Land the row directly before the row with this key. Pass the first key to move it to the top. Mutually exclusive with after_key. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only state readOnlyHint=false and destructiveHint=false, but the description adds valuable behavioral context: 'reordering never changes a single computed value' and 'presentation only'. This clarifies the actual impact of the operation beyond what annotations convey, helping the agent understand side effects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three concise, purposeful sentences. The main action is front-loaded, the default behavior is stated in the second sentence, and the practical usage note is saved for the final sentence. No filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers purpose, usage, default behavior, and the important nuance that reordering is presentation-only. This is complete for a simple reorder tool with a clear sibling group (add_block_rows, delete_block_rows) and no output schema needed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds meaning beyond the schema by specifying the default behavior when neither after_key nor before_key is given ('Moves to the end') and by explaining that both row and destination are addressed by key. This is useful context not present in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Reorder a block by moving one row to a new position', which is a specific verb+resource action. It clearly distinguishes this from sibling tools like add_block_rows and delete_block_rows by focusing on reordering an existing row rather than adding or removing.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit guidance on when to use and when not to use: 'Use it to match a reading order someone expects, not to change the model.' It also explains the default behavior when neither after_key nor before_key is given and references the sibling add_block_rows for the same default, helping the agent choose between siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
open_workbookA
Start the workbook you will work in. Call with no arguments for a fresh, empty one; pass path to load an existing .xlsx from disk and work on the human's real file.
This replaces whatever workbook the session currently holds, discarding unsaved changes — so call it once at the start, not between steps. You do NOT have to call it at all: an empty workbook appears automatically the moment any other tool touches the session.
Prefer path over xlsx_base64. xlsx_base64 exists for hosts with no shared filesystem and costs enormous context for a file of any size.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | File name to report to the engine when loading from base64. | |
| path | No | Path to an existing .xlsx to load. Omit for an empty workbook. | |
| xlsx_base64 | No | A .xlsx as base64, for when no shared filesystem exists. Use `path` when you can. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes beyond the annotations by disclosing a key side effect: 'replaces whatever workbook the session currently holds, discarding unsaved changes.' It also provides actionable behavioral context about base64's enormous context cost, which is not captured in the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Every sentence earns its place. The description is front-loaded with the primary concept, then covers alternatives, timing, and parameter selection in a compact but complete way. No filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's stateful behavior and optional parameter combinations, the description fully covers the essential usage context: what the tool does, when not to call it, why the current workbook is replaced, and the preferred data-passing method. No output schema is needed for this simple initialization tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema description coverage is 100%, so a baseline score of 3 applies. The description additionally clarifies when to use path over xlsx_base64 and explains why, enriching parameter semantics without repeating the schema verbatim.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's verb and resource: 'Start the workbook you will work in.' It further distinguishes its role by explaining fresh empty workbook vs loading an existing .xlsx, which is distinct from sibling tools like create_sheet or save_workbook.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit guidance is given for when to call ('once at the start, not between steps'), when not to call it ('you do NOT have to call it at all'), and which parameter to prefer ('Prefer path over xlsx_base64'). This is exemplary for helping an agent decide usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
preview_changesARead-only
Dry-run edits on the workbook's temp branch and report what they would do. Nothing is committed — the branch is discarded, so this is the safe way to explore a model instead of changing it and putting it back.
Two shapes. changes runs one hypothetical and returns every cell that would move, direct writes and cascaded recalculations alike. scenarios runs several, each on its own branch, and returns one result per scenario in order — that is a sensitivity table or a scenario comparison in a single call.
Add watch to get just the cells you care about instead of the whole cascade. A grid of sixteen scenarios over a model that cascades into 26 cells is 416 rows of diff to answer sixteen questions; watch makes it sixteen numbers. Name a cell semantically ({block, row_key, field}) or by coordinate ({sheet_idx, row, col}).
| Name | Required | Description | Default |
|---|---|---|---|
| watch | No | Report only these cells' values instead of the full diff. Name each one semantically or by coordinate. | |
| changes | No | One hypothetical. Use `scenarios` for more than one. | |
| scenarios | No | Several hypotheticals, each evaluated independently. Results come back in this order. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare readOnlyHint=true and destructiveHint=false ya, but the description adds meaningful behavioral detail: writes go to a temp branch that is discarded, and it highlights a potential large-response performance pitfall (416 rows of diff). This is exactly the kind of context that helps an agent avoid surprises beyond the annotation hints.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tightly-packed paragraphs, each earning its place: 1) core behavior and safety, 2) two modes, 3) output-size optimization. Front-loaded with the most important 'dry-run/safe' concept. No fluff, but the description is dense and requires some parsing; still efficiently structured.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 3 params and no output schema, the description covers the modes (`changes` vs `scenarios`), how to interpret results (returns what would move, including cascades), and the `watch` parameter's purpose and advantage. It doesn't describe the exact return shape, but given dense schema descriptions, this is sufficient and complete for the complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%: `watch` says 'report only these cells' values instead of the full diff', `changes` 'one hypothetical... use `scenarios` for more', and each field has a description. The description complements it by explaining the semantic vs coordinate addressing for `watch` and the notion of 'cascaded recalculations' which clarifies that the diff includes more than direct writes. Builds on schema, adds value.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description starts with a specific verb+resource ('Dry-run edits on the workbook'), states what it reports (what they would do), and explicitly contrasts with actual changes ('Nothing is committed'). It clearly distinguishes two operational shapes (changes vs scenarios) and mentions the optional watch filter, all in the first sentence. This strongly separates it from sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly frames this as 'the safe way to explore' instead of changing and putting it back, giving clear when-to-use context. It also explains when to use `watch` vs. getting the whole cascade incl. an explicit example of a large scenario grid. The schema reinforces with `scenarios` 'use `changes` for one.' Guidance is explicit and immediate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
refresh_pivotA
Bring a pivot's rows and columns back in line with its source.
Its NUMBERS were never stale — they are live formulas. Only the set of rows and columns falls behind, because no formula can add a row. That is exactly why this matters: a stale pivot shows correct numbers with whole groups missing, and totals taken from it are short with nothing to say so.
Call it before reading or reporting a pivot that describe_block flagged. Safe and cheap to call when nothing has changed — it reports that it did nothing.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Ref name of the pivot block. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds substantial behavioral context beyond the readOnlyHint=false and destructiveHint=false annotations. It explains that numbers are live formulas, only rows/columns can become stale, and it reports when it did nothing. This gives the agent an accurate mental model of the tool's side effects and safety profile.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose in the first sentence. The following paragraphs add valuable context about why the tool matters and when to call it, though some phrasing is slightly elaborate. Overall every sentence contributes meaning.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter tool with no output schema, the description covers purpose, behavior, usage context, and no-op behavior. It does not specify exact return format, but the note that it 'reports that it did nothing' gives enough signal for invocation and result interpretation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema fully documents the single parameter as 'Ref name of the pivot block.' The description mentions pivots but does not add new semantic detail about the name parameter beyond what the schema already provides, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Bring a pivot's rows and columns back in line with its source.' It further clarifies the exact scope of the refresh — only the set of rows and columns, not the NUMBERS which are live formulas. This clearly distinguishes it from sibling tools like edit_pivot or create_pivot.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit usage guidance: 'Call it before reading or reporting a pivot that describe_block flagged.' It also reassures about when it is acceptable to call even without known changes: 'Safe and cheap to call when nothing has changed.' This is direct, actionable guidance with no ambiguity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
save_workbookA
Write the workbook to a real .xlsx file the human can open in Excel. This is how you hand your work back — do it when the task is done.
Defaults to the path it was opened from, or last saved to; pass path to write somewhere else. Values, formulas and the block structure are all saved.
IMPORTANT — if the human is going to work on this in Excel, pass resolve_block_refs: true. Formulas that read blocks are written as BLOCKREF/BLOCKREFS, which only LogiSheets understands: Excel shows the saved numbers but turns those cells into #NAME? the moment it recalculates. Resolving rewrites them as ordinary A1 references so Excel can recompute the model. Leave it off when the file is coming back here — the named form is readable and survives rows moving.
The result carries a link to the workbook rather than its bytes, so the host can offer the human the file without any of it passing through your context.
| Name | Required | Description | Default |
|---|---|---|---|
| path | No | Destination .xlsx path. Defaults to the path the workbook was opened from. | |
| resolve_block_refs | No | Rewrite BLOCKREF/BLOCKREFS as ordinary A1 references. Set this when the human will open the file in Excel; Excel has no BLOCKREF function and would show #NAME? on recalculation. One-way: a resolved file is an export, not a round trip. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Despite annotations being minimal, the description extensively discloses behavior: default path (opened from or last saved), what is saved (values, formulas, block structure), the BLOCKREF issue and one-way resolution, and the result carrying a link instead of bytes. This goes far beyond the annotations and provides critical behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is somewhat long but well-structured: purpose first, then defaults, then a critical warning about block refs, and result behavior. Every sentence contributes necessary information, but the length could be trimmed if some details were in schema or annotations. No wasted words, but not maximally concise.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a save operation with no output schema, the description covers all important aspects: destination, what data is persisted, Excel compatibility nuances, one-way export, and return format (link). It also implies the tool's role in the overall workflow. This is comprehensive for its complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with both parameters described, but the description adds meaningful context: path defaults and when to set resolve_block_refs (Excel vs round-trip, one-way nature). This goes beyond the schema, so it earns above the baseline 3, though it doesn't introduce new parameter syntax.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool writes a workbook to a real .xlsx file for the human to open. It distinguishes from sibling tools by emphasizing 'real .xlsx file' and 'hand your work back', but does not explicitly differentiate from export_xlsx, so it lacks explicit sibling differentiation. Thus, it's clear but not fully distinguishing.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly states when to use the tool ('do it when the task is done') and provides detailed guidance on when to set resolve_block_refs (for Excel vs round-trip). However, it does not mention when not to use it or alternatives like export_xlsx, so it lacks exclusions. This is clear context but with no explicit alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_block_cellsA
Write one or more cells inside any block(s) in a single atomic transaction. Each change addresses a cell by (block ref name, row_key, field) — the LLM never deals with raw (sheet, row, col).
Pass changes as an array; one-cell writes are just length-1 arrays. Batching is the cheap default — putting N writes in one call is one transaction, one calc pass, one undo entry.
Rejected up-front (whole tx aborts) when any change:
targets a non-existent block / row_key / field, or
targets a field with a
value_formulaon its schema (engine-computed; use set_field_rule to change the rule instead).
Value can be a literal (string / number / boolean) or a formula prefixed with '='. null clears the cell.
| Name | Required | Description | Default |
|---|---|---|---|
| changes | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate readOnlyHint=false and destructiveHint=false, but the description adds significant behavioral detail: the entire transaction aborts if any change targets a non-existent block/row/field or a value_formula field, and it clarifies that null clears a cell. It also mentions atomicity, single calc pass, and single undo entry—information beyond what annotations provide. This fully aligns with the annotations, with no contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, well-organized paragraph that front-loads the main action, then covers batching, error conditions, and value types. There is no fluff or repetition; every sentence adds essential information, making it concise and easy to parse.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description fully covers the tool's complexity: atomic batch behavior, validation rules, value handling (literal, formula, null), and an explicit alternative for value_formula fields. With no output schema, this is adequate for a write operation, and the description leaves no critical gaps for an agent to discover at runtime.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has minimal descriptions (only the value parameter has a description), but the tool description compensates by explaining each parameter in prose: block ref name, row_key, field, and value semantics, including formula prefix and null clearing. It adds meaning beyond the basic types, though it could be more explicit about the format of each parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function: 'Write one or more cells inside any block(s) in a single atomic transaction.' It specifies the verb (write), resource (cells in blocks), and the addressing mechanism (block ref name, row_key, field), distinguishing it from raw cell operations. This is specific and unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains when to use this tool (for block-based cell writes, never raw coordinates) and explicitly names an alternative (set_field_rule) for fields with value_formula. It also encourages batching as the default. However, it does not explicitly contrast with sibling tools like set_cells or mention cases where it should be avoided, leaving some ambiguity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_block_descriptionA
Write what a block is for, in prose, onto the block itself. Saved in the file and returned by describe_block, so it is how the next agent — or the next you, in a later session — learns what the table means.
Say what one row represents, what any non-obvious field holds, and anything that must not be done to it. Do not restate the field names; they are already visible.
Refused when the block reserves modifyDescription to its owner. Pass an empty string to clear it.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Block ref name. | |
| description | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate a write operation (readOnlyHint=false) and non-destructive (destructiveHint=false). The description adds meaningful behavioral context: persistence ('Saved in the file'), the refusal condition, and the clearing behavior. It does not contradict annotations and covers the key side effects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is efficiently organized: the core action first, then purpose, then content guidance, then constraints. Every sentence contributes value without redundancy. It is appropriately detailed for the task.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter tool with no output schema, the description covers all necessary aspects: what to write, how to clear, and when it may fail. It leaves no critical ambiguity for an agent to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 50% (name is documented, description is not). The description compensates thoroughly by explaining exactly what the description parameter should contain ('Say what one row represents... Do not restate the field names') and how to clear it. This adds substantial meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Write what a block is for, in prose, onto the block itself.' It clearly distinguishes this from sibling tools by contrasting with describe_block (which reads) and by emphasizing the prose, non-field-name content. The action is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context for when to use the tool (to document a block for future agents) and includes a specific refusal condition ('Refused when the block reserves `modifyDescription` to its owner'). It also explains how to clear a description via empty string. It does not explicitly name alternatives beyond implying describe_block, but the guidance is sufficient.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_cellsA
Write one or more arbitrary cells on a sheet in a single atomic transaction (one undo step). Each cell is addressed by zero-based row/col. Content is a literal (string / number / boolean) or a formula prefixed with '='. null or '' clears the cell. For cells that belong to a block, prefer edit set_block_cells (it respects the schema); use this for plain, non-block cells. At most 200 cells per call.
| Name | Required | Description | Default |
|---|---|---|---|
| cells | Yes | ||
| sheetIdx | Yes | Zero-based sheet index. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses key behaviors: atomicity (one undo step), clearing cells with null/empty string, and the 200-cell limit. Given annotations already show mutability (readOnlyHint=false) and non-destructive (destructiveHint=false), the added details on clearing and atomicity add value beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact, front-loaded with the core purpose, and each sentence serves a distinct function: purpose, addressing/content rules, usage preference, and limit. No redundancy or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's moderate complexity (2 params, array of objects) and lack of output schema, the description covers essentials: how cells are addressed, content types, clearing, block preference, and call limit. It does not mention error handling or response format, but that is less critical for a write operation. The description is complete enough for an agent to invoke correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 50% (only 'content' and 'row'/'col' descriptions are in schema; 'sheetIdx' and the array structure are not fully described). The description adds meaning about cell content types (literal vs formula) and the clearing behavior, but it doesn't explain 'sheetIdx' beyond the schema's own comment. With partial coverage, the description partially compensates but not fully.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool writes one or more cells in a single atomic transaction, with specific addressing and content types. It distinguishes itself from the sibling 'set_block_cells' by emphasizing plain, non-block cells, and notes that block cells should use the sibling tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly says 'For cells that belong to a block, prefer edit set_block_cells' and 'use this for plain, non-block cells,' providing clear when-to-use and when-not-to-use guidance with an alternative tool named.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_field_ruleA
Attach declarative rules to a field. All three rule kinds (value_formula, validation, editability) are optional — pass only the ones you want to change. Omit a kind entirely to leave it untouched on this field; pass null to explicitly clear an existing rule.
Placeholders supported in formulas: #FIELD("name") — the same row's cell in field "name" #FIELD("name", "key") — field "name" on the row carrying that key, in THIS SAME block #KEY — the row's key value (quoted as a string literal) #PLACEHOLDER — the cell itself (validation/editability only)
The two-argument #FIELD is the only way to reach another row of the cell's own block: BLOCKREF is refused there (it depends on the whole-block vertex, so it would close a cycle). Use it for share-of-total or index-to-a-base-row columns, e.g. "=#FIELD("amt")/#FIELD("amt","TOTAL")". The other row is named by KEY, never by position — there is no "previous row" form, because rows can be reordered and inserted into, so a positional address would silently come to mean a different row. A running total (each row reading the row above) therefore has no rule form; write that column as ordinary cells outside the block. A rule that resolves onto the cell it is defining is rejected, as is a plain coordinate (A1/C3) landing inside the block — in a template a coordinate does not shift per row, so on the first row it would point at the cell being defined.
Engine behaviour after this call:
value_formula → cells in the field become engine-computed (no direct writes). Every row's formula is re-materialized.
validation → a
ShadowKind::Validationshadow is auto-installed on every row; warning markers refresh.editability → a
ShadowKind::UserEditableshadow is auto-installed on every row; the host permission patch reads it to gate writes.
Leading "=" on the formula body is optional; omit or include either way.
| Name | Required | Description | Default |
|---|---|---|---|
| block | Yes | ||
| field | Yes | ||
| validation | No | Boolean formula, e.g. "#PLACEHOLDER>=0". Pass null to clear; omit to leave existing untouched. | |
| editability | No | Boolean formula, e.g. "=#FIELD(\"status\")<>\"locked\"". Pass null to clear; omit to leave existing untouched. | |
| value_formula | No | Formula template, e.g. "=#FIELD(\"qty\")*#FIELD(\"price\")", or "=#FIELD(\"amt\")/#FIELD(\"amt\",\"TOTAL\")" to divide by a named row of the same block. Pass null to clear; omit to leave existing untouched. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description thoroughly explains the engine behavior after the call for each rule kind (re-materialization, shadow installation, permission gate). It also discloses rejection criteria for self-referencing rules and coordinates landing on the block, and notes that leading '=' is optional—all beyond the annotations, which only provide readOnlyHint and destructiveHint.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but dense with essential information. It is front-loaded with the core purpose and optionality, then logically progresses to placeholder syntax, cross-row references, constraints, and engine behavior. Every sentence contributes value, with no redundancy or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description is complete for the tool's complexity: it covers what the tool does, how to use each parameter, what happens after the call, and what errors are rejected. It even addresses edge cases like row reordering and template coordinates. No output schema exists, but the description sufficiently indicates the effects.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With schema coverage at 60%, the description adds substantial meaning to the parameters. It gives concrete examples for value_formula (e.g., multiplication, division by a named row), explains the #FIELD, #KEY, #PLACEHOLDER placeholders, and clarifies that passing null clears a rule while omitting leaves it unchanged—details not fully covered in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with "Attach declarative rules to a field," a specific verb+resource that clearly states the tool's function. It distinguishes three rule kinds (value_formula, validation, editability) and explains how they relate, making it distinct from sibling tools like set_cells or eval_formula.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly explains when to use the tool, how to leave rules untouched vs. clear them, and provides detailed guidance on placeholders, including when to use the two-argument #FIELD for cross-row references and why BLOCKREF is forbidden. It also notes that running totals have no rule form and directs users to write those as ordinary cells, giving clear exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
traceARead-only
Follow a cell's dependencies, in either direction, using the engine's own dependency graph.
precedents— what this cell reads. Use it to audit a number: "why is value-per-share what it is".dependents— what reads this cell, and through which reference. Use it before changing something: "what breaks if I edit this assumption".
Both by default. Name the cell semantically as (block, row_key, field), or by coordinate as (row, col) with an optional sheet_idx. Results come back named the same way whenever the cell sits inside a block, so you get "assumptions.wacc" rather than a coordinate to interpret.
This asks the engine rather than reading formula text, so it sees through BLOCKREF, ranges and whole-column references, and it answers the reverse direction — which formula strings cannot.
Granularity matters when blocks are involved. The engine tracks block dependencies per (block, field), not per row, so dependents of one block cell is everything reading that FIELD — the queried row among them. Each edge carries scope: "cell" is exact, "field" and "block" are over-approximations, and approximate: true is set on the result when any edge is wider than a cell. Treat a field-wide answer as "at least these", not "exactly these".
| Name | Required | Description | Default |
|---|---|---|---|
| target | Yes | The cell to trace. Either (block, row_key, field) or (row, col). | |
| direction | No | both |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly/destructive annotations, the description discloses critical behavior: it uses the engine's dependency graph, returns semantic names for block cells, and tracks dependencies per field rather than per row, causing over-approximation. It explicitly explains the 'scope' field and approximate flag, ensuring the agent understands the interpretive caveat.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured: starts with purpose, then usage, then behavior, then granularity caveats. Every sentence adds value and is directly relevant to correct use. Despite its length, it is not redundant; it front-loads the essential purpose and usage, followed by necessary technical detail.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (dependency tracing, block granularity, approximation), the description covers all key aspects: the two directions, naming, the engine's view through references, and the interpretation of field-wide results. It lacks an output schema, but the description suffices to understand what results will look like and how to use them.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description adds substantial meaning beyond the schema: it explains the two naming conventions (semantic vs coordinate) for the target parameter, clarifies the default for direction ('Both by default'), and details how results are named. This compensates for the schema's partial coverage and adds practical guidance for parameter usage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Follow a cell's dependencies, in either direction, using the engine's own dependency graph.' It specifies both directions (precedents/dependents) and gives concrete use cases, distinguishing it from sibling tools like eval_formula by mentioning it sees through BLOCKREF and ranges.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit guidance is given: use precedents for auditing a number and dependents before changing something. It also contrasts with formula-string reading and explains when to rely on the result granularity, including how to interpret approximate results. This gives clear when-to-use and what-to-expect context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
7 tool updates
v0.5.0- Added
create_analysis_block - Changed
create_block4 fields changed- added
Input schema / properties / fields / items / properties / descriptionAdded value: +{ + "description": "What this field means, in a sentence, where the name alone does not say it — the unit it is in (\"in units of 10k\"), the convention it follows, or something a later reader must not do to it. Saved on the schema and returned by describe_block, so write it for whoever opens the file next rather than for this conversation.", + "type": "string" +} - added
Input schema / properties / fields / items / properties / requiredAdded value: +{ + "default": false, + "description": "Every record must carry a value here. Declared on the schema, so every host and every later reader sees it.", + "type": "boolean" +} - added
Input schema / properties / fields / items / properties / uniqueAdded value: +{ + "default": false, + "description": "No two records may carry the same value here. Declared on the schema.", + "type": "boolean" +} - added
Input schema / properties / unique_togetherAdded value: +{ + "description": "Field groups whose values must not repeat in COMBINATION — a rule about the TABLE, not about one cell. `unique` on a field covers one column; this covers several together, which nothing else can say. Reach for it on a fact table: a repeated (region, quarter) is an error nowhere, it just makes every total over that table quietly count twice. Violations show up in inspect__list_violations like any other rule.", + "items": { + "items": { + "type": "string" + }, + "type": "array" + }, + "type": "array" +}
- Added
create_pivot - Added
edit_analysis_block - Added
edit_pivot - Changed
eval_formula1 field changed- changed
Input schema / properties / expr / descriptionPrevious value: -"Formula, with or without leading \"=\". E.g. \"SUM(A1:A10)\" or \"=BLOCKREF(\\\"orders\\\", \\\"O001\\\", \\\"金额\\\")\"."New value: +"Formula, with or without leading \"=\". E.g. \"SUM(A1:A10)\" or \"=BLOCKREF(\\\"orders\\\", \\\"O001\\\", \\\"amount\\\")\"."
- Added
refresh_pivot
8 tool updates
v0.1.1- Added
chart_delete - Added
chart_from_block - Added
chart_insert - Added
chart_list - Added
chart_update - Changed
convert_to_block2 fields changed- changed
Input schema / properties / header_row / descriptionPrevious value: -"Row holding the column titles; field names are read from it. Usually one row above `position`."New value: +"Row holding the column titles; field names are read from it. Omit it and the row directly above `position` is used when it looks like a header — all text, over data that is not." - added
Input schema / properties / key_fieldAdded value: +{ + "description": "Which field identifies a row. Omit and the first column whose values are all present and all different is used.", + "type": "string" +}
- Changed
create_block1 field changed- added
Input schema / properties / descriptionAdded value: +{ + "description": "What this table is for, in a sentence or two: what a row represents, what the fields mean where the names are not obvious, and anything a later reader must not do to it (e.g. a field the craft maintains). Saved with the block and returned by describe_block, so write it for whoever opens the file next rather than for this conversation.", + "type": "string" +}
- Added
set_block_description
20 tool updates
v0.1.0- First observed
add_block_rows - First observed
convert_to_block - First observed
create_block - First observed
create_sheet - First observed
delete_block_rows - First observed
describe_block - First observed
eval_formula - First observed
export_xlsx - First observed
get_cells - First observed
goal_seek - First observed
list_blocks - First observed
list_violations - First observed
move_block_row - First observed
open_workbook - First observed
preview_changes - First observed
save_workbook - First observed
set_block_cells - First observed
set_cells - First observed
set_field_rule - First observed
trace
TDQS
Scored across 31 tools
Most tools have clearly distinct resource+action boundaries, and the block/cell split is explained well. A few pairs could cause misselection—set_cells vs set_block_cells, describe_block(include_rows) vs get_cells, and chart_insert vs chart_from_block—but the descriptions do enough to disambiguate them.
The dominant verb_noun pattern (create_block, set_field_rule, add_block_rows) is consistent and predictable. The chart tools break it with noun_verb names (chart_list, chart_update, chart_delete), and chart_insert/chart_from_block sit awkwardly together, creating minor but noticeable deviations.
At 31 tools this crosses the 'too many' threshold, even though the tools cluster into coherent groups like charts, pivots, blocks, and diagnostics. Several chart-related tools could be consolidated, and the surface is heavy for an agent to hold and route between in context.
The surface covers the full spreadsheet workflow well: workbook lifecycle, block CRUD, cell access, formulas, charts, pivots, analysis blocks, validation, and even dependency tracing and goal seeking. Minor gaps exist—no delete_block or delete_sheet, no explicit sheet listing, and no formatting/rename operations—but agents can work around them.
Maintenance
Related MCP Connectors
Structured financial modeling for AI agents: build, version, audit models, export to Excel.
A structured financial modeling layer for AI agents. Build, version, and audit financial models without drift, then export to Excel, from Claude or any MCP client. Learn more: https://layerz.cc/for-agents
Connect AI assistants to Google Sheets through controlled tools for reading and updating rows.
Open, inspect, filter, edit and convert xlsx and csv files from your AI chat. Processing is local.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables AI agents to create, read, and manipulate Excel files without requiring Microsoft Excel installation. Supports comprehensive spreadsheet operations including formulas, formatting, charts, pivot tables, and data validation.MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI agents to create, read, and modify Excel workbooks without requiring Microsoft Excel, supporting operations like formulas, charts, pivot tables, formatting, and data validation.MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI agents to create, read, and manipulate Excel workbooks without Microsoft Excel installed, supporting formulas, formatting, charts, pivot tables, and data validation operations.MIT
- AlicenseAqualityCmaintenanceEnables AI agents to directly create, read, edit, and save Excel (.xlsx) spreadsheets using natural language through the Model Context Protocol, supporting cells, sheets, formatting, and formulas without writing Python code.215MIT