# MetricDuck — Financial Analysis MCP server

SEC filing intelligence for AI agents. Financials, screening, peer comparison for 5,000+ companies.

## Links
- Registry page: https://www.getdrio.com/mcp/com-metricduck-financial-analysis

## Install
- Endpoint: https://mcp.metricduck.com/mcp
- Auth: Not captured

## Setup notes
- Remote endpoint: https://mcp.metricduck.com/mcp

## Tools
- browse_company (Browse Companies) - Entity-axis navigation primitive — an orientation map for one company.

Returns a single response containing identity (incl. CIK), the text-extracted filing inventory by form type (the subset with extracted section text — NOT the company's full SEC filing history; use `list_filings` for the complete registry incl. filed-but-unextracted rows), **signal availability inline**, indexed range, and ranked drill-down pointers — so one call tells you which signals fire for the company and which axis to descend next (signal-axis, source-axis, or metric-axis). Accepts a ticker, a company name, or a CIK, so it also resolves the entity.

Compared with `search_companies`: that one is the resolver — it matches a name or partial name across companies and carries the SEC EDGAR entity link, filer_type, fiscal year-end and former names. Use it to pick between candidates; use this when you already know the company and want its inventory.

**When to use:**
- Starting a research thread on a single company
- Confirming what data MetricDuck has indexed before deep-diving
- Discovering which signals fire (M&A, partnerships, guidance shifts, accounting flags) without needing to fetch a filing first

**When NOT to use:**
- Cross-company screening → use `screen_companies` (metrics) or `screen_filing_signals` (signals)
- Concept/theme discovery → use `search_sec_filings`

**Drill-down map (the response will recommend specific calls based on what's available):**
- `get_filing_index(ticker)` — full signal map for the latest filing
- `get_xbrl_facts(ticker, search="...")` — dimensional financial drill-down

_(atom v1: revisit response shape after first 5 q001/q012/q003 traces)_ Endpoint: https://mcp.metricduck.com/mcp
- search_companies (Search Companies) - Resolve a company name or ticker to the exact ticker symbol via fuzzy name/ticker match.

**Scope:** exact-entity lookup only. Handles partial names ("micro" -> MSFT), typos, and ticker variations.
Returns ticker, full name, CIK, SIC, filer type (domestic / foreign private issuer / fund — i.e. which
form family to expect), fiscal year-end, and a primary-source SEC EDGAR entity-page link (verify the
resolution + see the company's full filing history) for each match.

**Use this when:** you have a specific company name or ambiguous ticker and need to confirm the exact ticker before calling other tools.

**Delisted / renamed / acquired companies** are resolvable by current OR former name (e.g. "American Software" → Logility, "Chase Manhattan" → JPM). They are returned ranked below active matches, flagged `[delisted]`, with their CIK. They have no current ticker — pass the returned `cik` to downstream tools (company tools accept a CIK in place of a ticker, except `get_stock_price`, which needs a ticker).

**Input tip:** queries matching the pattern of 2-5 uppercase letters are auto-extracted as a ticker. If you pass an all-caps company name (e.g., "AMCOR") that is NOT a ticker, the lookup may miss — pass "Amcor" with normal casing to force name-search behavior. On miss, this tool returns suggested near-matches when possible.

**Do NOT use this for concept/theme/industry discovery** (e.g., "gold miners", "LNG exposure", "companies mentioning tariffs"). This tool matches on company-name text only — it cannot surface companies by what they do. For concept discovery, use `search_sec_filings` (full-text search across filings) or `screen_companies` (metric + sector filters).

**Coverage boundary:** MetricDuck is **SEC-EDGAR only**. This tool is the authoritative coverage check. A no-match on a **non-US local-exchange symbol** (e.g. `3087.T`, `LSE:HSBA`, `7203:JP`) is a coverage boundary, not a lookup miss — the tool says so explicitly and you should treat it as **terminal** (don't retry ticker variations). Foreign issuers that file a US 20-F/40-F (HSBC, Toyota, Novo Nordisk…) ARE covered — reach them by **company name**, not their local symbol. Endpoint: https://mcp.metricduck.com/mcp
- get_company_overview (Company Overview) - Get comprehensive financial overview for a company in a single call.

Includes: current price, valuation (P/E, P/B, EV multiples, PEG), profitability (revenue, margins, returns),
cash flow (OCF, FCF, yields), balance sheet (debt, equity, ratios), capital allocation (buybacks, shares outstanding, shareholder yield),
business segment + geographic revenue mix (latest 10-K, with YoY change), latest earnings insights, filing intelligence highlights, and company flags.

Depth presets:
- depth="snapshot" — headline facts only (~2K chars): title, key signals, filing signals summary, flags, latest filing pointers. Best for multi-ticker sequencing or quick health checks.
- depth="core" (default) — full overview with valuation, profitability, segments, cash flow, balance sheet, capital allocation, and earnings.
- depth="full" — core + all tags (no 7-tag truncation), all earnings highlights/concerns (no 3-item truncation), plus 5Y historical distribution (median/p25/p75/p90) for P/E, EV/EBITDA, EV/FCF.

Latest snapshot only — use get_financials for multi-year trends, get_xbrl_facts for multi-period segment history, get_filing_index for a signal map of the latest filing, compare_companies for peer benchmarking, get_stock_price for a historical/as-of-a-date close or a return between two dates (the price here is current only).

POINT-IN-TIME / AS-OF: this overview does NOT take an as-of date — every figure is the latest snapshot. For a backtest or "as of <past date>" analysis (avoiding look-ahead), do NOT read the as-of state off this tool; route to the as-of-capable tools instead: get_financials(vantage_date="YYYY-MM-DD") for the statements filed on/before that date, get_filing_section/get_filing_index(vantage_date=…) for the then-current filing text/signals, get_xbrl_facts for point-in-time facts, and get_stock_price for the close on/after a date.

Use search_companies first if unsure of the exact ticker. Endpoint: https://mcp.metricduck.com/mcp
- get_stock_price (Stock Price (Daily)) - Daily end-of-day stock prices (open/high/low, close, split- & dividend-adjusted adj_close, volume) for US exchange-listed companies. Sourced from a market-data feed, not SEC filings.

Markets are open only on business days, so rows exist ONLY for trading days — the data IS the trading calendar:
- Price ON OR AFTER a date (e.g. an announcement landing on a weekend): pass start_date=<date>; the FIRST row is that date or the next open day.
- Price ON OR BEFORE a date: pass end_date=<date>; the LAST row is that date or the prior open day.
- A single specific date: pass start_date=<date> (omit end_date) — returns a short forward window whose first row is your on/after price.

Use Cases:
- "AAPL close on 2025-07-28" -> get_stock_price("AAPL", start_date="2025-07-28") (first row = that day or next open day)
- "DKNG total return 2025-01-02 → 2026-02-27" -> TWO calls: get_stock_price("DKNG", start_date="2025-01-02") and get_stock_price("DKNG", end_date="2026-02-27"); take each first/last close and compute the return (cheaper than one 14-month window)
- "SUI 1/14/30 calendar days after an 8-K date" -> get_stock_price("SUI", start_date="<announce>", end_date="<announce + ~32d>"), then pick the first row on/after announce, +1, +14, +30
- "Latest price" -> get_stock_price("AAPL")

When the window spans ≥2 trading days, the response also reports the first/last close and the period return on BOTH close (literal point-to-point) and adj_close (split/dividend-adjusted — the true economic return; the two diverge across a split or dividend).

Each response also includes the latest REPORTED period-end shares outstanding on/before your end date (period-end balance-sheet count; dei cover where absent) plus the implied market cap at the latest close — use these for market-cap / EV / P/B math instead of deriving share counts from NI/EPS (that yields weighted-average shares, a different basis).

Coverage: ~8,400 US common-equity tickers, end-of-day only (no intraday/real-time, no options/FX). Recent history is dense; deep pre-2014 history may be sparse. For period-end valuation multiples (P/E, EV/EBITDA, P/B) use get_metric_history; to assemble a CUSTOM multiple (e.g. lease-adjusted EV) combine this price with get_metric_history("ticker","oper_lease_liabs" / "ttl_debt" / "cash_st_invs" / "ttl_equity" / "shares_basic"). Endpoint: https://mcp.metricduck.com/mcp
- get_financials (Financial Statements) - Get multi-period financial statements: income statement, balance sheet, and cash flow in one call.

Returns quantitative historical data with key metrics and trends. Default: all 3 statements, quarterly, 2 years.
For qualitative analysis (risks, accounting quality, management tone), use get_filing_index (signal map) then get_filing_section to read the text.

Use Cases:
- "Show me AAPL's financials" -> all statements
- "MSFT revenue trend 5 years" -> period="annual", years=5
- "Is Tesla's debt increasing?" -> statements=["balance"]
- "As of a past date / point-in-time" -> get_financials("MSFT", vantage_date="2024-04-30") (values as known from filings published on/before that date)

Each period cites its original disclosing SEC filing (accession + filed date in a footnote; resolvable EDGAR index handles in the `<raw_data>` block), so every figure is traceable to its source filing.

**Exactness:** the markdown table ABBREVIATES (`$68.14M`) — it quantises to $10K above $1M and $10M above $1B, so it is not a tie-out surface. The `<raw_data>` block carries the exact stored value (`68135000`). Quote figures from `<raw_data>`, not the table, whenever the precise number matters.

Responses capped at ~20K chars. If truncated, whole statements are dropped (not sliced) with a note — request fewer statements or reduce years. Note the cap also trims `<raw_data>` periods, so a truncated response can lose the exact channel for the dropped periods. Endpoint: https://mcp.metricduck.com/mcp
- compare_companies (Compare Companies / Peers) - Compare a company against peers across ~70 curated fundamental metrics (TTM), with percentile rankings and relative strengths/weaknesses.

Returns a side-by-side table covering valuation (P/E, P/B, EV/EBITDA, EV/Sales, FCF yield), profitability (gross/operating/net/EBITDA margins, ROE, ROA, ROIC),
leverage & liquidity (debt/equity, net debt/EBITDA, interest coverage, current ratio), efficiency (asset/inventory turnover, DSO, cash conversion cycle),
and capital returns (dividend yield, dividend payout ratio, buyback yield, shareholder yield). Sector-inapplicable metrics are omitted (e.g. gross margin / FCF leverage for banks).

Pass 'metrics' to focus the table on specific metric_ids. This is a TTM cross-sectional snapshot — for a single company's value in a specific fiscal year/quarter use get_metric_history. Each company's row is dated: 'Data through' is its latest reported period, and valuation multiples are priced at the last close on/before that period end (period-end LOCF) — NOT today's price, and the dates can differ across peers by a quarter. For a multiple AS OF a specific date, or at the live price, or a CUSTOM definition (e.g. lease-adjusted EV), assemble it from get_stock_price (price leg) + get_metric_history primitives.

peer_mode controls peer selection:
- 'sector' (default): auto-selected from same sector + similar market cap
- 'tags': auto-selected by business model similarity (tag Jaccard) — better for cross-sector comparisons

Override with custom_peers for specific matchups. The number of custom_peers is capped by plan (Free: 3, Pro: 10); exceeding it returns the limit and the count you asked for, so retry with that many.
Data sourced from SEC EDGAR, updated with each quarterly/annual filing.

Use Cases:
- "Compare AAPL vs MSFT" -> compare_companies("AAPL", custom_peers="MSFT")
- "How does NVDA stack up in its sector?" -> compare_companies("NVDA")
- "Dividend payout ratio: KO vs KDP/PEP/KHC" -> compare_companies("KO", custom_peers="KDP,PEP,KHC", metrics="dividend_payout_ratio,dividend_yield")
- "COST vs WMT vs TGT" -> compare_companies("COST", custom_peers="WMT,TGT")

Responses capped at ~20K chars. If truncated, use fewer custom_peers or a 'metrics' subset. Endpoint: https://mcp.metricduck.com/mcp
- screen_companies (Screen Companies by Metrics) - Screen 5,500+ US companies by financial metrics. Find stocks matching quantitative criteria.

Metric IDs (canonical names from filing_metrics):
- Valuation: pe_ratio, pb_ratio, ev_ebitda, fcf_yield, market_cap, ev
- Profitability: gross_margin, oper_margin, net_margin, ebitda_margin, roe, roa, roic
- Cash Flow: fcf, net_cf_ops, cash_conversion
- Balance Sheet: debt_to_equity, current_ratio, ttl_debt, ttl_equity, cash_st_invs
- Size: revenues, net_income, ebitda, gross_profit

Growth screening: set period_type — e.g. metric_id="revenues" with period_type="ttm.yoy" (YoY). Growth pairs served: revenues/net_income/eps_basic/eps_diluted/fcf/roic @ ttm.yoy, revenues/fcf @ ttm.cagr3, ttl_assets @ ss.yoy.

Period types: ttm (default), ss (balance sheet snapshot), the growth pairs above, and q.med8/q.trend8/q.stdv8 valuation-quality series (pe_ratio, ev_ebitda, ev_fcf, roic). The screener serves LATEST-snapshot values; an unsupported metric+period combination returns a 422 naming the supported set — for other periods or full history use get_metric_history.

Sectors: TECH, FIN, HEALTH, CONS_STAPLES, CONS_DISC, IND, ENERGY, UTIL, RE, MAT, COMM
Operators: gt (>), gte (>=), lt (<), lte (<=), eq (=), between

Tag filtering (required_tags / excluded_tags) selects by business-model classification; unclassified companies are excluded from tag-filtered results.

Note: margins, returns and ROIC are decimals (0.15 = 15%). Negative P/E means losses — add a gt(0) filter to exclude loss-makers.

Use Cases:
- "High ROIC tech stocks" -> filters=[{metric_id:"roic", operator:"gt", value:0.15}], sectors=["TECH"]
- "Undervalued profitable industrials" -> filters=[{metric_id:"pe_ratio", operator:"lt", value:15}, {metric_id:"pe_ratio", operator:"gt", value:0}], sectors=["IND"]
- "Revenue growing >10% YoY" -> filters=[{metric_id:"revenues", operator:"gt", value:0.10, period_type:"ttm.yoy"}]
- "AI infrastructure companies not exposed to China supply chain" -> required_tags=["ai_ml_infrastructure"], excluded_tags=["china_supply_chain_heavy"]
- "Profitable subscription businesses" -> filters=[{metric_id:"net_margin", operator:"gt", value:0.10}], required_tags=["subscription_recurring"]

To screen by filing SIGNALS (tone, covenant risk, material weakness, etc.), use screen_filing_signals — a universe-correct cross-company signal screen — then intersect with a metric screen here.

Responses capped at ~20K chars. If truncated, reduce limit or add stricter filters. Endpoint: https://mcp.metricduck.com/mcp
- list_filings (List Filing Sections) - Browse Sources inventory and the section catalog for a single company. Covers SEC filings: 10-K, 10-Q, 8-K, DEF 14A, plus 20-F / 40-F / 6-K for foreign private issuers.

**Scope:** filings-metadata utility. Returns filing list (form type, dates, accession numbers) plus per-section details (word count, chunk count, tables) for 10-K/10-Q/DEF 14A; 8-K returns filing metadata only. Default: last 2 years. Use `fiscal_year` + `fiscal_period` to pin a single historical PERIODIC filing (10-K/10-Q) in one call — 8-K sub-types are not period-indexed, so pair `form_subtype` with `years` instead.

**For signal triage and "what matters" in a filing, use `get_filing_index` instead.** Use `list_filings` only when:
- You need an accession_number for a specific historical filing (before `get_xbrl_facts` or `get_filing_section`)
- You need to pin a specific fiscal year/period (e.g., FY2020 Q3)
- You need the full section inventory with sizes to plan pagination
- You need to confirm whether a specific filing exists

Sister Sources (non-SEC): earnings call transcripts → `compare_earnings_calls`; IR press releases / events → `screen_filing_signals` with signal_type="ir_press_release".

**Delisted / acquired issuers**: pass `cik` (10-digit, zero-padded) instead of `ticker` and set `include_delisted=true`. SEC's ticker registry excludes delisted issuers, so `ticker`-only calls 404 even when MetricDuck holds the filings. Example: SAVE Spirit Airlines (`cik="0001498710"`).

Data horizon: 2013+. Responses capped at ~20K chars; narrow via `form_type`, `fiscal_year`, or reduce `years`. Endpoint: https://mcp.metricduck.com/mcp
- get_filing_section (Read Filing Section) - Read a specific section from an SEC Source (10-K, 10-Q, 8-K earnings, 8-K events, or DEF 14A proxy).

**Two modes:**
1. **Section mode (default)** — pass section_id for full paginated text (up to 10 chunks per page).
2. **Outline mode** — OMIT section_id, pass accession_number: returns the filing's section TOC with ~120-char previews, so you pick by content instead of guessing an id. Use it on an unfamiliar Source (multi-exhibit 8-K, DEF 14A, FPI 6-K).

Omitting accession_number reads the latest filing; `list_filings` finds a specific one. Valid ids are listed under `section_id` below.

Use Cases:
- "Apple risk factors" -> get_filing_section("AAPL", "risk_factors")
- "Customer concentration in NVDA" -> get_filing_section("NVDA", "risk_factors", query="customer concentration")
- "Workforce / headcount by geography" -> get_filing_section("MSFT", "business_description", query="human capital")
- "M&A terms" -> get_filing_section("CVX", "item_1_01_material_agreement", form_type="8-K")
- "As of a past date / point-in-time" -> get_filing_section("MSFT", "business_description", vantage_date="2025-04-07") (serves the latest filing on/before that date — don't assume the newest filing reflects a past vantage)
- "Multi-exhibit 8-K" -> get_filing_section(ticker, accession_number="...") (outline mode) → pick exhibit → drill by section_id

Sister Sources (non-SEC):
- Earnings call transcripts → `compare_earnings_calls`, or list_filings + section_id="transcript_prepared_remarks"
- IR press releases / events → `screen_filing_signals` with signal_type="ir_press_release"; earnings-DECK guidance / operational KPIs (in neither the filing nor XBRL) → `get_ir_documents`
- Raw XBRL dimensional facts → `get_xbrl_facts`
- Year-over-year risk-factor change → `screen_filing_signals(signals=["has_new_risks"], ticker=…)` — a computed vs-prior-filing signal, cheaper and more reliable than diffing two filings yourself
- A figure ABSENT from the section you expected → `search_sec_filings(company=<ticker/CIK>, query="exact phrase")` locates which section of which filing carries it — absence from one section does not mean the filing lacks it

**Delisted / acquired issuers**: pass `cik` (10-digit, zero-padded) instead of `ticker` and set `include_delisted=true` — e.g. SAVE Spirit Airlines (`cik="0001498710"`).

Responses capped at ~20K chars. Use offset for pagination or query to narrow results. Endpoint: https://mcp.metricduck.com/mcp
- get_xbrl_facts (Raw XBRL Facts) - Raw XBRL facts from SEC filings — use only when `get_financials` cannot answer the question.

**Scope:** escape-hatch for dimensional / industry-specific / as-filed numbers. ~3,000 facts per filing with dimensional breakdowns (segment, geography, product line). Search by human-readable label, not XBRL concept names.

**First try `get_financials`** — 323+ standard metrics across TTM/FY/Q + YOY/CAGR for all 5,500+ companies: faster, cheaper, more portable across tickers.

**Use `get_xbrl_facts` only when:**
- You need a segment / geographic / product-line breakdown that `get_financials` aggregates away — available only for concepts the filer XBRL-tags dimensionally (usually revenue + segment profit / Adjusted EBITDA). Segment **costs** are frequently NOT tagged; a relaxed-search miss returns the recipe for recovering them.
- You need **revenue concentration / share** by customer, channel, distributor, geography, or product — the as-filed `ConcentrationRiskPercentage` facts. Deterministic, and present even when the prose only describes the relationship qualitatively. Search `concentration`.
- You need an industry-specific metric not in the standard catalog (e.g., `medical cost ratio` for a health insurer, `reserve replacement ratio` for an oil & gas name)
- You need to verify a specific number from filing text against the as-filed XBRL value
- You need a historical fiscal year not returned by `get_financials` (pass `fiscal_year`)
- You need a cash-flow / income **line across periods to de-cumulate a standalone quarter** — the as-filed cash-flow statement is cumulative YTD. Set `period_history: true` (see that parameter for the subtraction recipe).

**Sign — read this before quoting a direction.** `<raw_data>.value` is the raw as-filed XBRL instance value. It is a positive magnitude for outflow / contra-asset concepts (`PaymentsTo…`, capex, accumulated depreciation) but is **signed by construction** for the `IncreaseDecreaseIn…` working-capital family. The table shows that value, except where the instance value is negative AND carries the negated-label role — there it shows the filed face instead (so a working-capital *decrease* reads as the positive source of cash the statement shows).

`(filed −)` is a **best-effort hint, not a guarantee**: it comes from the filing's label linkbase and is recorded PER CONCEPT, so it fires on every use of a concept that is presented negatively *anywhere* in that filing — including lines the filing presents positively. Real example: Texas Instruments tags `IncomeTaxExpenseBenefit` with a negated label in its AOCI reclassification table, so its income-statement "Provision for income taxes" carries `(filed −)` even though the statement face reads `709`, not `(709)`.

**So: trust the value, treat the flag as a prompt to check.** When direction is load-bearing, confirm against the `edgar` fact link — or use `get_financials`, which applies a curated statement-sign map instead of the linkbase flag.

**Exactness:** the markdown rounds for readability; the `<raw_data>` block carries each fact's EXACT value + `decimals` (the as-filed precision floor: −3 = thousands, −6 = millions) + `edgar` — a deep-link to that exact fact in the SEC EDGAR iXBRL document, so every value resolves to the independent primary source.

**Share counts (pick the right basis):** the **dei** `EntityCommonStockSharesOutstanding` (shown as "cover-page / current") is the most-current shares outstanding, as of the filing/cover date — use it for **market cap, equity value, and "shares outstanding from the cover page"**. The **us-gaap** `CommonStockSharesOutstanding` is the **balance-sheet period-end** count (an earlier date); `WeightedAverageNumberOf…SharesOutstanding` is the **per-period average for EPS**. These can differ a few % for buyback-heavy / recently-issuing filers — match the as-of date in the Period column to your task.

Searching: commas OR-match (`revenue,product`); SPACES WITHIN a term AND-match, across the concept name, its label, and the filer's own dimension axis/member labels. A multi-word search is therefore a filter on the FILER's wording, not on meaning — it can drop the exact series you want with no warning. Start with ONE word and narrow client-side. Responses cap at ~20K chars — over it, whole facts are paged out of BOTH the table and the `<raw_data>` block together (the JSON stays valid) with an explicit `facts_omitted` count; narrow the search for the rest.

**No `vantage_date`** — the DEFAULT path resolves the latest filing as of TODAY. A past filing IS exactly reachable: pin it with `accession_number` (from `list_filings`, which takes `vantage_date`) or `fiscal_year`/`fiscal_period` — pin the filing rather than assuming latest for as-of work. Endpoint: https://mcp.metricduck.com/mcp
- get_filing_index (Filing Signal Index) - Get a navigable signal index for a company's latest SEC filing.

Returns typed facts extracted from the filing, each with evidence and a section pointer for drill-down.
This is the "table of contents" for what's in the filing — use it to decide WHAT to read.

The index is agnostic to your intent — all facts presented neutrally. Pick the facts relevant
to YOUR analysis, then drill with get_filing_section(). Facts from LLM analysis are labeled as such.

Optional lens parameter filters to a specific analytical view:
- earnings_quality: SBC, accounting flags, material weaknesses
- debt_stress: debt profile, covenant compliance, near-term maturities
- risk_trajectory: risk factors, escalations, key uncertainties
- competitive_position: segments, customer/channel/geographic concentration
- management_outlook: tone, guidance, guidance accuracy

Use this as the lightweight first-look map of what's in a filing before drilling into the text with get_filing_section.

IMPORTANT — indexes only the LATEST filing. For a PRIOR quarter's operating KPIs (same-store
/ comparable sales, ARPU, take-rate, bookings), forward GUIDANCE, or a BEAT/MISS-vs-guidance
question (e.g. "FND same-store sales in Q4 2024", "did MU beat its Q3 gross-margin guidance"),
do NOT page through the latest 10-Q/10-K — those metrics live in that quarter's EARNINGS-RELEASE
8-K, which MetricDuck extracts (comparable sales, KPIs, guidance, beat/miss) per quarter. Route:
list_filings(ticker, form_subtype="8-K-earnings", years=N) — each row is labelled with its implied fiscal period, so pick that quarter's accession from the list (do NOT pass fiscal_year/fiscal_period here; 8-Ks are not period-indexed), then
get_filing_section(ticker, "earnings_press_release" | "earnings_income_statement" | "earnings_segment_data",
accession_number=<that 8-K>). The release NARRATIVE — highlights, forward GUIDANCE/outlook, CEO commentary —
lives in "earnings_press_release" (target it with query="outlook"); "earnings_document_map" is now a compact
TOC (headline metrics + table/section index — call get_filing_section with accession_number and NO section_id
for the outline). (compare_earnings_calls(ticker) gives the cross-quarter KPI/guidance trajectory.)

Use Cases:
- "What should I look at in AAPL's 10-K?" -> get_filing_index("AAPL")
- "Any accounting red flags for ENPH?" -> get_filing_index("ENPH", lens="earnings_quality")
- "Debt situation for BA?" -> get_filing_index("BA", lens="debt_stress")
- "How is TSLA management framing things?" -> get_filing_index("TSLA", lens="management_outlook")
- "FND same-store sales in Q4 2024?" (prior-quarter KPI) -> list_filings("FND", form_subtype="8-K-earnings", years=3) -> get_filing_section("FND", "earnings_press_release", accession_number=<Q4 2024 8-K>) (the narrative/guidance prose; "earnings_document_map" is the compact TOC)

Sister Sources (non-SEC):
- Earnings call transcripts → `compare_earnings_calls` (cross-quarter view)
- IR press releases / events → `screen_filing_signals` with signal_type="ir_press_release" Endpoint: https://mcp.metricduck.com/mcp
- screen_filing_signals (Screen Filing Signals) - Screen companies by signals across all source types — filings, earnings, transcripts, IR events.

This is NOT metric screening (use screen_companies for P/E, ROIC, etc.).
Screens by verifiable facts, not LLM-generated scores.

Signals span five source types — 10-K/10-Q filing intelligence, 8-K/6-K earnings releases, earnings-call transcripts, IR press releases, and DEF 14A proxies. Full id catalog with labels: see the `signals` parameter.

Use Cases:
- "Which tech companies have cautious management?" -> signals=["tone_cautious"], sectors=["TECH"]
- "Does NVDA have any tone_shifted recently?" -> ticker="NVDA", signals=["tone_shifted"], recency_days=30
- "Did AAPL disclose new risk factors vs last year's 10-K?" (year-over-year risk surveillance) -> ticker="AAPL", signals=["has_new_risks"] — prefer this over reading risk_factors for two periods via get_filing_section and diffing the prose by hand
- "Companies that gave specific guidance on calls?" -> signals=["transcript_has_guidance"]
- "Which companies announced strategic partnerships or M&A deals?" -> signals=["ir_partnership"]

Cross-filing composition (Brief 35 — Pattern 4):
`ir_partnership` matches on M&A / partnership 8-K anchors (Item 1.01) carry a `companion_accessions: string[]`
field in their payload value when the announcement is split across an anchor + same-day companion 8-K
(7.01 Reg FD + Ex 99 press release / 8.01 other events). To read the full announcement narrative — CEO quotes,
deal terms, investor-presentation text living in the companion — pass those accession numbers to
`get_filing_section({..., section_id:"item_1_01_material_agreement", include_companions:true, companion_accessions:[...]})`.
Empty list means no companion exists or the producer hasn't backfilled it (acceptable; anchor-only flow still works). Endpoint: https://mcp.metricduck.com/mcp
- search_sec_filings (Full-Text SEC Filing Search) - Search the full text of every SEC filing since 2001 to find companies related to any concept — a product, technology, regulation, event, or company.

Returns filing-level results with aggregated statistics (company count, form type breakdown, industry distribution). For 10-K/10-Q filings processed by MetricDuck, also shows WHICH SECTIONS contain the term with drill-in pointers.

**Searchable form types** — any SEC form since 2001; omit `form_type` to search all:
- Periodic reports: 10-K, 10-Q (section-level drill-down available), 20-F, 40-F, 6-K (foreign private issuers)
- Events + proxies: 8-K, DEF 14A / DEFM14A / PRE 14A
- Registration + offerings: S-1, F-1, S-3, S-4, 424B series
- Ownership + other: SC 13D, SC 13G, SD (conflict minerals), N-CSR / N-CSRS (fund reports)

**Section-level enrichment** (10-K/10-Q only): results name which sections contain the term, with chunk pointers for drill-in via get_filing_section. Other forms return filing metadata + accession numbers only.

Use cases:
- "Who supplies Apple?" → ticker_lookup="AAPL" → companies listing Apple in revenue footnotes
- "Recent data breaches?" → query="cybersecurity incident", form_type="8-K"
- "Tariff-exposed companies?" → query="tariff", form_type="10-K" → risk factor disclosures
- "Activist campaigns?" → query="board representation", form_type="DEF 14A,SC 13D"

When to use other tools instead:
- You already know the company → `get_filing_index` (signal triage) or `list_filings` (filing inventory)
- You want financial metrics → `screen_companies` (numeric filters)
- You want earnings call cross-quarter view → `compare_earnings_calls`

Key limitation: keyword matching only, not semantic. "No material weakness" matches "material weakness found." Verify hits with `get_filing_section` for context.

Search tips: quoted exact phrases ("material weakness"); proximity `NEAR(5)`; `OR` / `NOT`; trailing wildcards (`restructur*`).

**Historical event queries** (M&A announcements, lawsuits, restructurings, leadership changes): the default 1-year `date_from` and `rank_by="date"` ordering bury historical anchors under mutual-fund NPORT-P holdings. For specific events, prefer `form_type="8-K"` + widen `date_from` to before the event + `rank_by="relevance"` — this surfaces the anchor 8-K in the top results instead of fund noise. Endpoint: https://mcp.metricduck.com/mcp
- get_earnings (8-K Earnings Release Financials) - 8-K earnings-RELEASE financials — headline income statement (revenue, net income, operating income, diluted EPS) PLUS the as-released cash-flow statement (operating cash flow, capex, free cash flow, +growth) — the figures management reports on release day, typically WEEKS before the audited 10-Q/10-K. On release day this is often the ONLY structured source for the fresh quarter's capex/OCF/FCF (the 8-K carries no XBRL, so get_financials/get_metric_history still show the prior quarter until the 10-Q lands).

Distinct from get_financials (audited XBRL 10-K/10-Q statements — filed later, GAAP-consistent) and get_company_overview (single-period snapshot; its earnings section is prose only, no figures). Use this tool for the earliest-available as-reported release figures, each with a per-figure deep-link + verbatim quote into the source exhibit when the API has an attested receipt.

Use Cases:
- "What did NVDA report for its latest quarter's revenue?" -> get_earnings("NVDA")
- "TSLA's last 8 quarters of earnings releases" -> get_earnings("TSLA", quarters=8)

Release figures are management's own characterization and may be non-GAAP-adjacent — verify against the quote when precision matters. A figure without a receipt is still shown (often filled from a prior extraction pass or awaiting the producer's validation) but without a deep-link — absence of a receipt is not evidence the value is wrong.

Point-in-time: pass `vantage_date` (YYYY-MM-DD) to serve the releases KNOWN on/before that date — the `quarters` walk back from the vantage instead of today. Sibling as-of tools: `get_filing_section`, `get_filing_index`, `list_filings`, `get_financials`, `get_metric_history`, `compare_earnings_calls`. (`get_company_overview` is NOT as-of-capable — it always serves the latest snapshot.)

Adjacent tools: get_financials for audited XBRL statements across multiple periods; get_company_overview for a single-period snapshot; get_guidance_vs_actual to join this release's actuals against prior guidance. Endpoint: https://mcp.metricduck.com/mcp
- get_guidance_vs_actual (Guidance vs Actual) - Did management deliver what they guided? Joins forward guidance from earnings-call transcripts to reported actuals from 10-K/10-Q + 8-K earnings for the same ticker + fiscal period.

Returns both sides verbatim with quotes and locators — agents synthesize the delivered-vs-guided narrative. This is a cross-feed temporal join; no single feed answers this question.

Use Cases:
- "Did NVDA deliver on Q2 FY2026 guidance?" -> get_guidance_vs_actual("NVDA", fiscal_period="Q2 FY2026")
- "How disciplined has MSFT been against its own guidance?" -> get_guidance_vs_actual("MSFT") then compare across periods
- "Latest period's guidance-vs-actual" -> get_guidance_vs_actual("TSLA") (period defaults to most recent)

Returns everything a beat/miss verdict needs — never the verdict. The comparison is basis-matched, as-reported-only arithmetic; the CALLER applies valence (whether "above guidance" is good is the caller's judgment, not MetricDuck's).

Use Cases:
- "Did NVDA deliver on Q2 FY2026 guidance?" -> get_guidance_vs_actual("NVDA", fiscal_period="Q2 FY2026") — read range_position (above/within/below) + delta and decide yourself.

Output:
- Guidance: forward items targeting the period — from earnings-call transcripts AND 8-K earnings releases (metric, value/range, basis, period, verbatim quote, source).
- Actuals: SEC 10-Q/K metric + narrative signals for that period, plus 8-K earnings signals when present.
- Comparison: for each guidance item, when it can be recomputed from the receipts on its OWN basis (GAAP vs non-GAAP matched, units aligned, period settled) — a neutral `range_position` (above | within | below the guided band) + signed `delta`. Otherwise a typed `status` says why NOT (no_actual_on_basis / not_yet_settled / value_unparsed / period_unresolved / value_incongruent) — never a false or guessed verdict. A non-GAAP guide is never compared to a GAAP actual.
- Notes: counts of calls/filings covered + comparison statuses so agents know coverage depth before interpreting.

**Not point-in-time.** No `vantage_date` — guidance↔actual joins reflect everything stored as of TODAY (a backtest at a past date would see actuals that had not yet been reported). For as-of work use a `vantage_date` tool: `get_earnings`, `get_financials`, `get_filing_index`, `compare_earnings_calls`. Endpoint: https://mcp.metricduck.com/mcp
- compare_earnings_calls (Compare Earnings Calls) - How has management's posture shifted across recent earnings calls? Cross-quarter trajectory view of transcript signals for a single ticker.

This is MetricDuck's EARNINGS-CALL TRANSCRIPT tool (agents also look for this as get_earnings_call_transcript / get_earnings_transcript / get_earnings_call / search_earnings_calls). For ONE call's verbatim prepared remarks or Q&A, drill with get_filing_section(section_id="transcript_prepared_remarks" | "transcript_qa_session"); this tool gives the cross-quarter view.

Different from get_filing_index (single-call triage map): this aligns calls by event date and surfaces CROSS-QUARTER patterns. For per-call depth, drill with get_filing_index.

Output (coverage-dependent): a coverage table per quarter — event date, fiscal period, accession, status, and transcript Source tier (SEC-filed vs Issuer-published vs Machine-transcribed), surfacing NO_TRANSCRIPT / WAITING gaps; transcripts are management commentary, not SEC-filed XBRL facts. Then an aggregate-trajectory table (Q&A Deflection / Concerns Retained / Forward Commits — one row per scalar, one column per quarter), guidance deltas grouped by metric, and the per-quarter qualitative arrays for whichever dimensions you request, surfaced side-by-side so drift is readable across columns. Drill hints are pinned to accessions.

Use Cases:
- "Deflection trend?" -> compare_earnings_calls("RDDT", n_quarters=8, dimensions=["hedges", "qa"])
- "Guidance discipline shifting?" -> compare_earnings_calls("NVDA", dimensions=["guidance"])
- "Strategic priorities + KPIs drift" -> compare_earnings_calls("PG", dimensions=["priorities", "kpi"])

Sister Sources: single-call deep read → `get_filing_section` (section_id="transcript_prepared_remarks" / "transcript_qa_session"); cross-period signal changes → `screen_filing_signals` with since_date/until_date; IR press releases → `screen_filing_signals` with signal_type="ir_press_release". Endpoint: https://mcp.metricduck.com/mcp
- get_metric_history (Metric History) - Time series for one metric across fiscal periods. Returns newest-first rows with fiscal_year + fiscal_period labels — AUTHORITATIVE for period-specific questions ("Q2 FY2025?"). The period_end calendar date is NOT the fiscal label, especially for non-December FYE companies (AAPL FY ends Sep; CRM FY ends Jan; ORCL FY ends May).

Each row with an SEC accession is cited back to the source filing via the MetricDuck viewer.

⚠ CONSOLIDATED ONLY — there is no segment/geography/product breakdown here, and no parameter adds one: the metrics layer sums those axes away, so per-member values are never stored. For a BY-SEGMENT series use `get_xbrl_facts(ticker, search="<segment name> revenue", period_history=true)` (as-filed dimensional facts) or `get_filing_section(ticker, "table_segment_reporting")` (the schedule, 3 fiscal years per 10-K).

Use Cases:
- "What was AAPL's Q2 FY2025 gross margin?" -> get_metric_history("AAPL", "gross_margin")
- "ROE last 5 years for MSFT" -> get_metric_history("MSFT", "roe", period_type="FY", window=5)
- "NVDA TTM revenue trend" -> get_metric_history("NVDA", "revenues", period_type="TTM")
- "ABNB gross booking value trend" -> get_metric_history("ABNB", "gross_booking_value") (operating KPI; quarterly or FY)
- "Net interest margin for a bank" -> get_metric_history("<bank>", "net_interest_margin")
- "As of a past date / point-in-time" -> get_metric_history("MSFT", "revenues", vantage_date="2024-04-30") (series as known from filings published on/before that date)

Also serves NON-XBRL operating KPIs (LLM-extracted from 10-K/10-Q MD&A + earnings releases), available QUARTERLY and ANNUAL (FY) — coverage varies by KPI. Spans banking (net_interest_margin, common_equity_tier_1_capital_ratio), insurance (combined_ratio), SaaS (arr, remaining_performance_obligations), retail/marketplace (store_count, same_store_sales, gross_booking_value, take_rate), lodging/REIT (revpar, occupancy_rate), airlines (passenger_load_factor, prasm, casm), energy (oil_production), workforce (headcount), and more — see the `metric_id` parameter for the common ids. Matching is strict (lowercase, exact spelling) and an unknown id returns the full served catalog, so guessing a canonical name is cheap. Financial-sector tickers (banks, insurers) often NULL on COGS-based metrics (gross_margin, gross_profit) — use sector-appropriate alternatives where available.

Price-derived multiples here (pe_ratio, ev_ebitda, pb_ratio…) use the PERIOD-END close; for a price on a SPECIFIC date use get_stock_price. To assemble a CUSTOM multiple (e.g. EV including operating leases) combine get_stock_price (price leg) with get_metric_history primitives: oper_lease_liabs, ttl_debt, cash_st_invs, ttl_equity, shares_basic.

**Latest fiscal year during earnings season:** full-year results post in an earnings 8-K weeks before the 10-K, which is what populates this structured FY series. If you query the latest FY inside that gap, the series ends one year early — this tool then appends a pointer to the earnings 8-K; follow it (get_filing_section "earnings_income_statement") rather than concluding the year is unavailable.

Adjacent tools: get_company_overview for a single-period snapshot across many metrics; get_financials for full statements (all line items) across multiple periods; get_stock_price for daily share prices and period returns. Endpoint: https://mcp.metricduck.com/mcp
- get_metric_lineage (Metric Lineage) - The DERIVATION of one COMPUTED metric — its human formula + immediate inputs (each value + source), one level at a time. The audit / verify affordance for derived figures (margins, ratios, ROIC, FCF, adj-EBITDA): call it ONLY when the query asks **how a metric is computed**, **which definition** MetricDuck used, or to **verify / audit** the derivation — NOT to get the value itself (use get_metric_history / get_company_overview for that).

Drillable (lazy, one level per call):
- a `derived` input points to its OWN derivation — call get_metric_lineage(ticker, that_symbol) to go deeper.
- a `base` input is an as-filed XBRL fact — open its filing handle, or get_xbrl_facts(ticker, search="<symbol>") to land on the exact fact.

Use Cases:
- "How is AAPL's net_margin calculated?" -> get_metric_lineage("AAPL", "net_margin")
- "Which ROIC definition does this use?" -> get_metric_lineage("AAPL", "roic")
- "Audit / verify gross_margin for Q2 FY2025" -> get_metric_lineage("AAPL", "gross_margin", fiscal_year=2025, fiscal_period="Q2")

Computed metrics only — a base as-filed figure has no derivation (the tool says so and points to get_xbrl_facts). Endpoint: https://mcp.metricduck.com/mcp
- get_ir_documents (IR Earnings Decks) - Retrieve IR earnings-PRESENTATION-DECK text — forward guidance, operational KPIs, and segment outlook that are ONLY in the company's investor-relations slide deck and NOT in the SEC 8-K/10-Q release text or XBRL.

Reach for this when the answer is a forward-looking guidance range or an operational KPI that the structured tools miss:
- get_metric_history / get_xbrl_facts return no series for a KPI or guidance figure
- get_filing_section finds the 8-K earnings release but it lacks the guidance/KPI (decks are a separate exhibit/source)

What lives here (not in XBRL/filing text): production or revenue guidance ranges, segment/division outlook, operational KPIs presented as slide charts (e.g., berth capacity %, Mboed production guidance, adjusted-EBITDA guidance).

Use Cases:
- "OXY Q3 2024 production guidance" -> get_ir_documents("OXY", fiscal_year=2024, fiscal_period="Q3", query="production guidance")
- "NCLH berth capacity outlook" -> get_ir_documents("NCLH", fiscal_year=2021, fiscal_period="Q3", query="berth")
- "KNTK adjusted EBITDA guidance range" -> get_ir_documents("KNTK", fiscal_year=2023, fiscal_period="Q3", query="EBITDA")

Each deck returns its title, original IR url, a stable MetricDuck-hosted gcs_uri, and the matching slide text cited by page. Pass a `query` to land on the exact page; omit it for a bounded prefix of the latest deck. Resolve by ticker or cik; narrow with fiscal_year/fiscal_period. Endpoint: https://mcp.metricduck.com/mcp
- get_company_events (IR Event Calendar) - Retrieve a company's IR event CALENDAR — UPCOMING and PAST investor-relations events (earnings calls, annual/shareholder meetings, broker conferences, investor days) with the materials attached to each (deck, webcast, press release, transcript).

Reach for this to answer time/calendar questions the document catalog can't:
- "When does {ticker} next report / hold its earnings call?" → the UPCOMING list (scheduled events)
- "What IR events did {ticker} have this year?" / "was {ticker} at any conferences?"
- "What materials are attached to {ticker}'s last earnings event?"

Each event has: occurred_at (issuer-local datetime) + time_precision, event_type (verbatim/open vocab), the verbatim source title, and material chips — each material's `material_id` is the get_ir_documents doc_id (a POINTER; read the content with get_ir_documents, not here).

Coverage is honest: if a company hasn't been harvested yet, that is stated — an empty result does NOT mean the company has no IR events. `last_checked_at` stamps the calendar's as-of time (events announced since are not shown).

For a deck's slide TEXT → get_ir_documents. For what management SAID on an earnings call (guidance/tone by quarter) → compare_earnings_calls.

**Not point-in-time.** No `vantage_date` — the upcoming/past split anchors on TODAY and the calendar reflects current knowledge. For as-of / backtest work use a `vantage_date` tool: `get_filing_index`, `list_filings`, `get_earnings`, `get_financials`. Endpoint: https://mcp.metricduck.com/mcp
- get_earnings_reports (Earnings Document Index) - Per-fiscal-period earnings DOCUMENT INDEX — one row per quarter/year gathering the documents for that reporting period: the 8-K press release, the earnings-call transcript (with prepared-remarks / Q&A deep-links), the 10-Q/10-K, the IR presentation deck(s), and the webcast event. Each artifact is present or honestly absent, so this is the "what can I pull for this quarter, and how do I reach it" map.

Reach for this to answer "what's available / where do I read it" per period:
- "What documents does {ticker} have for its last earnings?" → the newest row's artifacts (press release, transcript, deck, webcast, 10-Q)
- "Give me {ticker}'s earnings transcripts / decks by quarter" → the per-period transcript + deck links
- "Is there a webcast / presentation deck for {ticker}'s Q2?" → that row's webcast + deck cells (honest-absent when not harvested)

This is a NAVIGATION index, not figures. For the release NUMBERS (revenue / EPS / net income) use get_earnings; for audited XBRL statements get_financials; for the IR event CALENDAR (upcoming + past) get_company_events; for a deck's slide TEXT get_ir_documents; for what management SAID on the call (guidance/tone by quarter) compare_earnings_calls.

Coverage is honest per cell: a transcript reads present/pending/none; a deck join is exact (fiscal-period tuple, never a date); a webcast is a single-candidate ±1d match — and when the IR calendar isn't harvested that is stated (a missing webcast is NOT "no webcast held"). The response's `claimed` set is the deck/event ids this surface owns (so an IR-card consumer subtracts them cleanly).

**Not point-in-time.** No `vantage_date` — the index reflects documents as known TODAY. For as-of / backtest work use a `vantage_date` tool: `get_earnings`, `get_financials`, `get_filing_index`, `get_filing_section`, `list_filings`, `get_metric_history`, `compare_earnings_calls`. Endpoint: https://mcp.metricduck.com/mcp
- list_recent_filings (Recent Filings Feed) - Discover recent SEC filings landed since a watermark — single call, universe-wide, optional portfolio filter.

**Use this when:** building event-driven agent workflows (Routines, alerts, daily portfolio checks). The right primitive when the question is "what new filings have landed?" rather than "what filings does this one company have?".

**Returns:** flat list of {ticker, accession, filed_at, form_type, form_subtype}, newest filing date first and **largest issuers first within a date** — so `limit=15` during earnings week surfaces the banks and mega-caps that filed, not the alphabetically-first micro-caps. `form_subtype` is computed from the filing's section inventory: '8-K-earnings' (has any earnings_* section), '8-K-transcript' (has any transcript_* section), '8-K-event' (has any item_* section), '8-K-other' (8-K with none of the above), or null for non-8-K forms.

**Cost:** ~one call regardless of portfolio size — vs O(N) calls if you fan out per-ticker via `list_filings`.

**Composition:** for each row in the result, drill in via `get_filing_section(ticker, accession_number=...)` (omit `section_id` for the filing's section outline) to see what is in that specific filing, then `get_filing_section` with a `section_id` for narrative content.

**Use `list_filings` instead when:** you need ALL filings for ONE company (paginate by year). `list_recent_filings` is the cross-company / event-discovery primitive; `list_filings` is the per-company catalog.

**Not point-in-time.** No `vantage_date` — the watermark walks the live discovery feed as of TODAY. For an as-of view of one company's filings use `list_filings` with `vantage_date`. Endpoint: https://mcp.metricduck.com/mcp

## Resources
Not captured

## Prompts
- whats_changed - Orient on a company: what's changed across recent filings, where it stands now, and evidence for any active concern. Anchored on canonical status/initiation workflows. Leads with the latest-filing signal map before the current-period snapshot. Arguments: ticker
- signal_section_drill - Drill for evidence on a specific topic within a company's filings: signal map → targeted section search → source-anchored summary. Replaces blind section pagination with keyword-targeted chunk retrieval. Handles dead-ends honestly. Arguments: ticker, topic

## Metadata
- Owner: com.metricduck
- Version: 0.4.1
- Runtime: Streamable Http
- Transports: HTTP
- License: Not captured
- Language: Not captured
- Stars: Not captured
- Updated: Mar 18, 2026
- Source: https://registry.modelcontextprotocol.io
