Skip to main content
Glama
basis1: Excel engine for AI agents (formulas, recalculation, audit)

basis1: Excel engine for AI agents (formulas, recalculation, audit)

Official

Basis clients

Open-source clients for Basis, which parses Excel workbooks, evaluates formulas, traces dependencies and edits workbook models.

Package

What it is

Docs

@basis1/parse

TypeScript SDK for the Basis parsing API

sdk/

@basis1/mcp

MCP server that gives AI assistants Basis's workbook tools

mcp/

Both talk to the hosted Basis API (https://api.basis1.tech) and need an API key. The Basis engine and hosted service are separate and not part of this repository.

Quick start

npm install @basis1/parse
BASIS_API_KEY=… npx -y @basis1/mcp

Or run the MCP server from this repository with Docker:

docker build -t basis1-mcp .
docker run -i --rm -e BASIS_API_KEY=… basis1-mcp

Each package's README covers usage, configuration and what's sent over the network.

Related MCP server: Excel MCP Server

Development

Node 20.19 or later. The MCP server depends on the SDK through file:../sdk, so build the SDK first:

(cd sdk && npm ci && npm run build && npm test)
(cd mcp && npm ci && npm run build && npm test)

See CONTRIBUTING.md before opening a pull request, and SECURITY.md to report a vulnerability privately.

License

Apache License 2.0. See LICENSE.

Available Tools

26 tools
add_sheetAdd sheetAInspect

Add an empty sheet at the end of a session's workbook and make it the active sheet (the one unqualified refs like "B4" point to). Only for sessions created blank (create_session with no file); on an imported workbook it fails, so work in its existing sheets with set_inputs instead. To retitle a sheet use rename_sheet; to remove one use delete_sheet. Returns {sheet_index, sheet_name, sheet_count}.

Inputs: name (required), session_id (required).

audit_workbookAudit workbookA
Read-only
Inspect

Check a session's whole workbook for modeling problems and return a JSON report: broken references, circular references and whether they converge, hardcoded plugs (a constant or odd formula breaking a run of consistent formulas), external links, volatile functions, hidden sheets and names, stale cached values, and a verification block comparing Basis's computed values with the ones Excel last saved. Recalculates first and changes nothing else. Use it as a health check before trusting or handing off a model; for structure only use inspect_model, for one value's lineage trace_dependencies, and to compare two files diff_workbooks.

Inputs: session_id (required).

close_sessionClose sessionA
DestructiveIdempotent
Inspect

End a session and discard its workbook: the session_id stops working and the session can't be reopened. Edits not saved with save_to_library (or downloaded with export_workbook) are lost, and its commit_session checkpoints go with it, so restore_session can't bring it back. Call it when you're done with a workbook, or to free a slot when create_session fails with max_sessions. Returns {closed: true}, plus unsaved: true and a hint when the workbook was edited since it was opened or last saved to the Library. An unknown, expired or already closed session_id fails with session_not_found, which lists the sessions still open. Sessions also close on their own after 30 minutes without a call.

Inputs: session_id (required).

commit_sessionCommit sessionAInspect

Create a named checkpoint of the session's current state, e.g. before a risky edit. Returns {commit_id, message, total_commits}; pass commit_id to restore_session to roll back. Every call adds a new checkpoint. Checkpoints live in the session only and are lost when it closes or expires; to keep one in the Library's version history, call save_to_library after it (the version takes this message as its name).

Inputs: message (required), session_id (required).

create_sessionCreate sessionAInspect

Open a workbook in a session that the other workbook tools then use by session_id: the starting point for reading, editing, recalculating and exporting a model. Pass at most one of path, base64 (raw .xlsx bytes) or url, or none for a blank workbook (the only kind add_sheet can extend). The workbook is recalculated on load, including formulas written by other tools without cached values, so opening a file you edited elsewhere is how you read back what its formulas compute (get_outputs, get_formula_range); change inputs with set_inputs. Returns {session_id, document_id, library_file_id, sheets: [{index, name}], defined_names, calc}. For a one-off recalculation of a file, use recalc_workbook instead; to try a formula without a file, use evaluate_formula. The workbook is uploaded to the Basis API and held there for the session. Pass library_file_id instead to open a file from your Library. Each API key can hold 5 open sessions, and a session closes on its own after 30 minutes without a call. A sixth create_session fails with max_sessions and lists the open sessions; close one first. save_to_library keeps the workbook beyond the session.

Inputs: url, calc, path, base64, +2 more.

define_variableDefine variableA
DestructiveIdempotent
Inspect

Create a defined name for a cell, or repoint an existing one, so set_inputs and get_outputs can use a readable key ("Revenue") instead of a cell ref. A name that already exists in the same scope is overwritten with the new target; no cell's value or formula changes. Names follow Excel's rules (start with a letter, _ or , no spaces, not a cell ref) and invalid ones fail the call. Returns {name, refers_to, defined_names}, the last being every name after the change. To remove a name use delete_variable; to see the existing names first, use inspect_model.

Inputs: name (required), refers_to (required), session_id (required), scope_sheet.

delete_sheetDelete sheetA
Destructive
Inspect

Delete a sheet from a session's workbook, found by its 0-based index (see the sheets list from create_session or inspect_model), the way Excel does: formulas on other sheets that referenced it now read #REF! (Gone!A1 becomes #REF!A1) and evaluate to #REF!, a 3D range ending on it (Jan:Mar!B2) shrinks to the neighbouring sheet, names scoped to it are removed and names that pointed into it refer to #REF!. Sheets after it move down one index, so re-read indexes from the result before the next call. Works on imported and blank workbooks, and recalculates. It can't be undone: restore_session brings back other cells but not the sheet, so export_workbook or save_to_library first if you may need it. Returns {deleted: {sheet_index, sheet_name}, sheets: [{index, name}], active_sheet, formulas_broken (up to 200 cell refs), formulas_broken_count, names_removed, names_broken}. The last sheet, the last visible sheet or an index past the last sheet fails with bad_request and changes nothing. To retitle a sheet use rename_sheet; to empty one without breaking references, overwrite its cells with set_inputs.

Inputs: session_id (required), sheet_index (required).

delete_variableDelete variableA
DestructiveIdempotent
Inspect

Delete a defined name from a session's workbook, e.g. one you made with define_variable and no longer need. Only the name goes; the cell it pointed to keeps its value and formula. Match is by name, ignoring case, in workbook scope or, with scope_sheet, the name scoped to that sheet. A name still used by a formula is not deleted: the call fails with name_in_use and lists those cells, so rewrite them with set_inputs (or repoint the name with define_variable) first. A name that doesn't exist in that scope fails with not_found, and Excel's built-in names (print areas, filters) can't be deleted. restore_session doesn't bring a deleted name back; define_variable recreates it. Returns {deleted, scope_sheet, defined_names}, the last being every name left. To see the names first, use inspect_model.

Inputs: name (required), session_id (required), scope_sheet.

diff_workbooksDiff workbooksA
Read-only
Inspect

Compare two .xlsx files cell by cell and return the differences as JSON: {summary, added, removed, changed, format_changed}. Cells are matched on (sheet title, cell ref); changed covers value and formula changes, and format-only changes are listed separately. Use it to see what changed between two versions of a file, such as before and after an edit. For problems inside one workbook use audit_workbook; to undo edits in a session use restore_session. Provide exactly one of before_path/before_url/before_base64 and one of after_path/after_url/after_base64. Both files are uploaded to and parsed on the Basis API (up to 20 MB each) and count against the API key's parse quota; nothing is stored.

Inputs: after_url, after_path, before_url, before_path, +3 more.

evaluate_formulaEvaluate formulaA
Read-only
Inspect

Evaluate an Excel formula and return the computed result: a quick way to check what a formula returns on a few sample values before you put it in a workbook. Pass data as a map of cell references to values (e.g. {"A1": 100, "A2": true, "A3": "#N/A", "B1": "hello"}) and a formula string (e.g. "SUM(A1:A2)"). Values keep their Excel types, as in a workbook: true/false are logical cells (so SUM, AVERAGE and COUNT skip them in a range), a string that is exactly an error code (#N/A, #DIV/0!, #VALUE!, #REF!, #NAME?, #NUM!, #NULL!) is that error, and other strings are text. The formula is placed in row 1 of the first column right of your data, so don't reference that cell. Returns {formula, result, type, stats}, type being "number", "string", "boolean" or "error". A formula that evaluates to an Excel error returns type "error" with the code (#VALUE!, #N/A…) as a normal result; a formula that can't be parsed or uses an unsupported function is a tool error. Supports 278 Excel functions: math, financial (NPV, IRR, XIRR, PMT, PRICE, YIELD…), statistical distributions, regression, lookup, date/time, text, logical, and dynamic arrays (FILTER, SORT, UNIQUE, SEQUENCE, CHOOSECOLS, TAKE, DROP). Array expressions evaluate element by element inside SUMPRODUCT, LOOKUP, AGGREGATE, SMALL/LARGE, MATCH and INDEX. To check formulas that already live in a workbook, use create_session instead. Runs on the Basis API (needs an API key).

Inputs: formula (required), data.

export_workbookExport workbookA
DestructiveIdempotent
Inspect

Get a session's workbook back as an .xlsx file with every formula's computed value saved in it. Recalculates first. Call this when you need the file itself: to give it to the user, or to read it with pandas, openpyxl (data_only=True) or any tool that is not Excel. Returns the file and a summary of formula errors (#REF!, #DIV/0!, #NAME? with sheet and cell) and of anything that did not survive the save. Everything Basis does not model (styles, charts, images, data validation, defined names, comments, VBA) is carried over from the original file unchanged. Pass output_path to save the file on this machine.

Inputs: session_id (required), overwrite, output_path.

get_formula_rangeGet formula rangeA
Read-only
Inspect

Read the formulas and computed values of one cell or a rectangular range in a session: the way to check what a cell or a block of cells computes. Pass a single cell ("B4", "Sheet1!B4") or a range ("A1:D10"). Returns {worksheet, range, cell_count, cells: [{cell, formula, value, value_type}]}, with formula including its leading "=" (null for constants and empty cells) and value_type "number", "string", "boolean", "error" or "empty". Read a block in one call rather than cell by cell; to read values by defined name use get_outputs, and for the cells that feed one use trace_dependencies. Every cell in the rectangle is returned, up to 2,000 cells a call; a larger range fails with range_too_large, so read a big block in pieces. An unknown sheet or malformed range fails the call.

Inputs: range (required), session_id (required).

get_outputsGet outputsA
Read-only
Inspect

Read computed values from a session by defined name, cell or range: the way to check what a model's formulas return, e.g. after set_inputs. Pass names as defined names, cell refs ("B4", "Sheet1!B4") or ranges ("Sheet1!H2:H18", up to 2,000 cells, one entry per cell); omit names to read every defined name. Returns {values: {: {cell, type, value}}}; a cell holding an Excel error comes back with type "error" and its code, not as a tool failure, while a key that isn't a defined name or valid ref fails the call. Values only: for formula text use get_formula_range, and to see what feeds a value use trace_dependencies.

Inputs: session_id (required), names.

inspect_modelInspect modelA
Read-only
Inspect

Summarize a session's structure: each sheet's index, name and used rows and columns, every defined name with its target, the iterative-calc settings, and counts of cells, memory, edit events and commits. Use it to find your way around a workbook before reading or editing it: sheet indexes for rename_sheet, delete_sheet and define_variable, names for get_outputs and set_inputs. include_edges adds every formula dependency edge, which is large on big models; to follow the chain from one cell use trace_dependencies instead. For errors, plugs and broken references use audit_workbook.

Inputs: session_id (required), include_edges.

list_library_filesList Library filesA
Read-only
Inspect

List the workbooks in the user's Library: the files this account owns, newest-updated first, including everything save_to_library saved. Use it to find a library_file_id to open with create_session, or to check that a save landed. Returns {files: [{library_file_id, name, size_bytes, created_at, updated_at, latest_version: {seq, message, created_at}}], truncated}, times in ISO 8601; latest_version is the newest saved version and its name. Pass query to match part of a file name (ignoring case) and limit for how many to return (1-200, default 50); truncated is true when more files match, so narrow the query or raise limit. Shared files and the trash are left out. Fails with library_unavailable when the Library isn't connected. Reads your Basis Library through the API (needs an API key).

Inputs: limit, query.

list_sessionsList sessionsA
Read-only
Inspect

List the sessions open for this API key, to recover a session_id you've lost or to see how many are open before create_session. Returns {sessions: [{id, documentId, libraryFileId, createdAt, updatedAt, sheetCount, memBytes}]}, times in epoch milliseconds; closed and expired sessions are left out. Pass an id to any session tool, or to close_session to free a slot. Takes no arguments. Each API key can hold 5 open sessions, and a session closes on its own after 30 minutes without a call.

Inputs: no named parameters.

parse_workbookParse workbookA
Read-only
Inspect

Parse an .xlsx workbook in one call and return its full semantic NDJSON: one JSON record per line (workbook_meta, sheet, cell, edge, image, image_summary, audit), covering every cell's value and formula and the formula dependency edges. Use it to read a whole file without opening a session; large files are handed to an async job and awaited for you. To start a parse without waiting, use submit_job; to read a few cells or edit, use create_session; to compare two files, use diff_workbooks. Pass exactly one of path, url or base64 (up to 20 MB). The file is uploaded to the Basis API, and each call counts against the API key's parse quota (quota_exceeded once it is used up). webhook_url, if set, also gets an HMAC-signed POST when the parse finishes.

Inputs: url, path, base64, webhook_url.

recalc_workbookRecalculate workbookA
DestructiveIdempotent
Inspect

Recalculate an .xlsx file and return it with the computed values saved in every formula cell. Use this after you create or edit a workbook with openpyxl or any other library that writes formulas without results: those files have no cached values, so pandas, openpyxl (data_only=True) and other readers see empty cells until the file is recalculated. Replaces running LibreOffice recalc.py. Returns the file plus a summary of formula errors (#REF!, #DIV/0!, #NAME?, #VALUE!... with sheet and cell) and of formulas Basis could not compute: fix those and call again. Styles, charts, images, data validation, defined names, comments and VBA are carried over unchanged. Pass exactly one of path, url or base64. The workbook is uploaded to the Basis API for the recalculation and not kept. Pass output_path to save the result on this machine (the same path as the input, with overwrite: true, recalculates a file in place).

Inputs: url, path, base64, filename, +2 more.

rename_sheetRename sheetA
Idempotent
Inspect

Rename a sheet in a session's workbook, found by its 0-based index (see the sheets list from create_session or inspect_model). Formulas, named ranges and validations that reference the sheet are rewritten to the new name, so results don't change; use it rather than add_sheet when you only need a different title. Excel's rules apply: 1-31 characters, none of : \ / ? * [ ], no leading or trailing apostrophe, unique ignoring case; a name that breaks them, or an index past the last sheet, fails with bad_request. Returns {sheet_index, previous_name, sheet_name}.

Inputs: name (required), session_id (required), sheet_index (required).

restore_sessionRestore sessionA
DestructiveIdempotent
Inspect

Roll a session back to a checkpoint from commit_session: every cell edit made after it is undone, calc settings included, and the workbook is recalculated. Use it to throw away a what-if or a bad edit; it rewinds this session only and can't reopen a closed one. Returns {restored_to, cells_changed, calc, recalc}. A commit_id the session doesn't have fails the call. To compare two states without rolling back, export each with export_workbook and use diff_workbooks.

Inputs: commit_id (required), session_id (required).

save_to_librarySave to LibraryAInspect

Save the session's workbook to the user's Library for durable storage. If the session was loaded from the Library or was previously saved, this creates a new version of that file. Otherwise it creates a new Library file. Each save is a named version in the Library's history: pass message, or it takes the latest commit_session message since the last save. commit_session checkpoints themselves stay in the session, so save after each step you want kept as a version. Returns {library_file_id, version_id, name, message, created, noop}; noop is true when nothing changed since the last version. Open the file again later with create_session's library_file_id; list_library_files finds it.

Inputs: session_id (required), name, message.

set_calc_settingsSet calc settingsA
Idempotent
Inspect

Turn iterative calculation on or off for a session and recalculate. Needed for circular models (e.g. development pro formas where loan size depends on cost, which includes the loan's interest and fees): with it on, set_inputs re-converges the loop on every call. Saved with the session's next commit (restore_session to an earlier commit rolls it back) and written to the workbook, so an exported xlsx iterates in Excel too. Returns {calc, recalc}: the settings now in force and whether the model converged.

Inputs: iterative (required), session_id (required), max_change, max_iterations.

set_inputsSet inputsA
DestructiveIdempotent
Inspect

Write values or formulas into cells of a session and recalculate: the way to run a scenario on a model ("what if Revenue is 1.2M?"). Keys are defined names (e.g. "Revenue") or cell refs ("B4" on the active sheet, "Sheet1!A1"); values are numbers, booleans (logical TRUE/FALSE), error codes such as "#N/A", text, or a string starting with "=" to store a formula. Whatever the target cells held before is overwritten, so call commit_session first if you may want restore_session to undo it. The batch is all or nothing: a key that isn't a defined name or valid ref, or a formula that can't be stored, fails the call with invalid_input and no cell is written. Returns {applied, recalc, effects}: the cells written, recalc stats (with a warning for circular references that didn't converge) and each defined name whose value changed, with before and after. Read other results with get_outputs; to try a formula without touching the workbook use evaluate_formula; to create a name use define_variable.

Inputs: inputs (required), session_id (required).

stream_jobStream job outputA
Read-only
Inspect

Check on or read a parse job started by submit_job. By default it returns the job's NDJSON records once it has completed: the same output parse_workbook returns, one JSON record per line. Pass wait_seconds (up to 60) to wait that long for a job still processing; if it is still processing after that, the call fails with job_not_ready, so call again. Pass status_only: true to get the status instead, without waiting: {job_id, status, created_at, updated_at, expires_at, bytes_in, records_out, stream_url, error}, where status is "processing", "completed" or "failed". A failed job returns its parse error, and an unknown or expired job_id, or one submitted with another API key, fails with not_found. Everything after since comes back in one result, with no paging; pass since to skip records you already have. parse_workbook returns its result directly and needs no job.

Inputs: job_id (required), since, status_only, wait_seconds.

submit_jobSubmit parse jobAInspect

Start an async parse of an .xlsx workbook and return at once with a job handle {job_id, status: "processing", status_url, stream_url}. Use it instead of parse_workbook for large files or when you don't want to wait: call stream_job with wait_seconds to wait for the records (or status_only to just check). Every call starts a new job and counts against the API key's parse quota, so don't resubmit a file whose job is still running. Pass exactly one of path, url or base64 (up to 20 MB); the file is uploaded to the Basis API. webhook_url, if set, gets an HMAC-signed POST when the job finishes, so you can skip polling.

Inputs: url, path, base64, webhook_url.

trace_dependenciesTrace dependenciesA
Read-only
Inspect

Follow formula references from one cell in a session, breadth first, up to depth levels (1-5): direction "precedents" walks to the cells it reads, "dependents" to the cells that read it, and "both" (the default) does each. Returns {root, direction, max_depth, levels: [{depth, nodes: [{cell, formula, value, value_type}]}]} for one direction, or precedents and dependents (each a levels list) in place of levels for "both"; ranges are expanded to single cells and each cell is listed once per direction. Use it to explain where a number comes from, find the source of an error, or see what an input affects. For a cell's own formula use get_formula_range; for the whole graph at once use inspect_model with include_edges.

Inputs: cell (required), session_id (required), depth, direction.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A4.4/5.0

    Scored across 26 tools

    Disambiguation5/5

    Each tool has a clearly distinct purpose, and overlapping-seeming tools are explicitly differentiated: parse_workbook vs submit_job/stream_job (sync vs async parsing), get_outputs vs get_formula_range (values vs formulas+values), and inspect_model vs audit_workbook vs trace_dependencies (structure vs health vs lineage). The descriptions consistently cross-reference when to use an alternative tool, so an agent can select correctly despite the large surface.

    Naming Consistency5/5

    Tool names follow a consistent snake_case verb_noun pattern throughout: list_sessions, create_session, close_session, set_inputs, get_outputs, define_variable, delete_variable, inspect_model, trace_dependencies, audit_workbook, export_workbook, save_to_library. Minor variants like save_to_library are still readable and fit the same convention.

    Tool Count3/5

    The 26-tool surface is heavy and exceeds the typical well-scoped range, but it reflects a broad Excel engine covering sessions, parsing, editing, recalculation, auditing, and library storage. The set is mostly purposeful, though some consolidation (e.g. async parse tools, paired variable/sheet lifecycle tools) could reduce cognitive load.

    Completeness4/5

    Core workflows are well covered: open/parse, read, edit inputs, recalculate, inspect, audit, trace, export, and save. Minor gaps remain around structural editing and library lifecycle, such as no ability to add sheets to imported workbooks, no explicit clear-range operation, and no delete/version-management tools for Library files.

    Maintenance

    ActivityMaintained
    ResponsivenessOutdated data

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      D
      maintenance
      Enables 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
    • A
      license
      A
      quality
      B
      maintenance
      50 tools and 400 functions for working with Excel/.xlsx spreadsheets — read/write, recalculate formulas, diff, repair broken references, and audit. Built for AI agents.
      50
      2,388 npm
      6
      MIT
    • A
      license
      A
      quality
      B
      maintenance
      Enables AI agents to work with a real Excel-compatible spreadsheet engine, allowing them to create and manipulate structured data blocks, write and evaluate formulas, and save genuine .xlsx files with live formulas for human verification and reuse.
      31
      70 npm
      41
      MIT