mcp-edgar-ux
mcp-edgar-ux
For AI agents: SEC EDGAR filings that won't blow your context window. I return file paths, you use Read/Grep/Bash. A Tesla 10-K is 241K tokens - I save it to disk so you read only what you need.
For humans: Bloomberg Terminal-style output. Formatted tables, not raw JSON. Context-efficient by design.
Why This Approach Wins
Other SEC MCPs: Dump entire filing into tool response (241K tokens per 10-K)
This MCP: Save to /var/idio-mcp-cache/sec-filings/, return path (50 tokens)
You get:
Zero context pollution - Filing doesn't count against your limit
Selective reading - Read line 1000-1050, not all 10,000 lines
Multi-filing analysis - Compare 5 years of 10-Ks without context overflow
Formatted discovery - BBG Lite tables show what's available, not JSON blobs
The Bitter Lesson: Scale (disk storage) beats cleverness (cramming into context).
Installation
poetry installUsage
Quick Start
# Development (auto-reload on file changes, port 5012)
make dev # Server restarts when you edit code
# Production (background daemon, port 5002)
make server # Start server on http://127.0.0.1:5002
make logs # Tail server logs
# stdio mode (for Claude Code)
make stdio # Start stdio server
# Configure via .env (optional)
cp .env.example .env
# Edit .env to customize PORT and CACHE_DIRDefault ports:
Development: 5012 (auto-reload with
make dev)Production: 5002 (background daemon with
make server)
Configure Claude Code
Option 1: Using Poetry (recommended)
Configure Claude Code to use stdio transport:
{
"projects": {
"/your/project/path": {
"mcpServers": {
"mcp-edgar-ux": {
"command": "poetry",
"args": ["run", "mcp-edgar-ux"],
"cwd": "/path/to/mcp-edgar-ux"
}
}
}
}
}Option 2: SSE/HTTP Server (for web-based deployments)
For web interfaces or when you need a persistent HTTP server:
# Start HTTP server (runs in background)
make server
# Tail logs
make logs
# Customize port via .env (see Configuration section below)Configure Claude Code to use SSE transport:
{
"projects": {
"/path/to/your/project": {
"mcpServers": {
"edgar-ux": {
"type": "sse",
"url": "http://127.0.0.1:5002/sse"
}
}
}
}
}When to use SSE:
Web-based Claude Code deployments (e.g., browser terminals)
Multiple clients sharing one server instance
Debugging without restarting Claude Code
When to use stdio:
Local CLI usage (standard approach)
Single-user development environment
Usage in Claude Code:
# Fetch a filing
fetch_filing("TSLA", "10-K")
→ {path: "/var/idio-mcp-cache/sec-filings/TSLA/10-K/2025-04-30.txt", ...}
# Read what you need
Read("/var/idio-mcp-cache/sec-filings/TSLA/10-K/2025-04-30.txt", offset=1200, limit=50)
# Search for terms
Grep("supply chain", path="/var/idio-mcp-cache/sec-filings/TSLA/10-K/2025-04-30.txt")Tools
Addressing a filer: ticker or CIK
Every tool below accepts a CIK wherever it accepts a ticker (1082621,
0001082621, CIK0001082621).
This matters because EDGAR has issuer-side forms (10-K, 8-K — the filer is the
company) and holder-side forms (13F, 13D/G — the filer is whoever owns the
position). Holders often aren't issuers: HARVARD MANAGEMENT CO INC is CIK
0001082621 with no ticker, because an endowment has no listed stock. Ticker-only
addressing cannot reach it.
fetch_filing(ticker, form_type, date=None, format="text", document=None)
Download SEC filing to disk, return path.
Args:
ticker: Ticker ("TSLA") or CIK ("1082621")form_type: Form type ("10-K", "10-Q", "8-K", etc.)date: Optional date filter (YYYY-MM-DD). Returns filing closest >= date.format: Output format - "text" (default, clean), "markdown" (may have XBRL), or "html"document: Fetch a specific document from the accession (sequence number or filename) instead of the primary one
A submission is a bundle, not a file. This returns the accession's primary document. When the accession holds substance that wasn't returned, the output says so rather than looking complete:
PARTIAL — this is the primary document only.
1 document(s) in this accession were NOT returned:
[ 2] INFORMATION TABLE information_table.xml INFORMATION TABLEFor a 13F-HR the primary document is the cover page — it carries
tableEntryTotal and tableValueTotal and not one issuer name. Use
thirteenf_holdings() for the positions.
Returns:
{
"success": true,
"path": "/var/idio-mcp-cache/sec-filings/TSLA/10-K/2025-04-30.txt",
"company": "Tesla, Inc.",
"ticker": "TSLA",
"form_type": "10-K",
"filing_date": "2025-04-30",
"format": "text",
"size_bytes": 427000,
"sec_url": "https://www.sec.gov/...",
"cached": false
}Examples:
# Latest filing (text format, clean)
fetch_filing("TSLA", "10-K")
# Filing on or after specific date
fetch_filing("TSLA", "10-K", date="2024-01-01")
# Markdown format (may contain XBRL artifacts)
fetch_filing("AAPL", "10-Q", format="markdown")
# A named document from inside the accession
fetch_filing("NVDA", "13F-HR", document="2")
fetch_filing("1082621", "13F-HR", document="56904.xml")list_documents(ticker, form_type, date=None)
List every document inside a filing's accession.
Args:
ticker: Ticker ("NVDA") or CIK ("1082621")form_type: Form type ("13F-HR", "10-K", etc.)date: Optional date filter (YYYY-MM-DD)
Returns: Sequence, type, filename and description for each document, with
the primary one marked. Feed a sequence or filename to fetch_filing(..., document=...).
NVDA 13F-HR | 2026-08-14 | ACCESSION DOCUMENTS
ACCESSION: 0001045810-26-000065
SEQ TYPE DOCUMENT DESCRIPTION
1 13F-HR primary_doc.xml [PRIMARY]
2 INFORMATION TABLE information_table.xml INFORMATION TABLEthirteenf_holdings(ticker, date=None, form_type="13F-HR", max_holdings=50)
13F portfolio holdings — the information table, with issuer names.
Args:
ticker: CIK of the manager ("1082621") or ticker if it's also a listed issuer ("NVDA")date: Optional date filter (YYYY-MM-DD)form_type: "13F-HR" (default) or "13F-HR/A"max_holdings: Positions to display, largest first (default: 50; all are counted in totals)
Returns: Positions sorted by value with issuer, CUSIP, resolved ticker, % of book and share count — plus both totals, table and cover page, reconciled against each other. A cover-page total with no table behind it is exactly what this prevents.
HARVARD MANAGEMENT CO INC | 13F-HR | PERIOD 2026-06-30
FILED 2026-08-14 | CIK0001082621 | 0001193125-26-352412
PORTFOLIO: 19 positions | $4,263,102,872 (information table)
COVER PAGE: 19 positions | $4,263,102,872 [✓ reconciles]
# ISSUER TICKER VALUE % BOOK SHARES/PRN
1 SPACE EXPLORATION TECHN CORP - $2,210,091,186 51.8% 12,935,100
2 TAIWAN SEMICONDUCTOR MANUFAC TSM $349,591,747 8.2% 732,022search_filing(ticker, form_type, pattern, ...)
Search for pattern in SEC filing with fuzzy matching (tolerates typos/variations).
Args:
ticker: Stock ticker (e.g., "TSLA", "AAPL")form_type: Form type ("10-K", "10-Q", "8-K", etc.)pattern: Search pattern (extended regex, case-insensitive, fuzzy=1)date: Optional date filter (YYYY-MM-DD)context_lines: Lines of context before/after match (default: 2)max_results: Maximum matches to return (default: 20)
Returns: Matches with line numbers and surrounding context.
Examples:
# Find supply chain mentions
search_filing("TSLA", "10-K", "supply chain")
→ Finds: "supply chain", "supply-chain", "Supply Chain" (fuzzy matching)
# Search for multiple terms (OR)
search_filing("LNG", "10-Q", "Corpus Christi|Stage 3")
→ Matches either termlist_filings(form_type, ticker=None, ...)
List available SEC filings and their cached status.
Args:
form_type: Form type (e.g., "10-K", "10-Q", "8-K")ticker: Optional ticker or CIK. Omit to see latest across all companies.start: Starting index (default: 0, newest first)max: Maximum filings to return (default: 15)
Returns: List of filings with cached status (✓ = cached locally).
get_financial_statements(ticker, statement_type="all")
Get simplified financial statements (key metrics only, last 4 years).
IMPORTANT: Returns SIMPLIFIED high-level metrics from SEC aggregated data.
For detailed analysis, use fetch_filing() to get the full 10-K/10-Q.
Args:
ticker: Stock ticker (e.g., "TSLA", "AAPL")statement_type: "all" (default), "income", "balance", or "cash_flow"
Returns: Formatted multi-year statements (income, balance sheet, cash flow).
What you get:
Key GAAP metrics: Revenue, Net Income, Assets, Cash Flow, etc.
Last 4 annual periods
Clean, formatted tables
What you DON'T get:
Footnotes, exhibits, MD&A
Non-GAAP metrics or detailed line items
Forward-looking statements
Examples:
# All statements (4 years)
get_financial_statements("TSLA")
# Income statement only
get_financial_statements("TSLA", statement_type="income")Example Output
Our differentiator: BBG Lite formatted, human-readable output
list_filings("TSLA", "10-K")
TSLA 10-K FILINGS AVAILABLE
──────────────────────────────────────────────────────────────────────
FILED CACHED SIZE [ACTIONS]
2025-04-30 ✓ 423 KB
2025-01-30 ✓ 313 KB
2024-01-29 ✓ 814 KB
2023-01-31 -
2022-05-02 -
2022-02-07 -
2021-04-30 -
2021-02-08 -
2020-04-28 -
2020-02-13 -
2019-02-19 -
2018-02-23 -
2017-03-01 -
... 5 more filings
──────────────────────────────────────────────────────────────────────
✓ Cached filings available locally (instant access)
Other filings will be downloaded on demand from SEC
Data source: SEC EDGAR | Powered by edgartoolsfetch_filing("TSLA", "10-K")
TSLA 10-K | 2025-04-30 | FETCHED (downloaded)
COMPANY: Tesla, Inc.
FORM: 10-K
FILED: 2025-04-30
SIZE: 427 KB (10,234 lines)
PATH: /var/idio-mcp-cache/sec-filings/TSLA/10-K/2025-04-30.txt
Try: Read(path, offset=0, limit=50) | search_filing("TSLA", "10-K", "SEARCH TERM")Clean, formatted, immediately useful. No raw JSON dumps, no 241K tokens in context.
Configuration
Using .env file (recommended):
# Copy example and customize
cp .env.example .env
# Edit .env
PORT=5002
CACHE_DIR=/var/idio-mcp-cache/sec-filingsOr override inline:
# Custom port
PORT=8080 make server
# Custom cache directory
CACHE_DIR=/custom/path make serverDefaults (if no .env):
Port:
5002Cache:
/var/idio-mcp-cache/sec-filingsUser agent:
breed research breed@idio.sh(SEC requires this)
Workflow Example
# 1. Fetch Tesla's latest 10-K
fetch_filing("TSLA", "10-K")
→ /var/idio-mcp-cache/sec-filings/TSLA/10-K/2025-04-30.txt (427KB, clean text)
# 2. Search for supply chain mentions
search_filing("TSLA", "10-K", "supply chain")
→ Shows matches with line numbers and context
# 3. Read specific section
Read("/var/idio-mcp-cache/sec-filings/TSLA/10-K/2025-04-30.txt", offset=1200, limit=50)
→ Only 50 lines in context (not 241K tokens)
# 4. Analyze
"What are Tesla's supply chain risks?"Why File-Based?
Problem: Current MCPs dump full filing into tool response
TSLA 10-K = 241,120 tokens
AAPL 10-K = 268,922 tokens
Blows through context window
Forces LLM to process everything
Solution: Save to disk, read selectively
Zero context pollution on fetch
Use Read/Grep to view exactly what you need
Can work with multiple filings simultaneously
Filings persist between sessions
The Bitter Lesson: Scale (disk) beats cleverness (context).
Development
# Install dependencies
poetry install
# Development mode (auto-reload on file changes)
make dev
# Run tests
make test
# Lint and type check
make lint
# Clean cache
make cleanArchitecture
Hexagonal Architecture (Ports & Adapters):
mcp_edgar_ux/core/- Business logicDomain models (Filing, SearchResult, etc.)
Port interfaces (Repository, Fetcher, Searcher)
Use case services (pure business logic)
mcp_edgar_ux/adapters/- InfrastructureFilesystem cache (implements Repository port)
EDGAR API client (implements Fetcher port)
Grep search (implements Searcher port)
MCP handlers (shared tool definitions)
mcp_edgar_ux/container.py- Dependency injectionWires adapters to core services
Single point of configuration
mcp_edgar_ux/server_http.py- MCP HTTP/SSE server (170 lines)Thin wrapper around core
Uses dependency injection
Benefits:
Core is testable without MCP or infrastructure
Can swap adapters (S3 cache, different SEC API, etc.)
81% reduction in server code via dependency injection
Eliminated ~300 lines of duplication
Credits
Inspired by sec-edgar-mcp Built with edgartools Named after The Bitter Lesson by Rich Sutton
License
MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/bxxd/mcp-edgar-ux'
If you have feedback or need assistance with the MCP directory API, please join our Discord server