Skip to content

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

NameTypeRequiredDefaultDescription
model_nameAnnotated[str, Field(description='Name of the Bridge Town model that owns the sheet.')]Yes
sheet_idAnnotated[str, Field(description='Sheet identifier, as returned by list_native_sheets.')]Yes
tab_idAnnotated[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[strNone, 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.”)]`NoNone
base_branch`Annotated[strNone, 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.”)]`NoNone
compare_ref`Annotated[strNone, 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.”)]`NoNone
row_startAnnotated[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.')]No0
row_limit`Annotated[intNone, 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.’)]`NoNone
workspace_id`Annotated[strNone, Field(description=WORKSPACE_ID_FIELD_DESCRIPTION)]`NoNone

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.

{
"name": "get_native_sheet",
"arguments": {
"model_name": "forecasts",
"sheet_id": "assumptions"
}
}
{
"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"
}

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.

  • 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-mode write_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 supplies row_start / row_limit), staged_window reports start, end, total, and truncated; staged_count remains the full ledger count. The staged page is capped at 32 KiB; a single oversized edit returns a structured content_too_large error 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. state is fresh, staged, stale, running, failed, no_run, static, or output.
  • needs_recalculation: true exactly for staged, stale, running, failed, and no_run; it is false for fresh, static, and output.
  • known_branches / known_branches_truncated: a sorted, deduplicated, list of valid, accessible branches usable as compare_ref, capped at 200 names and 8 KiB. The default branch appears exactly once. known_branches_truncated: true means the repo has more accessible branches than fit those bounds — the branches actually returned are always a sorted prefix, never an arbitrary subset.

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.

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.