get_native_sheet
Canonical purpose-aware display path for native input sheets and output sheet views, including requests to show a consolidated P&L. Use this instead of transcribing cells into a client-rendered table; supported MCP Apps bind through the standard _meta.ui.resourceUri metadata. Read one native sheet’s full content: tabs, cells, formulas, formatting, calculation status, staging, compare, and provenance.
read-only · idempotent
Parameters
Section titled “Parameters”| Name | Type | Required | Default | Description |
|---|---|---|---|---|
model_name | Annotated[str, Field(description='Name of the Bridge Town model that owns the sheet.')] | Yes | — | |
sheet_id | Annotated[str, Field(description='Sheet identifier, as returned by list_native_sheets.')] | Yes | — | |
tab_id | Annotated[str, Field(description="Optional tab_id to return only that tab's cells and bound the response size. Omit or pass an empty string to return all tabs.")] | No | '' | |
branch | `Annotated[str | None, Field(description=“Branch whose cached row to read. Omit to read the model’s default-branch row — passing the default branch’s own literal name (e.g. ‘main’) reads that same row.”)]` | No | None |
base_branch | `Annotated[str | None, Field(description=“Optional branch/ref to diff this sheet’s cells against. When given, each populated cell’s changed field is set (true when its formula or value differs from the base_branch version; formatting-only differences don’t count) and changed_cell_count reports the total. Omit to skip the comparison — changed stays null and changed_cell_count stays null rather than a fabricated value.”)]` | No | None |
compare_ref | `Annotated[str | None, Field(description=“Optional branch to compare this sheet’s cell/row values against — must be one of the response’s known_branches. Input sheets gain a compare_value per populated cell; output sheets gain row_deltas keyed by row label on their row-array tab(s). Omit to skip the comparison entirely. Independent of base_branch: base_branch flags whether a cell’s formula/value changed (bool), compare_ref returns the actual comparison value/delta.”)]` | No | None |
row_start | Annotated[int, Field(ge=0, description='0-indexed first row to include for a row-array tab (requires tab_id -- ambiguous across multiple tabs). Continues a previous truncated tab window; on sparse input tabs, it also continues a truncated staged-edit window. Ignored when neither window applies.')] | No | 0 | |
row_limit | `Annotated[int | None, Field(ge=1, description=‘Maximum rows to return for a row-array tab, starting at row_start (requires tab_id). On sparse input tabs it also caps staged edits; omit to let the server byte-bound either window. Check tabs[].window or staged_window to see what was included.’)]` | No | None |
workspace_id | `Annotated[str | None, Field(description=WORKSPACE_ID_FIELD_DESCRIPTION)]` | No | None |
Returns
Section titled “Returns”Returns a structured object. Top-level fields:
model_name(string)sheet_id(string)name(string)purpose(string)attached_model(string)branch(string)latest_commit_sha(string)sha(string)row_count(integer)tab_count(integer)calculation_status(string)tabs(array<object>)calculation(object)provenance(object)generated_at(string)base_branch(null)changed_cell_count(null)compare_ref(null)compare_state(string)staged(array)staged_count(integer)needs_recalculation(boolean)model_freshness(object)known_branches(array<string>)known_branches_truncated(boolean)header_row(null)annotation_rows(array)used_range(string)total_rows(integer)default_branch(string)workspace_id(string)
See the response example below for the full payload shape.
Example
Section titled “Example”Tool Call
Section titled “Tool Call”{ "name": "get_native_sheet", "arguments": { "model_name": "forecasts", "sheet_id": "assumptions" }}Response
Section titled “Response”{ "model_name": "forecasts", "sheet_id": "assumptions", "name": "Assumptions", "purpose": "input", "attached_model": "model/revenue.py", "branch": "main", "latest_commit_sha": "abc1234def5678901234567890abcdef12345678", "sha": "abc1234def5678901234567890abcdef12345678", "row_count": 2, "tab_count": 1, "calculation_status": "clean", "tabs": [ { "tab_id": "tab1", "name": "Sheet1", "row_count": 2, "column_count": 2, "cell_encoding": "sparse", "cells": { "A1": { "value": "Growth Rate", "formula": null, "format": null, "style": null, "number_format": null }, "B1": { "value": 0.12, "formula": null, "format": null, "style": null, "number_format": "percent" } }, "rows": [], "formatting": { "column_widths": {}, "row_heights": {}, "frozen_rows": 0, "frozen_columns": 0, "show_gridlines": true } } ], "calculation": { "engine_version": "v1", "status": "clean", "last_evaluated_at": "2026-04-28T10:00:00+00:00" }, "provenance": { "source": "user", "run_id": null, "commit_sha": "abc1234def5678901234567890abcdef12345678", "branch": null, "output_name": null, "data_hash": null }, "generated_at": "2026-04-28T10:00:00+00:00", "base_branch": null, "changed_cell_count": null, "compare_ref": null, "compare_state": "not_requested", "staged": [], "staged_count": 0, "needs_recalculation": false, "model_freshness": { "state": "fresh", "run_status": "success", "run_id": "66666666-6666-6666-6666-666666666666", "commit_sha": "abc1234def5678901234567890abcdef12345678" }, "known_branches": [ "main", "scenario/q2-hiring" ], "known_branches_truncated": false, "header_row": null, "annotation_rows": [], "used_range": "A1:B1", "total_rows": 1, "default_branch": "main", "workspace_id": "ws_acme"}Comparing against another branch
Section titled “Comparing against another branch”Pass compare_ref (one of the response’s own known_branches) to compare
this sheet’s values against another branch. compare_ref is independent of
base_branch: base_branch only flags that a cell changed (changed: true/
false), while compare_ref returns the actual comparison value or delta.
For an input sheet, every populated cell gains compare_value (or, when
the cell doesn’t exist on compare_ref, compare_unavailable_reason: "not_on_ref" instead):
{ "A1": {"value": 100, "compare_value": 100}, "B1": {"value": 250, "compare_value": 200}, "C1": {"value": 42, "compare_unavailable_reason": "not_on_ref"}}For an output sheet, each row-array tab gains a row_deltas object keyed
by the row’s first-column label (not row index — row order can differ
between runs, labels don’t). Each entry reports status
("equal" | "changed" | "not_on_ref") and a deltas array
(head_value - compare_value per column, null where either side isn’t
numeric):
{ "row_deltas": { "Revenue": {"status": "changed", "deltas": [null, 150]}, "COGS": {"status": "not_on_ref", "deltas": []} }}An unresolvable compare_ref (not one of known_branches) is a
whole-request error, not a per-cell marker.
For an output comparison, the counterpart is correlated by attached
model, output name, successful run, and branch provenance — never by the
generated sheet id. At most 16 candidates are verified. If no single safe
counterpart exists, compare_state is one of
output_identity_unavailable, output_counterpart_missing, or
output_counterpart_ambiguous, and the output tab carries the same
compare_unavailable_reason instead of fabricated row deltas.
Staging, freshness, and branch choices
Section titled “Staging, freshness, and branch choices”staged/staged_count: currently-staged MCP edits for the requested tenant, sheet, normalized branch, and (when selected) tab. They use the same per-cell ledger as staged-modewrite_native_sheet_cells; output sheets always return an empty list because they cannot be staged. When a staged list exceeds the response budget (or a sparse-input caller suppliesrow_start/row_limit),staged_windowreportsstart,end,total, andtruncated;staged_countremains the full ledger count. The staged page is capped at 32 KiB; a single oversized edit returns a structuredcontent_too_largeerror rather than being silently truncated.model_freshness:{state, run_status, run_id, commit_sha}derived from the resolved live Git commit and the latest scoped run, never a cache timestamp.stateisfresh,staged,stale,running,failed,no_run,static, oroutput.needs_recalculation:trueexactly forstaged,stale,running,failed, andno_run; it isfalseforfresh,static, andoutput.known_branches/known_branches_truncated: a sorted, deduplicated, list of valid, accessible branches usable ascompare_ref, capped at 200 names and 8 KiB. The default branch appears exactly once.known_branches_truncated: truemeans the repo has more accessible branches than fit those bounds — the branches actually returned are always a sorted prefix, never an arbitrary subset.
Renderer hints
Section titled “Renderer hints”header_row, annotation_rows, used_range, and total_rows describe one
tab’s structure and are only populated when the response resolves to exactly
one unambiguous tab (a tab_id was passed, or the sheet has only one tab).
For a multi-tab response with no tab_id, every hint reports its empty
default (null/[]/0) rather than silently describing a tab the caller
never asked for.
Output presentation profile readback
Section titled “Output presentation profile readback”An output tab with a saved profile includes one bounded
presentation_profile object beside its rows. It contains the validated
schema_version, selector rules, and the current OCC version. Resolve
that profile before a legacy cell number_format; the legacy "currency"
marker means USD and must not override a returned GBP or other ISO currency.
Use the returned version as expected_profile_version in
format_native_sheet, then call get_native_sheet again to verify the
updated profile without changing raw numeric values.
{ "tab_id": "tab_output", "presentation_profile": { "schema_version": 1, "version": 4, "rules": [ { "selector_type": "column", "selector": "Amount", "format": {"kind": "currency", "currency_code": "GBP"} } ] }}- Module:
Native Sheets - Requires authentication via API token or Auth0 JWT.