Note (2026-04-24): After this document was written,
legal_entitywas renamed totenantand the oldtenantwas renamed toorganization. Read references to these terms with the pre-rename meaning.
Agents using the FP&A MCP tools to answer financial questions have three issues:
They don't discover the Data Map. orcha-fpna-context sounds like a setup
tool, so agents skip it and manually scan files. The Data Map — which maps
every financial data point to a file, sheet, and cell range — goes unused.
Scanning is slow. Profiling one sheet requires 3-5 tool calls (summary, read headers, sample rows, merged regions). A 10-sheet workbook needs 30+ round-trips before the agent understands the file.
No search capability. Agents can't locate a string (e.g., "Umsatzerlöse") across sheets without reading ranges and scanning manually.
orcha-fpna-excel), not in bulk via orcha-fpna-list-files.orcha-fpna-context → orcha-fpna-data-map
orcha-fpna-data-mapRetrieve the financial data map for a legal entity — a structured index of all known financial data sources (budget, payroll, AR, revenues, cash flow, travel expenses) with file locations, sheet names, and cell ranges. Returns one of three statuses: 'boot' (no data map exists — returns the discovery protocol to create one), 'draft' (partial data map from a previous session — returns protocol + draft for continuation), or 'ready' (complete data map for downstream use). You MUST call this before using orcha-fpna-excel or orcha-fpna-list-files.
orcha-fpna-excel (prepended):
IMPORTANT: You MUST call orcha-fpna-data-map first to check if the data you need has already been mapped. The data map tells you which file, sheet, and cell range contains each financial data point. Do not scan files manually if a data map already exists.
orcha-fpna-list-files (prepended):
IMPORTANT: You MUST call orcha-fpna-data-map first. If a data map already exists, it tells you where all financial data lives — you may not need to list files at all.
excel/profile (Replaces excel/summary)New sandbox function. One call per sheet returns everything an agent needs for triage.
(excel/profile "SheetName")
{:row-count 64
:column-count 18
:headers ["" "Jan" "Feb" ... nil nil]
:sample-rows [["Revenue" 100 200 ...] ...]
:merged-regions [{:range "B1:F1"} ...]
:named-ranges [{:name "Revenue" :refers-to "P&L!$B$2:$B$50" :scope :workbook}]}
column-count: max .getCellCount across all rows (true sheet width).headers: first row, padded to column-count with nil.sample-rows: rows 2 through min(11, row-count), padded to column-count.merged-regions: same as excel/merged-regions for that sheet.named-ranges: only ranges whose :refers-to references this sheet, plus
workbook-scoped ranges.excel/summary Removalexcel/summary is removed from the sandbox. excel/sheets remains for listing
sheet names. Agents use excel/profile per sheet for structure.
excel/find (Cross-Sheet Search)New sandbox function. Searches for a substring across all sheets.
(excel/find "search string")
[{:sheet "P&L" :cell "A15" :value "Umsatzerlöse"}
{:sheet "Budget" :cell "A22" :value "Umsatzerlöse (Plan)"}]
{:truncated true} as the
last element.Stream each sheet's rows. For each cell with a string/formula-text value, check
if the lowercased value contains the lowercased search term. Collect matches as
{:sheet :cell :value} with the cell address in Excel notation (e.g., "B15").
orcha-fpna-excelThe function reference section becomes:
**excel/sheets** `()` — Returns vector of sheet names.
**excel/profile** `(sheet-name)` — Returns a complete profile of a sheet:
row-count, column-count (true max width), headers (first row),
sample-rows (rows 2-11), merged-regions, and named-ranges scoped to
that sheet. Use this to understand a sheet's structure in one call.
**excel/read** `(range)` or `(range opts)` — Reads cells. Range uses
Excel notation. Always returns a 2D vector, padding short rows with nil.
**excel/find** `(search-string)` — Case-insensitive substring search
across all sheets. Returns up to 100 matches as
[{:sheet s :cell ref :value v} ...].
**excel/merged-regions** `(sheet-name)` — Returns merged cell ranges.
**excel/named-ranges** `()` — Returns all non-hidden named ranges.
excel/summary is removed. The Available Clojure core list and Not available
notes remain unchanged.
All new functions (excel/profile, excel/find) and the excel/summary
removal require unit tests:
excel/profile: variable-width rows, empty sheets, merged regions included,
named ranges filtered by sheet, sample rows capped at 10.excel/find: substring match, case-insensitivity, cross-sheet results,
100-result cap, skips non-string cells.excel/summary removal: sandbox evaluation of (excel/summary) returns an
error.excel/profile and excel/find callable from SCI code.