fairquery-edgar
Fairquery EDGAR is a read-only MCP server that turns public SEC EDGAR data into structured, paged results — five free direct-to-sec.gov tools plus one paid Apify batch export.
Resolve companies (
edgar_resolve_company): ticker, CIK, or name fragment → official SEC CIK, ticker, registrant name (free)List filings (
edgar_list_filings): one company's 10-K/10-Q/8-K/etc., filter by form type and date range, with accession numbers and document/index URLs (free)Read filing text (
edgar_get_filing_document): fetch a primary or named filing document as plain text (or raw HTML), paged by character offset (free)Get XBRL facts (
edgar_get_company_facts): list concepts a company reports, or pull time-series values (Assets, Revenues, NetIncomeLoss, EPS…) filtered by form, fiscal period, or date (free)Compare across companies (
edgar_get_concept_across_companies): one concept for one period across all filers via the SEC frames API, sortable (free)Batch export (
edgar_batch_export): up to 50 companies of filings + facts + optional text excerpts via the Apify Actor; pay-per-event, requiresAPIFY_TOKENFree tools need no token, are throttled to ≤5 req/s, return paged
{count,total,offset,hasMore,nextOffset,meta,items}and machine-readable errors (e.g.COMPANY_NOT_FOUND,SEC_FETCH_FAILED)Not for realtime quotes, options chains, non-US registries, or investment advice
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., "@fairquery-edgarFind Nvidia's CIK and its last five 8-K filings"
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.
Fairquery EDGAR: SEC Company Filings & Financial Facts
Apify Store · MCP via Apify · Contact: fairquery@proton.me
Public Apify Actor that turns the SEC’s public EDGAR data into clean, structured rows for AI agents and MCP clients. Look up by ticker, CIK, or company name. Returns official entity metadata, recent filings (10-K, 10-Q, 8-K and more) with document URLs, XBRL company facts (Assets, Revenues, NetIncomeLoss, diluted EPS and more), and optional plain-text excerpts. Every row carries a schema version, a source SEC URL, and a timestamp. Errors are machine-readable codes.
Not investment advice. Output is a structured mirror of public SEC EDGAR data for research and tooling. It is not a recommendation to buy, sell, or hold any security.
When to use this (LLM / tool selection)
Use this Actor when an agent needs:
Map a ticker, CIK, or company name → official SEC CIK / entity metadata
Recent SEC filings (10-K, 10-Q, 8-K, …) with document URLs
XBRL company facts (Assets, NetIncomeLoss, EPS, …) from
companyfactsOptional plain-text excerpts from primary filing documents
Do not use it for realtime quotes, options chains, insider Form 4 parsing beyond what submissions expose, or non-US registries.
Related MCP server: Aegis Gov SEC Filings MCP
MCP connection (Apify hosted)
Connect any MCP client to Apify’s MCP server with this Actor scoped in:
{
"mcpServers": {
"fairquery-edgar": {
"type": "http",
"url": "https://mcp.apify.com/?tools=fetch-actor-details,fairquery/edgar-company-facts-filings"
}
}
}Clients without OAuth can add "headers": {"Authorization": "Bearer <APIFY_TOKEN>"}.
MCP URL: https://mcp.apify.com/?tools=fetch-actor-details,fairquery/edgar-company-facts-filings
Actor id: fairquery/edgar-company-facts-filings (lowercase).
Example agent prompts
"Using the EDGAR tool, get Apple's and Microsoft's 10-K and 10-Q filings since 2023 and their latest Assets, NetIncomeLoss and diluted EPS."
"Find the CIK for Nvidia and list its last five 8-K filings with links."
Local stdio MCP server
This repo also ships a stdio MCP server (TypeScript, @modelcontextprotocol/sdk) under mcp/ with single-purpose tools. Five are free and call sec.gov directly (no token, brand User-Agent Fairquery, throttled to ≤5 req/s); one optional bulk tool runs the Apify Actor. initialize and tools/list work without a token.
Tool | What it does | Paging | Cost |
| Ticker / CIK / name fragment → SEC CIK, ticker, registrant name | – | free |
| One company's filings, filter by |
| free |
| Primary (or named) filing document from sec.gov Archives as plain text, by URL or accession number |
| free |
| XBRL facts: list available concepts (with |
| free |
| One concept for one period across all filers (SEC frames API), sortable, optional company filter |
| free |
| Multi-company export of filings + facts + excerpts via the Apify Actor | – | pay-per-event, needs |
Paged tools return {count, total, offset, hasMore, nextOffset, meta, items}. Errors are returned as {error, message, retryable} with codes such as COMPANY_NOT_FOUND, FILING_NOT_FOUND, NOT_FOUND, INVALID_URL, SEC_FETCH_FAILED.
Live test of all free tools: cd mcp && npm run build && node scripts/live-test.mjs.
Install & run (Node)
cd mcp
npm install
npm run build
node dist/index.js # free tools
APIFY_TOKEN=your_token node dist/index.js # also enables edgar_batch_exportMCP client config (Cursor / Claude Desktop)
{
"mcpServers": {
"fairquery-edgar": {
"command": "node",
"args": ["/absolute/path/to/edgar-company-facts-filings/mcp/dist/index.js"],
"env": {
"APIFY_TOKEN": "your_apify_token"
}
}
}
}Docker
Build from mcp/:
cd mcp
docker build -t fairquery-edgar-mcp .
docker run -i -e APIFY_TOKEN=your_token fairquery-edgar-mcpThe repo-root Dockerfile builds this stdio MCP server (build context = repository root) and is what Glama uses. The Apify Actor image is built from .actor/Dockerfile.
Glama
glama.json lists fairquery as maintainer. After Glama indexes the server, claim ownership if needed.
Data sources (SEC fair access)
Resource | URL |
Tickers map |
|
Submissions |
|
Company facts |
|
The Actor sends User-Agent: Fairquery fairquery@proton.me and throttles to ≤ 5 requests/second.
Input
Field | Type | Default | Description |
|
| — | Tickers ( |
|
|
| Which row types to emit (always emits |
|
|
| Form filter; empty = all |
|
| — | Keep filings with |
|
|
| Cap filing rows per company |
|
| defaults | XBRL concept names; empty uses a curated us-gaap set |
|
|
| Most-recent values per concept/unit |
|
|
| Fetch primary document text |
|
|
| Excerpt length cap |
Example input
{
"companies": ["AAPL", "MSFT"],
"mode": "both",
"formTypes": ["10-K", "10-Q"],
"since": "2023-01-01",
"maxFilingsPerCompany": 5,
"metrics": ["Assets", "NetIncomeLoss", "EarningsPerShareDiluted"],
"includeTextExcerpt": false
}Minimal:
{"companies":["AAPL"],"mode":"both","formTypes":["10-K"],"metrics":["Assets","NetIncomeLoss"]}Output
One dataset row per company, filing, fact, text excerpt, or error. Every row includes:
schema_version— currently1.0.0type—company|filing|fact|text_excerpt|errorsource_url— SEC URL the row came fromscraped_at— ISO timestamp
Error rows (machine-readable)
{
"schema_version": "1.0.0",
"type": "error",
"code": "COMPANY_NOT_FOUND",
"message": "Could not resolve company query: ZZNOTREAL",
"retryable": false,
"query": "ZZNOTREAL",
"source_url": "https://data.sec.gov/"
}Codes include: INPUT_EMPTY, COMPANY_NOT_FOUND, RESOLVE_FAILED, SUBMISSIONS_FETCH_FAILED, FACTS_FETCH_FAILED, EXCERPT_FETCH_FAILED.
Run summary
Key-value store record RUN_SUMMARY with counts, SEC request total, and echoed input.
Pricing (pay-per-event)
No subscription. Users are charged for these events (plus Apify’s default apify-actor-start):
Event | Price | When |
| $0.00005 | Once when the run starts (Apify default) |
| $0.002 | Each successfully resolved company row |
| $0.002 | Each filing row |
| $0.0005 | Each XBRL fact row |
| $0.003 | Each primary-document text excerpt row |
Primary Store display event: company-resolved.
Memory / runtime
Default 256 MB, timeout 300s. HTTP-only (no browser).
Local development
npm install
# put input in storage/key_value_stores/default/INPUT.json
npx apify run
npm testOptional local PPE dry-run: ACTOR_TEST_PAY_PER_EVENT=1 npx apify run.
Links
Apify Store: https://apify.com/fairquery/edgar-company-facts-filings
MCP: https://mcp.apify.com/?tools=fetch-actor-details,fairquery/edgar-company-facts-filings
Contact: fairquery@proton.me
License
MIT
Kits & templates
Optional guides from Fairquery for wiring this Actor into agents and automations (the Actor works fine without them):
AI Agent Data Toolkit Quick-Start (PDF): MCP setup for Claude Desktop and Cursor, API calls, recipes, cost estimates.
n8n + Zapier Workflow Template Pack: 10 importable n8n workflows for the four Fairquery Actors, plus Zapier setup guides.
Agent Prompt Pack for Research & Lead Ops: 69 prompts for company research, lead cleaning, SEO and security reviews.
Agent Starter Kit: 10 copy-paste MCP + n8n recipes ($5): 10 copy-paste MCP + n8n recipes, with ready-made Claude/Cursor configs and 3 starter workflows.
Disclaimer
Data originates from the U.S. Securities and Exchange Commission EDGAR system. Fairquery and this Actor provide no warranty of completeness or fitness for trading decisions. This is not investment advice.
Available Tools
6 toolsedgar_batch_exportBatch export filings & facts via Apify Actor (paid)ARead-onlyIdempotentInspect
Bulk export (paid, via Apify) of structured SEC EDGAR data for up to 50 US companies in one call: entity metadata, recent filings (10-K, 10-Q, 8-K, S-1, DEF 14A, ...) with document URLs, XBRL financial facts (Assets, Revenues, NetIncomeLoss, EarningsPerShareDiluted, ...) and optional plain-text excerpts of primary filing documents.
WHEN TO USE: an agent needs filing lists/links or reported financial values from official SEC data. mode="filings" for filing history/links, "facts" for financial numbers, "both" for both. Prefer the free single-purpose tools (edgar_resolve_company, edgar_list_filings, edgar_get_company_facts, edgar_get_filing_document) for interactive lookups; use this tool for multi-company batch exports billed to your Apify account. Not for real-time quotes, prices, options, non-US companies or investment advice.
BEHAVIOR: read-only; runs the Fairquery Apify Actor fairquery/edgar-company-facts-filings via the Apify API, which queries sec.gov (throttled to <=5 req/s). Requires the APIFY_TOKEN environment variable. Typical run 5-60 s; the call waits up to 5 minutes.
COST: paid (billed to your Apify account, pay-per-event): $0.00005 per run, $0.002 per resolved company, $0.002 per filing row, $0.0005 per fact row, $0.003 per text excerpt. Keep maxFilingsPerCompany, metrics and maxFactsPerMetric small to limit cost; e.g. 1 company, 5 filings, 3 metrics x 4 values ~ $0.018.
RETURNS: {count, items}. Every row has schema_version, type (company | filing | fact | text_excerpt | error), source_url and scraped_at. filing rows: cik, ticker, form, filing_date, report_date, accession_number, primary_document, document_url. fact rows: taxonomy, concept, label, unit, value, start, end, filed, form. error rows: code (INPUT_EMPTY, COMPANY_NOT_FOUND, RESOLVE_FAILED, SUBMISSIONS_FETCH_FAILED, FACTS_FETCH_FAILED, EXCERPT_FETCH_FAILED), message, retryable. Unresolvable companies produce an error row, not a failure.
WHEN NOT TO USE: single-company or interactive lookups - use the free tools above (same SEC data, no cost).
EXAMPLE: {"companies":["AAPL","MSFT"],"mode":"facts","metrics":["Revenues"],"maxFactsPerMetric":4} -> company + fact rows ($0.02).
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | "filings" = filing list only, "facts" = XBRL facts only, "both" (default). A company row is always included when resolved. | both |
| since | No | Only filings with filingDate >= this date (YYYY-MM-DD), e.g. "2023-01-01". | |
| metrics | No | XBRL us-gaap/dei concept names (case-sensitive), e.g. ["Assets","Revenues","NetIncomeLoss","EarningsPerShareDiluted"]. Omit for a curated default set (~10 concepts). | |
| companies | Yes | Tickers ("AAPL"), CIKs ("320193") or company name fragments ("Apple"). Example: ["AAPL","MSFT"] | |
| formTypes | No | Filter filings by form type, e.g. ["10-K","10-Q"] or ["8-K"]. Omit/empty = all forms. Ignored when mode="facts". | |
| excerptMaxChars | No | Max characters per excerpt (default 2000). Only used with includeTextExcerpt=true. | |
| maxFactsPerMetric | No | Most-recent values kept per concept and unit (default 8). Each fact row is billed. | |
| includeTextExcerpt | No | Also fetch a plain-text excerpt of each filing's primary document (default false; $0.003 each, slower). | |
| maxFilingsPerCompany | No | Max filing rows per company, newest first (default 10). Each row is billed. |
Output Schema
| Name | Required | Description |
|---|---|---|
| count | Yes | Number of rows returned |
| items | Yes | Result rows; each has a "type" field (data rows or machine-readable "error" rows) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover the safety profile (readOnly, idempotent, openWorld), and the description adds substantial context beyond them: the paid per-event cost model with concrete price points, the required APIFY_TOKEN, sec.gov rate-limiting at <=5 req/s, expected run duration (5-60 s, up to ~5 min wait), and that unresolvable companies yield error rows rather than failures. This is exactly the extra behavior an agent needs before committing to a paid call.
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?
Well front-loaded and organized under labeled sections, with every cost/timing sentence earning its place given the paid remote execution. Slight redundancy in the RETURNS section, which restates return-shape detail already carried by the output schema, prevents a 5.
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 9-parameter, paid, remote-actor tool with an output schema, the description covers cost, auth, timing, throttling, error semantics, and sibling routing, which is everything an agent needs to invoke it correctly. The return-value recap is redundant with the output schema but does not leave gaps.
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 100%, so the baseline is 3, but the description adds value beyond the schema by tying cost to the sizing parameters ('Keep maxFilingsPerCompany, metrics and maxFactsPerMetric small to limit cost') and giving a worked example call with metrics. It stops short of adding per-parameter syntax detail, so 4 rather than 5.
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?
States a specific verb and resource ('Bulk export ... of structured SEC EDGAR data') plus scope ('up to 50 US companies in one call') and enumerates exactly what is returned (entity metadata, filings, XBRL facts, text excerpts). It explicitly distinguishes itself from the free single-purpose siblings, so an agent can route correctly without opening the schema.
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?
Provides an explicit WHEN TO USE section with mode-selection guidance ('filings' vs 'facts' vs 'both'), names the free alternative tools for interactive lookups, and adds a WHEN NOT TO USE section excluding real-time quotes, prices, options, non-US companies and investment advice. Nothing about selection is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
edgar_get_company_factsGet XBRL financial facts for a companyARead-onlyIdempotentInspect
Get reported XBRL financial data (us-gaap, ifrs-full, dei, ...) for one company from the SEC companyfacts API, e.g. Assets, Revenues, NetIncomeLoss, EarningsPerShareDiluted. Two modes: (1) omit concepts to LIST the concepts the company reports (name, label, units, number of values) so you can pick exact names; (2) pass concepts to get their time-series values, newest first, optionally filtered by form (10-K/10-Q), fiscal period or date. Use edgar_get_concept_across_companies to compare one concept across many companies. Behavior: free, read-only GET to data.sec.gov (no token). Concept names are case-sensitive. Values are as reported (duplicates across filings possible; set dedupe=true to keep one value per period). RETURNS: paged {count,total,offset,hasMore,nextOffset,meta:{cik,name},items}. List mode items: {taxonomy,concept,label,units,values}. Values mode items: {taxonomy,concept,label,unit,value,start,end,fy,fp,form,filed,accession_number,frame}. Errors: COMPANY_NOT_FOUND, NOT_FOUND (no XBRL data), SEC_FETCH_FAILED. WHEN NOT TO USE: for filing documents/text use edgar_list_filings + edgar_get_filing_document; for one concept across all companies use edgar_get_concept_across_companies. COST: free - direct sec.gov requests from this MCP server, no APIFY_TOKEN, no Apify billing. EXAMPLE: {"company":"MSFT","concepts":["Revenues"],"fiscalPeriod":"FY","limit":5} -> 5 newest annual Revenues values in USD.
| Name | Required | Description | Default |
|---|---|---|---|
| forms | No | Values mode only: keep values reported in these form types (case-insensitive), e.g. ["10-K"] for annual or ["10-Q"] for quarterly. Omit for all forms. | |
| limit | No | Optional page size: items to return, integer 1-500 (default 50) | |
| since | No | Values mode: keep values whose period end >= YYYY-MM-DD | |
| dedupe | No | Values mode: keep one value per concept/unit/period (latest filed). Default true. | |
| offset | No | Number of items to skip for paging (default 0); use nextOffset from the previous response | |
| search | No | List mode only: case-insensitive substring filter on concept name or label, e.g. "revenue" | |
| company | Yes | Ticker ("AAPL"), CIK ("320193", zero-padding optional) or company name fragment ("Apple"); best match is used. Call edgar_resolve_company first if the name is ambiguous. | |
| concepts | No | Exact concept names, e.g. ["Revenues","NetIncomeLoss"]. Omit to list available concepts. | |
| taxonomy | No | Restrict to a taxonomy: "us-gaap", "ifrs-full", "dei", "srt". Omit for all. | |
| fiscalPeriod | No | Values mode: keep only this fiscal period |
Output Schema
| Name | Required | Description |
|---|---|---|
| meta | No | Tool-specific context (company, source_url, ...) |
| count | Yes | Number of items in this page |
| items | Yes | Result rows for this page |
| total | Yes | Total items matching the filters (before paging) |
| offset | Yes | Offset of the first item in this page |
| hasMore | Yes | True if more items exist after this page |
| nextOffset | Yes | Offset to pass for the next page, or null |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds substantial context beyond the annotations: free/read-only GET to data.sec.gov with no token or Apify billing, case-sensitive concept names, and the important gotcha that values are as-reported with duplicates across filings unless dedupe=true. This is exactly the operational detail annotations cannot convey.
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?
Front-loaded with the core action and modes, then sectioned with RETURNS, WHEN NOT TO USE, COST and EXAMPLE labels that make scanning easy. Slightly verbose: 'free' is stated twice (opening line and COST section), and the RETURNS detail overlaps the output schema, but the density is largely justified for a 10-parameter tool.
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 10-param tool, it covers modes, default behavior, error codes (COMPANY_NOT_FOUND, NOT_FOUND, SEC_FETCH_FAILED), and points to edgar_resolve_company for ambiguous names. Output schema exists, so return detail is bonus rather than a gap.
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 100%, so the baseline is 3. The description still adds value by framing the concepts parameter as the mode selector (omit to list, pass to retrieve) and providing a concrete example payload with limit and fiscalPeriod, clarifying how parameters combine.
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?
States a specific verb+resource (get reported XBRL financial data for one company) plus named source (SEC companyfacts API) and examples of concepts returned. It explicitly distinguishes itself from edgar_get_concept_across_companies, which is the closest sibling.
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?
Gives explicit when-to-use via the two-mode breakdown (omit concepts to list, pass concepts for time-series), a WHEN NOT TO USE section routing to edgar_list_filings/edgar_get_filing_document for documents and to edgar_get_concept_across_companies for cross-company comparison. Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
edgar_get_concept_across_companiesCompare one XBRL concept across all companiesARead-onlyIdempotentInspect
Cross-company query: get one XBRL concept (e.g. Revenues, Assets, NetIncomeLoss) for one calendar period for every SEC filer that reported it, using the SEC frames API. Sortable and paged. Use for screening and peer comparison ("largest companies by total assets at end of 2023", "net income of all filers in CY2023"). For one company's history use edgar_get_company_facts. Period format: "CY2023" (annual duration), "CY2023Q2" (quarterly duration), "CY2023Q4I" (instant, for balance-sheet items like Assets). Unit e.g. "USD", "USD-per-shares", "shares", "pure". Behavior: free, read-only GET to data.sec.gov (no token). Returns paged {count,total,offset,hasMore,nextOffset,meta:{taxonomy,concept,label,unit,period,source_url},items:[{rank,cik,entity_name,value,start,end,location,accession_number}]}. Optional ciks filter restricts to given companies. Errors: NOT_FOUND (no such concept/unit/period frame), SEC_FETCH_FAILED. WHEN NOT TO USE: for one company's time series use edgar_get_company_facts; for filings use edgar_list_filings. COST: free - direct sec.gov requests from this MCP server, no APIFY_TOKEN, no Apify billing. EXAMPLE: {"concept":"Assets","period":"CY2023Q4I","limit":10} -> top 10 filers by total assets at end of 2023.
| Name | Required | Description | Default |
|---|---|---|---|
| sort | No | Sort order (default value_desc) | value_desc |
| unit | No | Unit of measure (default "USD"; e.g. "USD-per-shares", "shares") | USD |
| limit | No | Optional page size: items to return, integer 1-500 (default 25) | |
| offset | No | Number of items to skip for paging (default 0); use nextOffset from the previous response | |
| period | Yes | "CY2023", "CY2023Q2" or "CY2023Q4I" (instant) | |
| concept | Yes | Exact concept name, case-sensitive, e.g. "Assets", "Revenues", "NetIncomeLoss" | |
| taxonomy | No | Taxonomy (default "us-gaap"; also "ifrs-full", "dei", "srt") | us-gaap |
| companies | No | Optional tickers/CIKs/names to restrict results to |
Output Schema
| Name | Required | Description |
|---|---|---|
| meta | No | Tool-specific context (company, source_url, ...) |
| count | Yes | Number of items in this page |
| items | Yes | Result rows for this page |
| total | Yes | Total items matching the filters (before paging) |
| offset | Yes | Offset of the first item in this page |
| hasMore | Yes | True if more items exist after this page |
| nextOffset | Yes | Offset to pass for the next page, or null |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive/openWorld, but the description adds substantial context beyond them: it is a free, unauthenticated GET to data.sec.gov (no token, no Apify billing), returns a paged payload with named fields, supports an optional ciks filter, and enumerates errors (NOT_FOUND, SEC_FETCH_FAILED). This is rich disclosure an agent cannot get from the annotations.
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?
Front-loaded with the core purpose, then organized into labeled sections (Period format, Behavior, WHEN NOT TO USE, COST, EXAMPLE) that each carry distinct value. It is on the long side, and the return-field enumeration partly overlaps the output schema, but nothing is wasted filler.
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?
With an output schema present and annotations covering the safety profile, the description still supplies auth model (no token), cost, error states, period/unit formats, an alternative-routing section, and a worked example. Nothing an agent needs to call it 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 100%, so the schema already documents all eight parameters, setting a baseline of 3. The description adds value by spelling out period-format semantics ('CY2023' annual, 'CY2023Q2' quarterly, 'CY2023Q4I' instant for balance-sheet items) and unit examples, reinforcing intent beyond the raw schema strings.
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?
States a specific verb and resource: query one XBRL concept across every SEC filer via the SEC frames API. It names concrete concepts (Revenues, Assets, NetIncomeLoss) and explicitly distinguishes itself from the sibling edgar_get_company_facts, so an agent can route without opening a schema.
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?
Provides explicit when-to-use contexts ('screening and peer comparison') with two concrete scenarios, and a dedicated WHEN NOT TO USE section routing to edgar_get_company_facts for single-company history and edgar_list_filings for filings. Alternatives and the conditions selecting them are fully enumerated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
edgar_get_filing_documentGet SEC filing document textARead-onlyIdempotentInspect
Fetch the text of an SEC filing document from the sec.gov EDGAR archives, converted from HTML to plain text, returned in character-paged chunks. Use to read the actual content of a filing (risk factors, MD&A, 8-K press release, ...). Identify the document by documentUrl (from edgar_list_filings), or by company + accessionNumber (the primary document is used unless document names another file in the filing). Behavior: free, read-only GET to www.sec.gov (no token). Large 10-Ks can exceed 500k characters; read them in pages with offset/maxChars (nextOffset is returned). Only https://www.sec.gov/Archives/ URLs are accepted. RETURNS: {document_url,content_type,total_chars,offset,returned_chars,hasMore,nextOffset,text}. Errors: INVALID_URL, COMPANY_NOT_FOUND, FILING_NOT_FOUND, NOT_FOUND, SEC_FETCH_FAILED. WHEN NOT TO USE: to find which filings exist use edgar_list_filings first; for structured financial values use edgar_get_company_facts (no text parsing needed). COST: free - direct sec.gov requests from this MCP server, no APIFY_TOKEN, no Apify billing. EXAMPLE: {"company":"AAPL","accessionNumber":"0000320193-24-000123","maxChars":20000} -> first 20000 chars of the 10-K text with nextOffset for the next page.
| Name | Required | Description | Default |
|---|---|---|---|
| raw | No | Return raw HTML instead of extracted text (default false) | |
| offset | No | Character offset to start from (default 0) | |
| company | No | Ticker ("AAPL"), CIK ("320193", zero-padding optional) or company name fragment ("Apple"); best match is used. Call edgar_resolve_company first if the name is ambiguous. | |
| document | No | File name inside the filing to fetch instead of the primary document, e.g. "ex99-1.htm" | |
| maxChars | No | Max characters to return (default 20000, max 100000) | |
| documentUrl | No | Full sec.gov Archives URL, e.g. https://www.sec.gov/Archives/edgar/data/320193/000032019324000123/aapl-20240928.htm | |
| accessionNumber | No | Accession number, e.g. "0000320193-24-000123" (requires company) |
Output Schema
| Name | Required | Description |
|---|---|---|
| text | Yes | |
| offset | Yes | |
| hasMore | Yes | |
| nextOffset | Yes | |
| total_chars | Yes | |
| content_type | Yes | |
| document_url | Yes | |
| returned_chars | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations (readOnlyHint/idempotent/openWorld already cover the safety profile) by disclosing the no-token free access model, the URL whitelist restriction (only https://www.sec.gov/Archives/), the fact that 10-Ks can exceed 500k chars, and the pagination contract with nextOffset. Enumerated error codes (INVALID_URL, COMPANY_NOT_FOUND, SEC_FETCH_FAILED, etc.) add concrete failure behavior.
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?
Front-loaded with the core action, then cleanly sectioned into Behavior, RETURNS, WHEN NOT TO USE, COST, and EXAMPLE. The RETURNS field list and error enumeration partially duplicate the existing output schema, which is the only wasted space; everything else earns its place.
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 7 params, rich annotations, and an output schema, the description covers the remaining agent-facing gaps: how to identify the document, pagination strategy for very large filings, cost/auth model, URL constraints, and failure modes. An agent can invoke this correctly without further exploration.
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 100%, so the baseline is 3, but the description adds relational semantics the schema cannot express: documentUrl comes from edgar_list_filings, company+accessionNumber resolves to the primary document unless 'document' names another file, and offset/maxChars drive the paging loop with nextOffset returned. It does not restate types or bounds, correctly leaving those to the 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?
States a specific verb (Fetch), resource (SEC filing document text from EDGAR), and the transformation applied (HTML converted to plain text, character-paged chunks). It is clearly distinguishable from siblings like edgar_list_filings (discovery) and edgar_get_company_facts (structured values), which it names.
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?
Contains an explicit WHEN NOT TO USE block routing to edgar_list_filings for discovery and edgar_get_company_facts for structured numbers, plus a positive use statement ('Use to read the actual content of a filing'). Two identification paths (documentUrl vs company+accessionNumber) are also spelled out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
edgar_list_filingsList SEC filings for a companyARead-onlyIdempotentInspect
List a single company's SEC EDGAR filings (newest first) with form type, filing/report dates, accession number and direct document URLs, filtered by form type and date range, with limit/offset paging. Use to find which filings exist (e.g. "Apple's 10-Ks since 2020", "Tesla 8-Ks this year") and to get an accession_number / document_url for edgar_get_filing_document. Not for financial values (use edgar_get_company_facts). Behavior: free, read-only GET to data.sec.gov submissions API (no token). By default searches the ~1000 most recent filings; set includeOlder=true to also load the full historical archive (more requests). RETURNS: {count,total,offset,hasMore,nextOffset,meta:{cik,name,tickers},items:[{accession_number,form,filing_date,report_date,primary_document,primary_doc_description,items,size_bytes,document_url,index_url}]}. Errors: COMPANY_NOT_FOUND, NOT_FOUND, SEC_FETCH_FAILED. WHEN NOT TO USE: for document text use edgar_get_filing_document; for XBRL numbers use edgar_get_company_facts; for many companies at once use edgar_batch_export (paid). COST: free - direct sec.gov requests from this MCP server, no APIFY_TOKEN, no Apify billing. EXAMPLE: {"company":"AAPL","formTypes":["10-K"],"since":"2020-01-01","limit":5} -> 5 newest Apple 10-K rows with accession_number and document_url.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Optional page size: items to return, integer 1-200 (default 20) | |
| since | No | Optional inclusive lower bound on filing_date, format YYYY-MM-DD, e.g. "2020-01-01". Default: no lower bound. | |
| until | No | Optional inclusive upper bound on filing_date, format YYYY-MM-DD, e.g. "2024-12-31". Default: no upper bound. | |
| offset | No | Number of items to skip for paging (default 0); use nextOffset from the previous response | |
| company | Yes | Ticker ("AAPL"), CIK ("320193", zero-padding optional) or company name fragment ("Apple"); best match is used. Call edgar_resolve_company first if the name is ambiguous. | |
| formTypes | No | Exact form types to keep, e.g. ["10-K","10-Q"], ["8-K"], ["4"]. Case-insensitive. Omit for all forms. | |
| includeOlder | No | Also search filings older than the ~1000 most recent (default false) |
Output Schema
| Name | Required | Description |
|---|---|---|
| meta | No | Tool-specific context (company, source_url, ...) |
| count | Yes | Number of items in this page |
| items | Yes | Result rows for this page |
| total | Yes | Total items matching the filters (before paging) |
| offset | Yes | Offset of the first item in this page |
| hasMore | Yes | True if more items exist after this page |
| nextOffset | Yes | Offset to pass for the next page, or null |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Although annotations already declare readOnly, openWorld, idempotent, and non-destructive, the description adds meaningful behavior: free/no-token access, default search over ~1000 recent filings, includeOlder triggering more requests, and specific error codes. This goes well beyond the structured safety hints and helps set expectations for cost and scope.
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 organized into scannable sections (behavior, returns, exclusions, cost, example). However, the detailed RETURNS block and a duplicate 'not for financial values' aside are somewhat redundant given an output schema already exists, adding length without new decision-relevant information.
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 7 parameters, annotations covering safety, and an output schema, the description still supplies everything needed: purpose, when/when-not-to-use, cost, error conditions, default scope behavior, and an example. Nothing essential for correct invocation 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 100%, so the baseline is 3; the schema already documents each parameter, including formats and ranges. The description adds value through a concrete example and by clarifying that includeOlder=true expands to the full historical archive at the cost of more requests, which enriches the meaning of that parameter beyond its schema text.
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+resource ('List a single company's SEC EDGAR filings') and immediately specifies the returned fields, filtering, and paging. It explicitly distinguishes itself from siblings like edgar_get_filing_document and edgar_get_company_facts, so an agent can identify when this tool applies without opening schemas.
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 gives concrete use cases ('which filings exist', retrieving accession_number/document_url) and a dedicated WHEN NOT TO USE block naming alternatives for document text, XBRL numbers, and multi-company exports. The condition selecting each sibling is explicit, leaving no routing ambiguity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
edgar_resolve_companyResolve company to SEC CIK (free)ARead-onlyIdempotentInspect
Resolve US company tickers, CIKs or name fragments to official SEC CIK numbers, tickers and registrant names using the SEC public ticker map (company_tickers.json). Use this first when you only need an identifier (e.g. "what is Nvidia's CIK?") or want to confirm which company a name refers to before fetching filings/facts. Next steps: edgar_list_filings for filings, edgar_get_company_facts for financial data. Behavior: read-only HTTP GET to sec.gov, no API token, no cost; the map is cached for 6 hours. Covers SEC registrants with a listed ticker only (no delisted/private filers). RETURNS: {count, items}: one "company_match" row per match (cik zero-padded to 10 digits, ticker, name, match = cik|ticker|name, submissions_url), or an "error" row with code COMPANY_NOT_FOUND. Exact ticker/CIK matches win over name substring matches. WHEN NOT TO USE: not for filings (edgar_list_filings) or financial values (edgar_get_company_facts); other tools already accept tickers/names directly. COST: free - direct sec.gov requests from this MCP server, no APIFY_TOKEN, no Apify billing. EXAMPLE: {"queries":["NVDA","apple"]} -> {count:2, items:[{type:"company_match", cik:"0001045810", ticker:"NVDA", name:"NVIDIA CORP", match:"ticker"}, ...]}
| Name | Required | Description | Default |
|---|---|---|---|
| queries | Yes | 1-50 tickers ("NVDA"), CIKs ("1045810" or zero-padded) or case-insensitive name fragments ("nvidia") | |
| maxMatchesPerQuery | No | Max rows per query for name-fragment searches (default 5) |
Output Schema
| Name | Required | Description |
|---|---|---|
| count | Yes | Number of rows returned |
| items | Yes | Result rows; each has a "type" field (data rows or machine-readable "error" rows) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly/idempotent/openWorld annotations, it discloses transport (HTTP GET to sec.gov), no token/no cost, a 6-hour cache, and the critical coverage limitation (only SEC registrants with a listed ticker – no delisted/private filers). It also explains match precedence and the COMPANY_NOT_FOUND error row.
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?
Front-loaded with the core purpose and organized under RETURNS / WHEN NOT TO USE / COST / EXAMPLE, so an agent can scan it fast. Minor redundancy: 'no API token, no cost' is repeated in the Behavior line and the COST line, costing a little tightness.
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 two-parameter read tool with an output schema, the description covers purpose, routing, cost, caching, coverage limits, match precedence, error code, and a worked example. Nothing an agent needs in order to call it 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 100%, so the baseline is 3, but the description adds genuine semantic value: accepted query forms (ticker/CIK/name fragment), the meaning of maxMatchesPerQuery for name-fragment searches, and the rule that exact ticker/CIK matches beat name substring matches. A concrete example call reinforces this.
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?
States a specific verb+resource: resolve US company tickers, CIKs or name fragments to official SEC CIK numbers/tickers/registrant names, naming the underlying source (company_tickers.json). It is clearly distinguishable from the filing- and facts-oriented siblings.
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?
Explicitly says to use it first when only an identifier is needed, names the next-step tools (edgar_list_filings, edgar_get_company_facts), and adds a WHEN NOT TO USE clause noting other tools accept tickers/names directly. When/when-not/alternatives are all covered.
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.
7 tool updates
v1.2.1- Added
edgar_batch_export - Removed
edgar_company_filings_and_facts - Added
edgar_get_company_facts - Added
edgar_get_concept_across_companies - Added
edgar_get_filing_document - Added
edgar_list_filings - Added
edgar_resolve_company
1 tool update
v0.1.0- First observed
edgar_company_filings_and_facts
TDQS
Scored across 6 tools
Most tools have clearly distinct purposes: identifier resolution, filing lists, document text, single-company facts, cross-company concept screening, and bulk export. However, edgar_batch_export overlaps functionally with several free tools (filings, facts, text excerpts), which could confuse selection despite explicit cost and scale guidance. The overall set is well-differentiated but not perfectly exclusive.
All tool names share the consistent 'edgar_' prefix and use snake_case with verb-led phrases (resolve_company, list_filings, get_filing_document, get_company_facts, get_concept_across_companies, batch_export). The pattern is predictable and readable, with only the minor stylistic variation of 'batch_export' versus the 'get_' family, which does not impede understanding.
Six tools is well-scoped for an SEC EDGAR data server, covering the essential operations without redundancy. Each tool earns its place, balancing single-company lookups, cross-company queries, and bulk export. The count sits comfortably within the ideal 3–15 range.
The surface covers the core lifecycle: resolving companies, listing filings, reading filing text, retrieving single-company facts, cross-company concept comparison, and batch export. Minor gaps exist, such as full-text search across EDGAR and retrieval of non-primary documents within a filing, and free multi-company multi-metric queries require paid batch or multiple calls. These are workable limitations rather than critical dead ends.
Maintenance
Related MCP Connectors
Resolves stock tickers to SEC CIK numbers, recent 10-K/10-Q/8-K filings, and entity metadata.
Primary-source SEC filing intelligence and financial/disclosure reconciliation for AI agents.
Get a US company's SEC filings and headline financials from EDGAR. $0.002/call via x402.
Search SEC EDGAR filings, financial statements, and company data.
Related MCP Servers
- -licenseNot gradedqualityNot gradedmaintenanceEnables deep analysis of SEC EDGAR filings through universal company search, document content extraction, and advanced filing search capabilities. Provides AI-ready access to business descriptions, risk factors, financial statements, and full-text search across any public company's SEC documents.-
- 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
- AlicenseAqualityBmaintenanceEnables AI agents to research US public company filings, financials, and insider transactions using SEC EDGAR data, with no API keys required. Provides tools for company lookup, recent filings, full-text search, financial facts, and insider activity.5MIT
- AlicenseNot gradedqualityBmaintenanceEnables searching SEC EDGAR for companies, retrieving recent filings (e.g., 10-K, 10-Q), and accessing structured XBRL financial facts.42 npmMIT