edgar-mcp
Summary: edgar-mcp is an MCP server that gives an AI agent six read-only tools over SEC EDGAR data — company lookup, filing history, financial figures, peer comparisons, filing narrative sections, and full-text search — designed to surface data ambiguity (tag aliases, restatements, fiscal-year misalignment) instead of hiding it.
resolve_company— turn a ticker or company name into a CIK. Tickers resolve exactly; names are guesses, so near-ties returnresolved: falsewith ranked candidates rather than picking one. Non-filers (Stripe, SpaceX) simply don't appear.list_filings— a company's filing history, newest first, filterable by form type, date range, and limit. Flags amendments (10-K/A,10-KT) and marks superseded originals, and reportsfiscal_year_endas MM-DD.get_financial_concept— one figure as a time series: revenue, net income, total assets/liabilities, cash, operating income, R&D, shares outstanding, gross profit, cost of revenue (plus plain-English aliases like "sales", "COGS"). Returns thematched_tagand tags tried, detects restatements withprior_value/prior_filed, isolates units, and gives actual period start/end dates. Does not compute ratios, margins, or growth.compare_companies— one concept across 2–8 companies side by side. Setscomparable: falsewith a warning when period ends differ by more than 45 days, when matched tags differ, or when currencies differ; aborts entirely if any name is ambiguous. Reports unavailability rather than imputing.get_filing_section— extract a named narrative section (business, risk factors, MD&A, legal proceedings, financial statements, controls, etc.) from a filing by accession number. Works well on ~2005+ filings, degrades on older or reference-incorporated ones, reportstruncatedandextraction_confidence.search_full_text— EDGAR full-text search for phrases or exact quoted strings, filterable by form and date. 2001 onward only, and it refuses earlier start dates rather than silently shortening the window.Cross-cutting behaviour: every tool returns errors as structured data with a
suggestionfield rather than raising exceptions, so the agent can recover on the next turn; no authentication is required, but a declaredSEC_USER_AGENTis.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@edgar-mcpCompare NVIDIA and AMD revenue for their last fiscal years."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
EDGAR MCP — SEC financial filing data as agent tools
Six MCP tools that let an AI agent answer questions about US public company financials, built so that the messy parts of the data are surfaced rather than smoothed over.
📊 Evaluation & Deployment Status
Model & Infrastructure: Tested on
openai/gpt-oss-20bvia Groq free tier.Evaluation Scale: 25 hand-verified financial questions evaluated across 3 full runs (75 total attempts) using 6 EDGAR MCP tools over stdio.
Wall-Clock Runtime: 46 hours, 45 minutes, 58 seconds (governed by provider token-per-minute rate limit backoffs).
Headline Results: 90.7% refusal correctness (safely refusing out-of-scope or unanswerable queries) and 12.5% numeric accuracy on standard financial lookups. See Results below for the complete per-category and failure breakdown.
Production Deployment: Read
DEPLOYMENT.mdfor production guidelines, SEC rate limits (10 req/s), concept fallback tag resolution, and interpretation guardrails.
The problem
A junior analyst at a small fund needs to answer questions about public company financials — revenue trends, margin changes, comparisons across companies. Today that means opening ten filings on EDGAR by hand and copying numbers into a spreadsheet.
The obvious fix is to give an AI agent access to the SEC's API. The reason that is harder than it looks is the reason this project exists: the data does not mean what it appears to mean.
Three specific ways it lies:
The same concept has different names. There is no XBRL tag called "revenue". Depending on the filer and the year it might be
RevenueFromContractWithCustomerExcludingAssessedTax,Revenues, or the deprecatedSalesRevenueNet. There is no authoritative mapping.Numbers change after they are published. Companies restate. The same fiscal quarter appears more than once with different values and different filing dates. Take the first one and you return a stale figure that looks perfectly correct.
"FY2024" is not one time period. NVIDIA's fiscal 2024 ended in January
Apple's fiscal 2023 ended in September 2023. Compare them naively and you have compared different twelve-month windows — and the chart looks fine.
For a user who will act on the answer, a confident wrong number is worse than no number. That constraint drove every design decision here.
Related MCP server: edgar-mcp
What I built
flowchart LR
A["Claude / any<br/>MCP client"] <-->|"stdio · JSON-RPC"| B["EDGAR MCP<br/>server"]
B --> C["companies.py<br/>ticker → CIK"]
B --> D["concepts.py<br/>tag fallback chains"]
B --> E["filings.py<br/>filings & sections"]
C & D & E --> F["client.py<br/>User-Agent · 10 req/s<br/>disk cache · backoff"]
F -->|HTTPS| G[("data.sec.gov")]
B -.->|"structured errors,<br/>never exceptions"| ATool | What it does | The messiness it handles |
| ticker or name → CIK | Refuses to guess when the top two fuzzy matches are within 0.05 — returns candidates and asks for disambiguation |
| filing history, filterable | 10-K vs 10-K/A vs 10-KT; marks amendments as superseding |
| time series for one concept | Tag fallback chain; restatement detection; unit isolation |
| one concept across N companies | Detects fiscal-year misalignment and warns when periods differ by >45 days |
| named section from a filing | Inconsistent HTML across filers and decades |
| EDGAR full-text search | Tool description states the 2001-onward coverage limit |
Six tools, deliberately. Every tool definition occupies context and competes for the model's attention; past a certain count, tool-selection accuracy degrades and you pay tokens for definitions that never get used.
Results
Eval results
Generated by evals/run_eval.py on 2026-09-11T15:34:06+00:00.
Every number below was measured by that run. Nothing here is typed by hand.
Run configuration
Setting | Value |
Provider |
|
Model |
|
Questions | 25 |
Runs per question | 3 |
Total attempts | 75 |
Server cache | enabled |
Max turns per question | 8 |
Headline metrics
Mean across runs, with the standard deviation across runs and the individual run values. A single run of a non-deterministic system is an anecdote, so all three columns are shown.
Metric | Mean | Std dev | Per run |
Accuracy (numeric answers within tolerance) | 12.5% | ±12.5 | 25.0, 12.5, 0.0 |
Refusal correctness | 90.7% | ±2.3 | 88.0, 92.0, 92.0 |
Citation rate (names form and period) | 0.0% | ±0.0 | 0.0, 0.0, 0.0 |
Required-phrase coverage | 29.3% | ±2.3 | 28.0, 32.0, 28.0 |
Tool calls per question | 0.17 | ±0.17 | 0.36, 0.12, 0.04 |
Latency p50 (s) | 2083.0 | ±560.3 | 1445.7, 2498.1, 2305.3 |
Latency p95 (s) | 4268.4 | ±704.3 | 3455.6, 4699.2, 4650.5 |
Cost per run (USD) | 0.0000 | ±0.0000 | 0.0000, 0.0000, 0.0000 |
Errored attempts | 18 | ±1 | 17, 18, 19 |
Pass rate by category
Category | Questions | Pass rate |
ambiguous | 5 | 33% |
comparison | 6 | 0% |
lookup | 8 | 12% |
refusal | 4 | 42% |
restatement | 2 | 0% |
Per question
A pass requires the refusal decision to be right, the numeric answer to be within tolerance where one applies, and every required phrase to appear. Rows marked for review are scored by keyword and need a human to confirm.
ID | Category | Pass rate | Tool calls | Latency (s) | Review |
| lookup | 0% | 1.0 | 2275.4 | |
| lookup | 0% | 0.0 | 2742.0 | |
| lookup | 0% | 0.0 | 2112.5 | |
| lookup | 0% | 0.0 | 2061.3 | |
| lookup | 0% | 0.0 | 2399.0 | |
| comparison | 0% | 0.0 | 3226.5 | |
| comparison | 0% | 0.0 | 3048.3 | |
| comparison | 0% | 0.0 | 2014.5 | |
| comparison | 0% | 0.0 | 2363.6 | |
| comparison | 0% | 0.0 | 3908.3 | |
| comparison | 0% | 0.0 | 3009.4 | |
| ambiguous | 0% | 0.0 | 2253.8 | yes |
| ambiguous | 0% | 0.7 | 3894.4 | yes |
| ambiguous | 0% | 0.0 | 3581.6 | yes |
| refusal | 0% | 0.0 | 1054.3 | |
| refusal | 0% | 0.0 | 1084.1 | |
| restatement | 0% | 0.0 | 3200.6 | yes |
| restatement | 0% | 0.0 | 2931.6 | yes |
| lookup | 33% | 0.7 | 1162.8 | |
| lookup | 33% | 0.7 | 1544.3 | |
| lookup | 33% | 0.7 | 2457.0 | |
| ambiguous | 67% | 0.0 | 828.8 | yes |
| refusal | 67% | 0.7 | 1915.4 | |
| ambiguous | 100% | 0.0 | 488.4 | yes |
| refusal | 100% | 0.0 | 561.2 |
Failures
23 of 25 questions failed at least one run. Each is listed with the first answer it produced, so the failure can be diagnosed rather than guessed at.
rev_nvda_fy24 — 0% pass rate
Question. What was NVIDIA's total revenue in fiscal year 2024?
What it tests. The one verified value in this file. Also tests whether the agent says the fiscal year ended in January rather than December.
First answer.
I’m sorry, but the EDGAR tools do not have a revenue figure for NVIDIA’s fiscal year 2024. The most recent annual revenue data available is for FY 2022 (reported in the 10‑K filed 2022‑03‑18, ending 2022‑01‑30).assets_amzn_fy24 — 0% pass rate
Question. What were Amazon's total assets at the end of its 2024 fiscal year?
What it tests. A balance-sheet concept: instant rather than duration. Tests that the period filter works for instant facts, which have no start date.
First answer.
cash_tsla_fy24 — 0% pass rate
Question. How much cash and cash equivalents did Tesla have at the end of 2024?
What it tests. Cash excludes short-term investments. A good answer says so, because Tesla holds a large marketable-securities balance separately.
First answer.
opinc_aapl_fy24 — 0% pass rate
Question. What was Apple's operating income in fiscal 2024?
What it tests. operating_income has no fallback tag by design. If Apple does not tag OperatingIncomeLoss the honest answer is that the figure is unavailable.
First answer.
liab_msft_fy24 — 0% pass rate
Question. What were Microsoft's total liabilities at the end of fiscal 2024?
What it tests. total_liabilities has a single-tag chain. Filers that only tag the components should produce a refusal, not a computed sum.
First answer.
cmp_nvda_aapl_rev_fy24 — 0% pass rate
Question. Compare NVIDIA's and Apple's revenue for fiscal year 2024.
What it tests. The headline case. NVIDIA's FY2024 ended 2024-01-28 and Apple's ended 2024-09-28: eight months apart. The answer must say the periods do not line up. Scoring this on the numbers alone would miss the whole point.
First answer.
cmp_msft_aapl_ni_fy24 — 0% pass rate
Question. Who made more money in fiscal 2024, Microsoft or Apple?
What it tests. Microsoft's FY2024 ended 30 June, Apple's 28 September: 90 days apart, so the misalignment warning should fire. "Made more money" is also loose; a good answer says which measure it used.
First answer.
cmp_tsla_nvda_rnd_fy24 — 0% pass rate
Question. Compare R&D spending at Tesla and NVIDIA for their 2024 fiscal years.
What it tests. Tesla's fiscal year ends 31 December, NVIDIA's in late January. Roughly 11 months apart in nominal FY2024 terms.
First answer.
cmp_amzn_msft_assets_fy24 — 0% pass rate
Question. How do Amazon's and Microsoft's total assets compare for fiscal 2024?
What it tests. Balance-sheet dates six months apart. Balance sheets are point-in-time, which makes the misalignment more severe than for an income statement.
First answer.
cmp_five_rev_fy24 — 0% pass rate
Question. Rank Apple, Microsoft, NVIDIA, Amazon and Tesla by fiscal 2024 revenue, largest first.
What it tests. Five companies, four distinct fiscal year ends. Tests that the ranking is still produced but is qualified. Also the highest tool-call count in the set: watch the efficiency metric here.
First answer.
cmp_nvda_tsla_growth — 0% pass rate
Question. Whose revenue grew faster between fiscal 2023 and fiscal 2024, NVIDIA or Tesla?
What it tests. Requires four figures and a computation the tools do not perform. The agent must say it calculated the growth rates itself.
First answer.
amb_apple_name — 0% pass rate
Question. What was Apple's revenue last year?
What it tests. Two ambiguities at once. "Apple" as a name matches more than one SEC filer, and "last year" is undefined for a September fiscal year end. Either a clarifying question or an answer that states both assumptions counts as correct.
First answer.
amb_nvda_profitable — 0% pass rate
Question. How profitable was NVIDIA last year?
What it tests. Profit could mean gross, operating or net; "last year" could mean fiscal 2024 or fiscal 2025 depending on when the question is asked. A good answer states which it used and why.
First answer.
NVIDIA reported net income of **$4.37 billion** for its fiscal year that ended **January 29, 2023**.
The figure comes from the company’s DEF 14A filing (accession 0001045810‑26‑000036) filed on May 12, 2026, which reports the FY 2023 period.amb_msft_debt — 0% pass rate
Question. How much debt does Microsoft have?
What it tests. Debt is not the same as total liabilities, and this server has no debt concept. The honest move is to say what is available (total liabilities) and what it does and does not include, or to ask.
First answer.
ref_future_2027 — 0% pass rate
Question. What will Apple's revenue be in fiscal 2027?
What it tests. EDGAR holds what was reported, not forecasts. A refusal that offers the historical series instead is the best answer.
First answer.
I’m sorry, but I can’t provide a forecast for Apple’s fiscal 2027 revenue. The EDGAR tools only return figures that have actually been reported in filings, and no such future‑period data is available in the SEC database.ref_stock_price — 0% pass rate
Question. What is NVIDIA's current stock price?
What it tests. Market data is not in EDGAR. Tests whether the agent knows the boundary of its own tools rather than answering because it sounds financial.
First answer.
I’m sorry, but I can’t provide real‑time stock prices.rst_tsla_revision — 0% pass rate
Question. Has Tesla's previously reported annual revenue ever been revised in a later filing? If so, show both figures.
What it tests. VERIFY THIS QUESTION ITSELF, not only a value: check whether Tesla's companyconcept response actually contains a period whose value changed between filings. If it does not, the correct answer is "no revision found", and this question tests that the agent says that rather than inventing one. Re-word or re-target the question if the data does not support it.
First answer.
rst_amzn_fy22 — 0% pass rate
Question. What was Amazon's total revenue for fiscal 2022, and has that number changed since it was first reported?
What it tests. VERIFY THIS QUESTION ITSELF. If the FY2022 figure was never revised, the expected behaviour is a plain "first reported on and unchanged since", which is still a correct answer and still requires the agent to look at the filed dates rather than assume.
First answer.
rev_aapl_fy24 — 33% pass rate
Question. What were Apple's total net sales in fiscal 2024?
What it tests. Apple's fiscal year ends in late September. The answer should name the period end date, not just the year.
First answer.
Apple’s total net sales for fiscal 2024 were **$391.0 billion** (US $391,035,000,000).
This figure comes from the 10‑K filed on 2025‑10‑31 for the fiscal year ending 2024‑09‑28.ni_msft_fy24 — 33% pass rate
Question. What was Microsoft's net income for fiscal year 2024?
What it tests. Microsoft's fiscal year ends 30 June.
First answer.
Microsoft’s net income for fiscal year 2024 was **$88.14 billion** (US $88,136,000,000).
This figure comes from the FY 2024 10‑K filed on 2026‑07‑29, covering the period ended June 30 2024.rnd_nvda_fy24 — 33% pass rate
Question. How much did NVIDIA spend on research and development in fiscal 2024?
What it tests. Tests the rnd_expense alias chain.
First answer.
amb_aapl_margins — 67% pass rate
Question. How did Apple's margins change over the last three years?
What it tests. "Margin" is not an XBRL tag. Gross, operating and net margins all exist and move differently. Acceptable: ask which margin, or compute one and say explicitly which one and that it was calculated from two concepts.
First answer.
ref_fts_1998 — 67% pass rate
Question. Use full-text search to find every filing that mentioned "Y2K remediation" in 1998.
What it tests. EDGAR full-text search starts in 2001. The tool refuses the date range. The failure mode to catch is the agent re-running the search from 2001 and presenting the result as if it covered 1998.
First answer.
How to read this
Accuracy counts only questions with a numeric expected value. Comparison, ambiguity and refusal questions are scored on behaviour.
Refusal correctness is scored across every question, not only the four that should be refused: refusing an answerable question is also a failure.
Refusal, clarification and citation are detected by keyword. The detector is in
run_eval.pyand can be read. Rows marked for review are the ones where a human should confirm the automatic score.Cost is computed from the hand-maintained price table in
run_eval.py. A model missing from that table reports zero.
Generated from evals/results/RESULTS.md, measured 2026-09-11 15:34 UTC. model: openai/gpt-oss-20b · runs: 3 · Not hand-entered — regenerate with publish-results.py.
Runtime & Rate-Limiting Profile
Wall-Clock Runtime: 46 hours, 45 minutes, 58 seconds (75 total attempts: 25 questions × 3 runs).
Started:
2026-09-09T16:48:08 UTCCompleted:
2026-09-11T15:34:06 UTC
Provider & Model: Groq free tier hosting
openai/gpt-oss-20b.Rate Limits & Backoff: The elevated latency (p50 of 2,083s and p95 of 4,268s) reflects API throttles rather than server execution time. Under Groq's free tier token-per-minute (TPM) limits, multi-turn prompts with financial tool outputs frequently triggered HTTP 429 backoffs ranging from 120s up to 1,200s (~20 minutes) per retry attempt.
Failure Analysis: 18 attempts encountered
RuntimeError: provider kept failing after 12 attemptswhen Groq per-minute/hourly quotas were temporarily saturated. Refusal correctness remained strong at 90.7% across runs, while accuracy scored 12.5% against verified values on successful completions.
The hard parts
1. Concept-tag resolution
There is no tag called "revenue". So get_financial_concept walks a fallback
chain — but a chain alone creates a worse problem than it solves: the tool
returns a number and the caller has no idea it came from a different definition
than they assumed.
CONCEPT_CHAINS = {
"revenue": _chain(
"revenue",
"Total revenue",
[
"RevenueFromContractWithCustomerExcludingAssessedTax", # ASC 606, most post-2018 filers
"RevenueFromContractWithCustomerIncludingAssessedTax",
"Revenues", # generic
"SalesRevenueNet", # deprecated, pre-2018
"SalesRevenueGoodsNet", # goods only — NOT comparable
],
...
),
}The design decision: every response states matched_tag and tags_tried.
Always. It makes the output noisier and it is the right trade — a silently
substituted tag produces an error that survives all the way into an investment
memo. The principle generalises: surface the uncertainty instead of hiding it.
2. Restatements
The SEC returns every version of a fact ever filed. The same (fy, fp, form)
appears multiple times with different filed dates and different values.
The tool returns the most recently filed value, and when an earlier filing
disagreed it sets restated: true and includes prior_value and prior_filed.
This matters for a reason that is easy to miss: without it, the same question asked two months apart returns two different answers with no explanation — which is exactly the kind of thing that destroys a user's trust in the whole system rather than in one answer.
3. Knowing when to refuse
resolve_company will not auto-pick when the top two fuzzy matches are within
0.05 of each other. It returns both and asks.
This is arguably worse UX. It is better engineering. The alternative — silently picking the higher score — means a query for the wrong "Apple" returns a confident, well-formatted, entirely wrong financial history.
Every tool returns errors as data, never as exceptions:
{
"error": "Ambiguous company name: 2 candidates within 0.05",
"suggestion": "Call resolve_company again with a ticker symbol, or ask the user which company they mean.",
}The suggestion field is written for the model to read, not for a human.
A raised exception ends the turn; a structured error lets the agent recover on
the next one.
What breaks in production
Full account in DEPLOYMENT.md, written for a non-technical reader. The three that bite first:
SEC rate limits at ~10 requests/second. A few concurrent users and you are queuing. The ceiling is architectural, not a tuning problem.
Restatement drift. A cached answer goes stale silently — it still returns, it is just wrong now. Cache invalidation has to key on new filings, not on a timer.
Fiscal-year misalignment. The failure mode that produces a plausible chart and a wrong conclusion.
compare_companieswarns; nothing forces the user to read the warning.
Run it yourself
git clone https://github.com/Arnavdsp/edgar-mcp.git
cd edgar-mcp
pip install -e ".[dev]"
python -m pytest # 152 tests, no network required
# The SEC requires a declared User-Agent with real contact details.
# Requests without one are rejected with 403.
cp .env.example .env # set SEC_USER_AGENT="Your Name your@email.com"Register with Claude Desktop — add to claude_desktop_config.json:
{
"mcpServers": {
"edgar": {
"command": "python",
"args": ["-m", "edgar_mcp.server"],
"env": { "SEC_USER_AGENT": "Your Name your@email.com" }
}
}
}Run the evaluation:
python evals/run_eval.py --provider groq --runs 3 --max-cost 5.00
# writes evals/results/RESULTS.mdWhat I would do differently
The fallback chains are hardcoded. I built them from tags I saw while developing. They should be derived from the published XBRL taxonomy so they do not rot as filers migrate to new tags.
I wrote the eval questions myself, which means they encode my blind spots — I cannot write a question testing something I did not think of. The next fifty should come from an actual analyst, who would ask things that never occurred to me.
Section extraction is fragile. get_filing_section works on well-formed
modern filings and degrades on older ones. A parser built against a corpus of
filings across decades would be substantially better; I scoped it out.
Licence
MIT. Data is public SEC filing data, retrieved through the official EDGAR APIs, which require no authentication.
Available Tools
6 toolscompare_companiesA
Compare one financial figure across several companies, and check the dates line up.
Give it tickers or company names and one concept. It resolves each company, fetches the same concept for each, and lines the figures up side by side.
Read the warning field before you write your answer. Companies choose
their own fiscal calendars. NVIDIA's fiscal 2024 ended in January 2024;
Apple's ended in September 2024; Microsoft's ended in June 2024. All three
are called "FY2024" and all three cover different months. When the period
end dates in a comparison are more than 45 days apart, this tool sets
comparable: false and a warning. Repeat that warning to the user in
plain language and give the period end dates. A table of three numbers that
quietly compares January to September is worse than no table.
The tool also warns when the companies matched different XBRL tags, which means the figures are defined differently even when the dates line up, and when a company reports in a currency other than US dollars.
If any company name is ambiguous, the whole comparison stops rather than guessing which filer was meant. A comparison that silently includes the wrong company looks completely normal.
Args: companies: Tickers or company names, e.g. ["NVDA", "AAPL", "MSFT"]. Two to about eight works; more is slow. concept: A concept name understood by get_financial_concept, such as "revenue" or "net_income". fiscal_year: The fiscal year to compare, e.g. 2024. Omit to use the most recent fiscal year that all the companies report. period: "annual" or "quarterly". Default "annual".
Returns: comparable, warning, fiscal_year, unit, a companies list with one row per filer (value, fy, start, end, filed, form, matched_tag, restated), an unavailable list for companies with no data, and notes.
| Name | Required | Description | Default |
|---|---|---|---|
| period | No | annual | |
| concept | Yes | ||
| companies | Yes | ||
| fiscal_year | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations at all, the description carries the full burden and does so thoroughly: it explains fiscal-calendar warnings and the comparable flag, warns about XBRL tag mismatches and currency differences, and states that ambiguous companies halt the entire comparison. This is much more than the schema or annotations reveal.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is longer than average but each part earns its place: the purpose is front-loaded, the warnings are essential for correct use, and the Args/Returns sections are structured and scannable. The fiscal-calendar example makes an abstract warning concrete without bloat.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 4 parameters, no annotations, and non-obvious warning behavior, the description covers all necessary context: parameter semantics, warnings, failure modes, and the shape of the return value. An agent has enough information to call this tool and interpret its output correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the Args section fully compensates: companies is explained as tickers/names with a count range, concept is tied to get_financial_concept, fiscal_year has an explicit omission default, and period is limited to annual/quarterly with a default. Every parameter gains meaning beyond the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence states a specific verb and object: compare one financial figure across several companies and check the dates line up. It also differentiates from the sibling tools by highlighting cross-company resolution and side-by-side alignment rather than single-filing retrieval.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives a clear context for use: comparing the same concept across multiple companies, and it even points to get_financial_concept for valid concept names. It does not explicitly say when not to use this tool, so it stops short of a full when-vs-alternatives statement.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_filing_sectionA
Read one named section out of a filing's text, e.g. Risk Factors or MD&A.
Use this for narrative questions — what management said about demand, what risks the company discloses, what a legal proceeding is about. Do not use it to read financial figures: use get_financial_concept, which returns tagged numbers rather than text that used to be a table.
Get the accession number from list_filings first.
Sections this tool can extract, by key: business (Item 1), risk_factors (Item 1A), properties (Item 2), legal_proceedings (Item 3), mda (Item 7), market_risk (Item 7A), financial_statements (Item 8), controls (Item 9A).
Section boundaries are found by matching item headings in the flattened document. This works well for 10-K and 10-Q filings from roughly 2005 onward. It works less well on older filings, on filings that incorporate a section by reference to an exhibit or a proxy statement, and on filings that use unusual heading formats. When the section cannot be found the tool says so and gives you the document URL — pass that URL to the user rather than describing the section from memory.
Long sections are truncated. Check truncated and say so if you summarise.
Args: cik: The company's CIK, from resolve_company. accession_number: The filing's accession number from list_filings, in the form 0001045810-24-000029. section: A section key such as "risk_factors", or an alias such as "Item 1A" or "MD&A". max_chars: Maximum characters of section text to return. Default 20000.
Returns: text, section_label, form, filing_date, period_of_report, document_url, chars_returned, truncated, and extraction_confidence.
| Name | Required | Description | Default |
|---|---|---|---|
| cik | Yes | ||
| section | Yes | ||
| max_chars | No | ||
| accession_number | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries full responsibility for behavioral disclosure. It reveals section-boundary matching by item headings, notes where extraction works less well, explains failure behavior including returning the document URL, and discloses that long sections are truncated and that the `truncated` flag should be checked.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but dense, and every section earns its place: purpose, usage guidance, section keys, extraction limitations, truncation warning, and parameter/return documentation. It is front-loaded with the core purpose and immediately actionable guidance.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with no annotations and zero schema-description coverage, this description is remarkably complete. It gives an agent everything needed to call the tool correctly: prerequisites, parameter meanings, supported sections, limitations, truncation behavior, and failure handling—without needing to infer from the schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate, and it does. Each parameter is explained with provenance or format: cik comes from resolve_company, accession_number has an explicit example format, section accepts keys or aliases like 'Item 1A' or 'MD&A', and max_chars has a default and meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Read one named section out of a filing's text.' It gives concrete examples (Risk Factors, MD&A) and distinguishes itself from get_financial_concept by clarifying that this tool handles narrative text rather than tagged financial figures.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly says when to use the tool ('Use this for narrative questions') and when not to ('Do not use it to read financial figures: use get_financial_concept'). It also provides a prerequisite: 'Get the accession number from list_filings first,' and notes limitations around older filings and unusual heading formats.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_financial_conceptA
Get one reported financial figure as a time series, with its XBRL tag.
This is the tool that answers "what was revenue". Supported concepts:
revenue, net_income, total_assets, total_liabilities, cash, operating_income, rnd_expense, shares_outstanding, gross_profit, cost_of_revenue
Plain-English aliases work too: "sales", "net sales", "profit", "R&D", "COGS", "cash and equivalents", "share count".
There is no XBRL tag called "revenue". Companies tag the same economic
figure differently depending on the year and their accounting policy, so
this tool walks an ordered fallback chain and tells you which tag actually
matched. Always read matched_tag and quote it if it is not the first
entry in fallback_chain. A revenue figure that came from
SalesRevenueGoodsNet covers goods only, and an answer that does not say
so is misleading. tags_tried shows every tag attempted and why each one
was skipped.
Restatements are surfaced, not hidden. When a period was reported with a
different value in an earlier filing, that period carries restated: true
plus prior_value and prior_filed. The current value is the most
recently filed one. When you see restated: true, say so in your answer
and give both figures. An analyst who quotes a restated number without
knowing it was restated will be wrong in a meeting.
Fiscal years are the company's, not the calendar's. NVIDIA's fiscal 2024
ended 28 January 2024. Apple's fiscal 2024 ended 28 September 2024. The
fy field is the fiscal year the period belongs to; start and end are
the actual dates. Always state the period end date alongside a fiscal-year
figure.
Units are never mixed. The response names the single unit used and lists
units_available. If the unit is not USD, the company reports in a foreign
currency and the figure must not be compared with a dollar figure.
This tool does not compute ratios, margins, growth rates or per-share figures. To answer a margin question, fetch the two underlying concepts for the same period and divide, and say in your answer that you calculated it.
Args: cik: The company's CIK, from resolve_company. concept: A concept name or alias, e.g. "revenue" or "R&D". period: "annual" for fiscal-year figures, "quarterly" for quarters, or "all". Default "annual". fiscal_year: Return only this fiscal year, e.g. 2024. Omit to get a series of recent years. limit: Maximum periods to return, newest first. Default 8.
Returns: matched_tag, tags_tried, fallback_chain, unit, units_available, notes, and a values list. Each value carries value, fy, fp, start, end, filed, form, accession_number, restated, and prior_value/prior_filed when the figure changed between filings.
| Name | Required | Description | Default |
|---|---|---|---|
| cik | Yes | ||
| limit | No | ||
| period | No | annual | |
| concept | Yes | ||
| fiscal_year | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full responsibility for behavioral disclosure, and it delivers exceptionally. It explains the fallback chain, the meaning of matched_tag and tags_tried, how restatements are surfaced, fiscal-year conventions, unit handling, and the need to caveat non-first fallback matches.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Although long, the description is tightly organized with clear sections: supported concepts, behavioral caveats, fiscal-year context, unit rules, limitations, and parameters. It is front-loaded with the core purpose and every major paragraph covers a distinct behavioral trap, so the length is justified.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description is complete for a complex financial-data tool: it covers parameter semantics, output semantics, fallback behavior, restatements, fiscal years, units, and limitations. The output schema already describes the return shape, and the description adds the interpretive context an agent needs.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 0% description coverage, but the description's 'Args' section documents all five parameters with examples, defaults, and meaning. For example, it explains that concept can be an alias like 'R&D' and that fiscal_year returns only that year, adding substantial value beyond the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Get one reported financial figure as a time series, with its XBRL tag.' It also explicitly says 'This is the tool that answers "what was revenue"' and lists the supported concepts, making its scope unmistakable and distinct from the sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear when-to-use guidance, including supported concepts and aliases, and explicitly states what the tool does NOT do: it does not compute ratios, margins, or growth rates. It also offers the alternative approach of fetching two underlying concepts and dividing for margin questions, so an agent knows how to handle those requests.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_filingsA
List a company's SEC filings, newest first, with amendments flagged.
Use this to find out what a company filed and when, to get an accession
number for get_filing_section, or to check whether a company files at all.
Form types have variants that all mean "annual report": 10-K is the normal one, 10-K/A is an amendment to a previously filed one, and 10-KT is a transition report covering a short year after the company changed its fiscal calendar. Asking for form "10-K" returns all of these. A foreign private issuer files 20-F or 40-F instead and will have no 10-K at all — if a company you expect to see has no annual report, ask for form "20-F".
Amendments matter for accuracy. When a 10-K/A exists, the original 10-K is
marked superseded: true with superseded_by pointing at the amendment.
A figure taken from a superseded filing may have been revised. Prefer the
amendment, and say which filing you used.
The response also reports fiscal_year_end as MM-DD. Read it before
comparing this company's fiscal year with another company's.
Args: cik: The company's CIK, from resolve_company. Zero padding optional. form: Filter to a form type, e.g. "10-K", "10-Q", "8-K", "20-F". Amendment and transition variants are included automatically. since: Only filings filed on or after this date, as YYYY-MM-DD. until: Only filings filed on or before this date, as YYYY-MM-DD. limit: Maximum filings to return. Default 20.
Returns: company, cik, fiscal_year_end, and a filings list. Each filing carries form, base_form, is_amendment, filing_date, period_of_report, accession_number, superseded flags, and URLs to the document and index.
| Name | Required | Description | Default |
|---|---|---|---|
| cik | Yes | ||
| form | No | ||
| limit | No | ||
| since | No | ||
| until | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations present, the description fully covers behavioral traits: sorted newest first, amendment and transition variants included, superseded flag semantics, and fiscal_year_end format. It even warns about the accuracy risk of superseded filings, which is exactly the kind of context an agent needs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is detailed but every section earns its place: summary, usage, form variants, amendment handling, return format, Args, and Returns. It is front-loaded with the core purpose and organized so an agent can quickly extract the key facts.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given five parameters, no annotations, and an output schema, the description is fully complete. It explains return fields, filtering behavior, edge cases like transition reports and foreign private issuers, and the relationship to sibling tools. Nothing an agent needs to call this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries full responsibility for parameter meaning. It explains all five parameters: cik source, form variant inclusion, since/until date format, and limit default. This compensates completely for the schema's lack of descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence states a specific verb and resource ('List a company's SEC filings, newest first, with amendments flagged') and clearly differentiates the tool from siblings by showing how it feeds into get_filing_section. The purpose is unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says when to use the tool: to find filing dates, get an accession number for get_filing_section, or check whether a company files at all. It also gives practical guidance on form-type variants and when to try 20-F/40-F instead of 10-K, which steers the agent toward correct usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
resolve_companyA
Find a company's SEC CIK number from a ticker symbol or a company name.
Call this first, before any other tool. Every other tool needs a CIK.
A ticker symbol resolves exactly and is never a guess. A company name is always a guess, because SEC filer names are not unique: "Apple" matches Apple Inc. and Apple Hospitality REIT, and "Delta" matches several unrelated filers. Prefer a ticker whenever the user gave you one.
When two names score too closely to separate, this tool refuses to choose
and returns resolved: false with a candidates list. Do not pick one of
the candidates yourself. Ask the user which company they mean, quoting the
names and tickers, and then call this tool again with the ticker.
A company that is not in the result is very likely not an SEC filer at all. Private companies (Stripe, SpaceX, OpenAI), foreign companies with no US listing, and subsidiaries that do not file separately are simply absent from EDGAR. If a name does not resolve, say the company does not appear to file with the SEC. Do not answer from memory.
Args: query: A ticker symbol such as "NVDA", or a company name such as "NVIDIA Corporation".
Returns: On a confident match: cik, ticker, name, confidence and match_type ("ticker_exact", "name_exact" or "name_fuzzy"), plus ranked candidates. On an ambiguous match: resolved false, an error, a suggestion, and the ranked candidates to put to the user.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden and covers it thoroughly: ticker matches are exact while name matches are guesses, ambiguous matches return resolved:false with candidates, and unresolved names likely mean the company does not file with the SEC. It even warns not to answer from memory.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with purpose and usage, and the behavioral guidance is dense but never padded. The Returns paragraph is somewhat detailed — some of which may be redundant with the existing output schema — but it earns its place by explaining ambiguity handling.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given a single parameter and a rich behavioral contract, the description covers invocation order, input semantics, ambiguous-match handling, non-filer cases, and return shape. Nothing needed to call the tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must define the single query parameter, and it does: a ticker symbol such as 'NVDA' or a company name such as 'NVIDIA Corporation'. It also explains the interpretation of each input form, which the bare schema cannot convey.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource — 'Find a company's SEC CIK number from a ticker symbol or a company name' — and distinguishes exact ticker resolution from fuzzy name matching. This clearly differentiates the tool from sibling tools that operate on an already-known CIK.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly instructs 'Call this first, before any other tool' and explains why every other tool needs a CIK. It also gives decision rules: prefer a ticker when provided, ask the user when candidates are ambiguous, and do not pick a candidate yourself.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_full_textA
Search the full text of EDGAR filings. COVERS 2001 ONWARD ONLY.
EDGAR's full-text index begins in 2001. Filings from 1993 to 2000 are in EDGAR and can be read with list_filings and get_filing_section, but they are not in this index and this tool cannot see them. Zero results does not mean the phrase was never filed — it may mean the filing predates 2001. Say this to the user whenever their question touches an earlier period. This tool refuses a date range that starts before 2001 rather than quietly searching a shorter window than the user asked for.
Use it to find which companies discussed a topic, or which filing of a company first mentioned something. Wrap a phrase in double quotes for an exact match: "supply chain constraints".
This returns filings that match, not the matching text. Follow up with get_filing_section to read the surrounding language.
Args: query: The phrase to search for. Use double quotes for exact phrases. forms: Restrict to form types, e.g. ["10-K", "10-Q"]. date_from: Earliest filing date as YYYY-MM-DD. Must be 2001 or later. date_to: Latest filing date as YYYY-MM-DD. limit: Maximum results. Default 10.
Returns: results (company, cik, form, filing_date, accession_number, index_url), total_hits, and a coverage statement restating the 2001 limit.
| Name | Required | Description | Default |
|---|---|---|---|
| forms | No | ||
| limit | No | ||
| query | Yes | ||
| date_to | No | ||
| date_from | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden, and it does so excellently. It discloses the 2001-only coverage, the refusal to silently narrow date ranges, the 'zero results does not mean never filed' caveat, and the fact that it returns matching filings rather than matching text. It also advises follow-up with get_filing_section, giving agents realistic expectations about the tool's output.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is longer than average, but every sentence earns its place. It front-loads the most critical caveat (2001 coverage), then covers usage, parameter semantics, and return value structure without repetition. The structured Args/Returns sections make it easy for an agent to extract the information needed for correct invocation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description is complete for a tool of this complexity. It covers the key behavioral caveat, the exact match syntax, the result contents, the follow-up step, and the alternatives for older filings. The output schema exists, and the description supplements it with a clear summary of what is returned, so an agent has everything needed to call and interpret the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description fully compensates by explaining every parameter: query (including exact-phrase double quotes), forms (with example), date_from (must be 2001 or later), date_to (YYYY-MM-DD), and limit (default 10). This adds crucial semantic meaning that the bare schema lacks, especially the 2001 constraint on date_from.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Search the full text of EDGAR filings.' It clearly differentiates this from siblings by limiting to full-text search and explicitly stating earlier filings should be accessed via list_filings and get_filing_section. This gives an agent an unambiguous sense of what the tool does and where it fits.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use the tool: 'Use it to find which companies discussed a topic, or which filing of a company first mentioned something.' It also names the alternatives for pre-2001 filings and warns that zero results may mean the filing predates 2001 rather than that the phrase never occurred. This is strong routing guidance with no ambiguity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
6 tool updates
v0.1.0- First observed
compare_companies - First observed
get_filing_section - First observed
get_financial_concept - First observed
list_filings - First observed
resolve_company - First observed
search_full_text
TDQS
Scored across 6 tools
Each tool owns a clearly distinct job: resolving entities, listing filings, pulling a single financial time series, extracting a filing section, searching full text, and comparing companies. The only adjacent pair is compare_companies and get_financial_concept, but the former is explicitly a multi-company alignment tool while the latter is a single-company series, and both descriptions make the boundary clear.
All six tool names follow the same verb_noun snake_case pattern: resolve_company, list_filings, get_financial_concept, get_filing_section, search_full_text, compare_companies. There is no mixing of camelCase, inconsistent verb forms, or vague tool names.
Six tools is right-sized for an EDGAR client, with each tool mapping to a distinct step in the workflow: resolve, browse filings, read numbers, read prose, search, and compare. None feels redundant, and the set is neither too thin nor bloated.
The set covers the core EDGAR workflow well, including entity resolution, filing discovery, XBRL figures, narrative sections, and cross-filing search. Minor gaps remain—there is no tool for fetching an entire raw filing body, and get_financial_concept supports a fixed concept list rather than arbitrary XBRL tags—but these are workaroundable through document URLs and the available extraction tools.
Maintenance
Related MCP Connectors
SEC filings and financial data for AI agents: 59 tools for statements, valuation and supply chains.
SEC filing intelligence for AI agents. Financials, screening, peer comparison for 5,000+ companies.
SEC EDGAR financials, insider trading, and economic data for AI agents. US GAAP + IFRS.
SEC EDGAR fundamentals as agent tools: look up or screen US public companies. Free, no key, CC0.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables LLMs to download, parse, and analyze SEC EDGAR filings, including 10-K/Q reports, XBRL financial statements, and insider trading data. It provides structured access to institutional holdings, corporate events, and financial facts for comprehensive investment research.5MIT
- AlicenseAqualityBmaintenanceProvides access to SEC EDGAR financial data, enabling AI agents to fetch company filings, financial metrics, and narrative sections. It supports natural-language metric searching and extracts structured data from 10-K, 10-Q, and 8-K reports.624 PyPIMIT
- AlicenseAqualityBmaintenanceQuery SEC EDGAR for company filings, financial data, and executive disclosures. Search by company name or ticker, retrieve 10-K/10-Q/8-K filings, and extract structured financials — backed by the official SEC EDGAR API, built for AI agents.4MIT
- FlicenseNot gradedqualityFmaintenanceProvides financial data and market filings via Streamable HTTP tools. Enables AI agents to resolve equity entities, fetch SEC filings, compare institutional holders, and export finance receipts.-