Read · Section 01

Workbook Refresh — Fill Your Own Spreadsheet from the Filings, With Citations

Fills an existing comp sheet or monitoring book from as-filed XBRL — input cells only, an accession beside every figure, UNKNOWN where the filing is silent.

Caterpillar, Deere and Paccar look like a five-minute comp-sheet refresh. But Deere's fiscal year ends in October, and neither Deere nor Paccar reports an operating-income line. Copy the numbers by hand and you end up with a margin column that compares two different metrics over two different twelve-month windows.

This recipe fills the comp sheet, monitoring book or covenant tracker you already keep. Claude reads your headers, writes only the cells a filing answers, and puts the 10-K's accession number beside each figure. Where the filing is silent, the cell says UNKNOWN and the summary says why.

Why this works with edgar.tools MCP

A wrong number in a spreadsheet looks exactly like a right one, and every formula that depends on it inherits the error. So each figure here comes from a filing you can open:

  • financial_statements returns line items as filed in XBRL, along with the accession of the filing that reported them.
  • Ask it for statement: "breakdown:segment" (or product, geography) and you get revenue by segment, plus a check on whether the segments add up to consolidated revenue. Deere's run $468M over, which is intersegment sales. Caterpillar's include a subtotal line. You find out before either reaches your revenue-mix column.
  • company_filings confirms which 10-K or 10-Q Claude is reading, so an October year-end can't slip in next to a December one.
  • Every response carries data_quality (as_of, is_stale), so you know when the latest filing is already months old.

How to use

Open the workbook with edgar.tools connected and ask:

Refresh this sheet from the latest annual filings. Cite every number, and flag anything you could not fill.

It works on your own sheets and on the Excel templates. In a chat without a spreadsheet, paste the header row and ticker column and you get the filled table back.

Prompt — paste this into Claude, ChatGPT, or Gemini

The framework (v1.0)

You are filling an analyst's existing workbook from SEC filings. The workbook is the specification: you do not redesign it, you populate it. Your output is judged on whether every number you wrote is traceable and whether every number you could not source was left visibly empty rather than guessed.

Non-negotiables

  • Read the sheet's shape before fetching anything. Identify the header row, the column that holds tickers or company names, and the period each column wants. Fetching first and mapping afterwards is how a value lands in the wrong column.
  • Write input cells only. Never overwrite a formula. If a target cell contains a formula, leave it alone, put the value in the nearest free cell or a note, and say so in your summary. A formula is somebody's modelling decision; a number is just a number.
  • Every figure names its filing. Put the accession in the sheet's source column if it has one; otherwise add a Sources row or a cell comment. A figure with no source is a figure the analyst cannot defend in a meeting.
  • If the filing does not state it, write `UNKNOWN`. Do not substitute a near-neighbour: a pre-tax margin is not an operating margin, and a segment total is not a consolidated one. Silently swapping metrics is the single most damaging thing you can do here, because the column header will still say the metric you did not use.
  • Never compute across a half-filled row. Leave derived cells to the workbook's own formulas. Excel reads a blank as zero, so a difference or a ratio you compute over missing inputs produces a confident number that means nothing.
  • Check the period labels. A column headed "FY2025" means different dates for different filers — fiscal years end in October as readily as December. Put the period-end date in the sheet, or in your summary, so two rows are never silently compared across different year-ends.
  • Surface staleness. If data_quality.is_stale is true, or the latest filing predates the period the sheet asks for, say so rather than filling the column as though it were current.

Workflow (ordered, mandatory)

Step 1 — Map the sheet

State back, in one short block: the sheet name, the header row, which column identifies the company, which rows are to be filled, and which columns you believe each map to. Name any column you cannot map — "column E 'Quality score' looks like a house metric; I will leave it" — and do not fetch anything for it. If the ticker column is empty, stop and ask; there is nothing to fill.

Step 2 — Confirm the filing, per company

Call company_filings({ company: "<ticker>", form: "10-K" }) (or 10-Q when the sheet wants quarters) and note the accession and filing date you are about to read. This is one cheap call that prevents the expensive error: reading a period the sheet did not ask for.

Skip it when the sheet only wants the latest annual figures and you will accept whatever financial_statements returns as latest — but then report the source_accession it used, so the period is still visible.

Step 3 — Pull the numbers

Call financial_statements({ company: "<ticker>", statement: "income_statement", period: "annual" }) — one call per company covers most comp sheets. Use balance_sheet or cash_flow only if the sheet's columns actually ask for them; each extra statement is another call and most comp sheets do not need them.

Read values off line_items by standard_concept where present (Revenue, Operating Income, EPS Diluted, Net Income), falling back to label when it is not. Take the value under the period-end date the sheet wants, not simply the first one.

Not every filer reports every line. Many report no consolidated operating-income line at all, going straight from costs to a pre-tax figure. When the concept you need is absent, that cell is UNKNOWN — say which line the filer reports instead, in your summary, and let the analyst decide whether it is an acceptable substitute. That decision is theirs, not yours.

Segment, product or geography columns. When a column asks for revenue by segment, product line or region — "Segment revenue", "% International", "Americas", a revenue-mix block — call financial_statements({ company: "<ticker>", statement: "breakdown:segment", period: "annual" }), with breakdown:product or breakdown:geography as the header asks. Do not read the segment note out of the filing text for this; the breakdown is the tagged table. Each group's members carry values by period end and a share_pct, and the group carries a check:

  • sums_to_total — the members add to consolidated revenue. Write them.
  • sums_to_total_excluding_overlap — one member (marked overlaps) is a subtotal or a nested region. Write the others; never add the overlapping one into a mix.
  • exceeds_total — the members run a few percent over, usually intersegment sales; unallocated is the elimination. Write the members as filed and name the elimination in your account.
  • partial — the members fall short; unallocated is corporate or other revenue the breakdown does not assign. Write the members and state the gap.
  • overlapping — some member is a subtotal of the others (a share_pct over 100 gives it away). Write only the named business segments, never a total computed from them, and say which member you left out.

Never sum segments into the consolidated revenue column; that column comes from the income statement. For geography, countries lists every country the filing reports exactly or inside a named bundle — a country not listed is not broken out, so its cell is UNKNOWN, not a figure derived from "International" or "Rest of world". A breakdown comes from one filing at a time; its source_accession goes in the source column like any other figure.

Optional (+1 call per company). financial_snapshot returns pre-computed ratios if the sheet wants margins and returns you would otherwise derive. Use it when several ratio columns are wanted; skip it for two or three.

Step 4 — Write, then account for what you wrote

Fill the input cells. Then produce a short written account: how many cells you filled, how many you left UNKNOWN and why, any formula cell you declined to touch, any period mismatch between rows, and any staleness warning you saw.

Do not skip this because the sheet "looks right". The account is what makes the refresh checkable without re-reading every filing.

Required output

Write the cells, then reply in Markdown — no code block — using this shape:


WORKBOOK REFRESH — [sheet name] [N] companies · [period] · refreshed YYYY-MM-DD

Company[metric][metric][metric]Source
…………Form + date

Filled — [N] cells across [N] rows. Left empty — [cell refs]: [why, naming the line the filer does report if there is one]. Not touched — [any formula cells, and what you did instead]. Period note — [any row whose fiscal period differs from the others]. Freshness — [any is_stale or lag worth stating].


Stopping conditions

  • No ticker or company column → stop and ask. There is nothing to map.
  • A ticker resolves to candidates → list them and ask; do not pick.
  • The sheet asks for a metric no filing reports (analyst estimates, consensus, target prices, market data) → say so plainly. Consensus is not in EDGAR, and no amount of searching filings will produce it.
  • The whole column would be UNKNOWN → report that before writing anything; the column probably wants a metric the filings express under another name, and the analyst can tell you which.
Then askRun this on CAT.

What MCP-grounded refreshing adds

Claude on its ownClaude with edgar.tools
The figuresRecalled from training, often for the wrong fiscal yearRead from the filing, with its accession
Which filingYou can't tellNamed on every response and checkable with company_filings
A metric the filer doesn't reportSwapped for something closeLeft UNKNOWN, with the line the filer does report
Fiscal year-endsAssumed to line upA period-end date on every value
Segment revenueRebuilt from the footnoteTagged table, with a check on whether it adds up
Stale dataYou don't find outis_stale on every response

Sample output structure

Caterpillar, Deere and Paccar, from their latest 10-Ks. Two margin cells stay empty, and the account under the table says why.

Sample LLM output — what this recipe returnsPreview

WORKBOOK REFRESH — Machinery comps 3 companies · latest FY (10-K) · refreshed 2026-08-30

CompanyRevenue ($M)Operating marginDiluted EPSPeriod endSource
Caterpillar67,58916.5%18.812025-12-3110-K, filed 2026-02-13
Deere & Co45,684UNKNOWN18.502025-10-3110-K, filed 2025-12-18
Paccar28,445UNKNOWN4.512025-12-3110-K, filed 2026-02-18

Filled — 10 cells across 3 rows.

Left empty — C3, C4 (operating margin, Deere and Paccar): neither filer reports a consolidated operating-income line. Deere goes from total costs to Income of Consolidated Group before Income Taxes ($6,257M); Paccar reports Income before income taxes ($2,677.4M). Both are pre-tax, both include items an operating margin excludes — a pre-tax margin here would be 13.7% and 9.4%, which is not the metric column C asks for. Substituting one for the other would make the column silently incomparable, so the decision is yours: keep the column operating-only and accept two blanks, or re-label it pre-tax and I will fill all three.

Not touched — no formula cells in the filled range; the EV/EBIT column is left to the sheet's own formulas.

Period note — Deere's fiscal year ends 2025-10-31, two months before the other two. The rows are one fiscal year each but not the same twelve months; a revenue-growth column across these three would compare different windows.

Freshness — Caterpillar's backing source carried is_stale: true (freshness_lag_days: 116) at capture. The FY2025 10-K is the latest annual filing for all three, but a newer 10-Q may exist for any of them.

Revenue by segment — the sheet's mix block, from breakdown:segment on the same two 10-Ks:

CompanySegmentFY revenue ($M)ShareCheck
CaterpillarPower & Energy27,14340.2%overlapping
CaterpillarConstruction Industries25,06037.1%
CaterpillarResource Industries12,47418.5%
CaterpillarFinancial Products4,2206.2%
Deere & CoProduction & Precision Ag17,74938.9%exceeds_total
Deere & CoConstruction & Forestry11,65025.5%
Deere & CoSmall Ag & Turf10,46422.9%
Deere & CoFinancial Services6,28913.8%

Caterpillar's group also carries Reportable Segment Aggregation Before Other Operating Segment at $73,955M — 109.4% of consolidated revenue, a subtotal, so it was left out; All Other Segments ($46M) is below the sheet's rows. Neither company's segments add to consolidated revenue: Caterpillar's segments, All Other included, run $1,354M over $67,589M, and Deere's unallocated is −$468M against $45,684M — intersegment sales both filers eliminate. The shares are of consolidated revenue, so they do not sum to 100%, and the Revenue column above stays the income-statement figure.

Sample captured 2026-08-30 from live `financial_statements` and `company_filings` calls on the linked filings; segment block captured 2026-09-27 from `financial_statements` with `statement: "breakdown:segment"` on the same accessions — refreshed when the figures age a fiscal year.

Every refresh ends with that account: what was filled, what was left empty and why, what was left alone, and which rows cover different periods. Whoever checks the sheet next can see where each number came from without reopening the filings.

  • 10-K Speedrun — when a refreshed row raises a question about a company you don't know well.
  • Insider Activity Interpreter — for the monitoring book: what insiders did in the names you hold.
  • Earnings Release Decoder — when a company has just reported and the 10-K isn't filed yet.