Skip to main content
Glama
edgar-mcp

edgar-mcp

by asp53826

edgar-mcp

An MCP server that gives a model working access to SEC EDGAR — company filings, filing text, and XBRL financial facts.

CI Python 3.11+ runtime deps

Verification launch kit

Inspect

Published evidence

Strongest result

Warm 10-K reads reach 1.1 ms / 0.00 MB, measured at 138x the cold fetch

Verification

Wire-level request windows, transferred-byte counters, offline fixtures, and burst tests

Failure boundary

Public EDGAR data only; not an investment recommendation or a complete accounting model

Reproduce

make test && make bench

Interactive replay

Replay the burst and false cache hit

Evidence contract: a class named RateLimiter or Cache proves nothing by itself. The benchmark measures grants inside a real one-second window and bytes transferred on the wire.

→ Interactive results page — fire a burst of tool calls and watch a full token bucket sail through the limit it was written to enforce, then see what each EDGAR host can actually validate.

EDGAR will happily hand you a 9 MB filing and then throttle you for asking twice. The interesting part of this server is everything between the model and the wire.

Related MCP server: SEC EDGAR MCP

What is actually implemented

  • ticker, CIK, or company name resolves to an EDGAR identity, with ambiguous names returning candidates instead of a silent wrong guess;

  • filing history spans EDGAR's overflow files, so companies past ~1000 filings don't get silently truncated to the recent page;

  • filing text arrives windowed with a next_offset cursor — a 10-K is ~206K characters and does not belong in a context window whole;

  • inline-XBRL scaffolding is stripped, so extracted text starts at the prose and not at 11K characters of false2025FY0000320193...;

  • XBRL concepts come back as a time series, with a tag-discovery tool because nobody knows the right us-gaap tag name off the top of their head;

  • one metric can be ranked across every filer for a period via the frames API;

  • full-text search covers filings from 2001 onward;

  • requests are paced under SEC's 10 req/s ceiling even when a model fires a parallel burst of tool calls;

  • responses are cached per-host by the freshness rule that host actually supports.

flowchart LR
  M["model tool call"] --> R["resolve ticker / CIK / name"]
  R --> C{"cached?"}
  C -->|"Archives: immutable"| D["disk, no network"]
  C -->|"data.sec.gov: TTL fresh"| D
  C -->|"stale or absent"| P["pacer @ 9 req/s"]
  P --> E["EDGAR"]
  E -->|"429 / 5xx"| P
  E --> W["cache write"]
  W --> X["iXBRL strip + window"]
  D --> X
  X --> M

Measured, not implied

Apple M-series, macOS, Python 3.13, live EDGAR. Reproduce with make bench.

Check

Result

Tests passing

32

companyfacts cold fetch

3.75 MB / 97 ms

companyfacts warm read

0.00 MB / 1.4 ms (68×)

10-K document cold fetch

1.52 MB / 154 ms

10-K document warm read

0.00 MB / 1.1 ms (138×)

submissions warm read

0.00 MB / 0.2 ms (755×)

Sustained request rate

9.2 req/s

Peak requests in any 1s window

10 (SEC ceiling: 10)

iXBRL scaffolding removed from a 10-K

11,303 chars

Text extraction throughput

23.4 MB/s

Windows to read a full 10-K @ 40K

6

Both the cache and pacer numbers above are post-fix. The first benchmark run reported a 3.75 MB "cache hit" that was really a full re-download, and 19 requests inside a one-second window against a 10 req/s limit. See DESIGN.md.

Where it loses

  • Freshness on data.sec.gov is a guess. That host sends no ETag and no Last-Modified, so conditional requests are impossible and freshness falls back to a 1-hour TTL. A filing that lands mid-TTL is invisible until it expires. Pass ttl=0 if you need read-your-writes.

  • Windowing re-reads, it doesn't range-read. EDGAR honors HTTP Range on Archives (verified: 206, accept-ranges: bytes), but partial HTML can't be parsed reliably, so the whole document is fetched once and windowed from cache. The first call on a large filing pays the full download.

  • Search is never cached. Results are query-shaped and EDGAR's full-text endpoint offers no validators, so every search is a live round trip against the 9 req/s budget.

  • The pacer is global. Ten companies queried in parallel serialize at ~9 req/s. Correct, but not fast.

  • XBRL values are consolidated totals. Dimensional breakdowns (by segment, by geography) exist in the data and this does not surface them.

  • Full-text search starts at 2001. Older filings are reachable through list_filings, not search_filings.

Verify it

make test    # 32 tests, no network
make bench   # live EDGAR, prints the table above

Setup

SEC requires a User-Agent carrying a real contact address and blocks requests without one. The server refuses to start rather than letting you discover that as a confusing 403 later.

export EDGAR_USER_AGENT="your-project you@example.com"

Build and run the local container over stdio:

docker build -t edgar-mcp:local .
docker run --rm -i \
  -e EDGAR_USER_AGENT="your-project you@example.com" \
  edgar-mcp:local

The image runs as an unprivileged user and writes its EDGAR cache under that user's home directory. Mount /home/edgar/.cache/edgar-mcp if the cache should survive container restarts.

Add to claude_desktop_config.json or .mcp.json:

{
  "mcpServers": {
    "edgar": {
      "command": "uv",
      "args": ["run", "--directory", "/path/to/edgar-mcp", "edgar-mcp"],
      "env": { "EDGAR_USER_AGENT": "your-project you@example.com" }
    }
  }
}

Tools

Tool

Purpose

lookup_company

ticker / CIK / name → EDGAR identity

list_filings

filing history, filtered by form and date

get_filing_text

windowed document text, follow next_offset

list_concepts

which XBRL tags a company actually reports

get_concept

time series for one tag

compare_concept

one tag ranked across all filers for a period

search_filings

full-text search, 2001→

cache_stats

hit rate, requests, bytes downloaded

A typical chain is lookup_company → list_filings → get_filing_text, or list_concepts → get_concept when you want numbers rather than prose.

License

MIT

Available Tools

8 tools
cache_statsB

Cache hit rate, request count, and bytes downloaded this session.

Inputs: no named parameters.

compare_conceptB

Compare one XBRL concept across all filers for a period, ranked by value. Period is CY2023 (annual), CY2023Q1 (duration), or CY2023Q1I (instant).

Inputs: tag (required), period (required), unit, limit, +1 more.

get_conceptC

Time series for one XBRL concept (e.g. Revenues, Assets, NetIncomeLoss) as reported by a company across filings.

Inputs: tag (required), query (required), limit, taxonomy.

get_filing_textA

Fetch the text of a filing document from its EDGAR Archives URL. Returns a window; if truncated is true, call again with next_offset.

Inputs: url (required), limit, offset.

list_conceptsA

List the XBRL tags a company actually reports, most-reported first. Use this to find the right tag before calling get_concept.

Inputs: query (required), contains.

list_filingsA

List a company's filings, newest first. Filter by form type (10-K, 8-K, DEF 14A, 4, ...) and filing-date range (YYYY-MM-DD).

Inputs: query (required), forms, limit, since, +1 more.

lookup_companyA

Resolve a ticker, CIK, or company name to its EDGAR identity.

Inputs: query (required).

search_filingsA

Full-text search across EDGAR filings from 2001 onward. Returns matching filings with document URLs.

Inputs: q (required), forms, limit, since, +1 more.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.8/5.0

    Scored across 8 tools

    Disambiguation5/5

    Each tool targets a distinct purpose: listing concepts, resolving companies, listing filings, fetching filing text, retrieving concept time series, searching full-text, comparing concepts, and cache statistics. No two tools appear to overlap in function, making selection unambiguous.

    Naming Consistency4/5

    Most tools follow the verb_noun pattern (list_concepts, lookup_company, get_filing_text, search_filings, compare_concept). The only deviation is cache_stats, which uses a noun_noun form and lacks a verb, but this is a minor inconsistency in an otherwise coherent naming scheme.

    Tool Count5/5

    With 8 tools, the server is well-scoped for SEC EDGAR data access. Each tool covers a necessary function without redundancy, and the count fits comfortably within the ideal range for a domain-specific MCP server.

    Completeness5/5

    The tool surface provides a complete read-only workflow: company resolution, filing discovery, full-text search, XBRL concept retrieval, and cross-company comparison. No obvious gaps exist for typical EDGAR use cases, and cache_stats adds operational insight.

    Maintenance

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      A
      quality
      C
      maintenance
      MCP server providing read-only access to SEC EDGAR filings, allowing LLMs to look up companies, search filings, and retrieve securities offering data.
      3
      68 PyPI
      2
      MIT
    • A
      license
      C
      quality
      B
      maintenance
      MCP server for accessing SEC EDGAR filings. Connects AI assistants to company filings, financial statements, and insider trading data with exact numeric precision.
      21
      664 PyPI
      386
      AGPL 3.0
    • A
      license
      A
      quality
      D
      maintenance
      An MCP server that wraps SEC EDGAR APIs to provide company financial data, screening metrics, and disclosure signals for investment diligence, with every figure traced to its source filing.
      8
      MIT
    • A
      license
      Not graded
      quality
      D
      maintenance
      MCP server for SEC EDGAR data, providing tools to look up companies, retrieve filings and documents, and access XBRL financial facts.
      142 npm
      MIT