使用说明
arelle-mcp
The definitive MCP server for XBRL processing, validation, and financial analysis.
Built by King Hippopotamus.
Uses Arelle — the world's only free, open-source XBRL-certified processor — as its core engine. No other XBRL MCP server exists. This is the first.
What it does
arelle-mcp gives LLMs (Claude, GPT, etc.) full access to XBRL financial data
through 46 tools. That number is the tool registry's, not a figure typed
into this file — count it yourself against any checkout:
python -c "import asyncio; from arelle_mcp.server import mcp; \
print(len(asyncio.run(mcp.list_tools())))"
tests/test_tool_count.py runs that count in CI and fails if this README
drifts from it.
| Category | Tools | Description |
|---|---|---|
| Filing Ops | xbrl_load_filing, xbrl_filing_summary, xbrl_compare_filings, xbrl_close_filing, xbrl_list_filings |
Load, inspect, compare, and manage XBRL/iXBRL filings |
| Validation | xbrl_validate |
Validate against SEC EFM, EU ESEF, UK HMRC, or generic rules |
| Fact Extraction | xbrl_extract_facts, xbrl_fact_details |
Query financial data points with filtering by concept, period, dimension, unit |
| Taxonomy | xbrl_browse_taxonomy, xbrl_concept_details |
Search and explore the taxonomy (standard + company extensions) |
| Relationships | xbrl_presentation_tree, xbrl_calculation_tree, xbrl_dimension_structure |
Navigate financial statement hierarchies, calculation trees, and dimensional breakdowns |
| SEC EDGAR | xbrl_fetch_sec_filing, xbrl_search_sec_concept, xbrl_company_facts |
Fetch SEC filings by ticker/CIK, search historical concept data |
| Rendering | xbrl_render_statement |
Reconstruct financial statements (Balance Sheet, Income Statement, Cash Flow) |
| Document Intelligence | xbrl_extract_text, xbrl_search_text, xbrl_get_footnotes, xbrl_list_sections, xbrl_get_cover_page, xbrl_get_html_tables, xbrl_get_exhibits, xbrl_get_raw_xml |
Read the narrative: MD&A, risk factors, footnotes, cover page, tables, exhibits |
| Analysis Engine | xbrl_financial_ratios, xbrl_trend_analysis, xbrl_segment_breakdown, xbrl_anomaly_detection, xbrl_smart_summary, xbrl_peer_comparison |
Ratios, trends, segment splits, anomaly flags, peer comparison |
| Formula & Validation+ | xbrl_run_formula, xbrl_list_formulas, xbrl_dts_comparison, xbrl_check_calculations, xbrl_validate_extended |
XBRL Formula execution, DTS diffing, calculation-linkbase checks |
| EDGAR Pro | xbrl_edgar_search, xbrl_edgar_company_info, xbrl_edgar_filing_index, xbrl_edgar_bulk_facts, xbrl_edgar_insider_trades |
Full-text search, company metadata, filing index, bulk facts, Form 4 |
| Export | xbrl_export_json, xbrl_export_csv, xbrl_export_concepts, xbrl_export_dts, xbrl_create_instance |
Emit JSON/CSV/concept lists/DTS, and author new instances |
Plus 5 resources (reference data) and 5 prompt templates (guided analysis workflows).
Quick Start
Install
pip install arelle-mcp
Claude Desktop
Add to claude_desktop_config.json:
{
"mcpServers": {
"arelle-mcp": {
"command": "arelle-mcp",
"env": {
"ARELLE_MCP_MAX_FILINGS": "5"
}
}
}
}
Claude Code
claude mcp add arelle-mcp -- arelle-mcp
Cursor / Other MCP Clients
{
"arelle-mcp": {
"command": "python",
"args": ["-m", "arelle_mcp"]
}
}
HTTP Mode (Remote)
ARELLE_MCP_TRANSPORT=streamable-http ARELLE_MCP_PORT=8000 arelle-mcp
Usage Examples
Analyze Apple's Latest 10-K
"Fetch Apple's latest 10-K and give me a financial summary"
The LLM will:
- Call
xbrl_fetch_sec_filing(ticker="AAPL", filing_type="10-K") - Extract key metrics with
xbrl_extract_facts - Render financial statements with
xbrl_render_statement
Validate a Filing
"Validate this SEC filing: https://www.sec.gov/Archives/edgar/data/..."
Compare Two Quarters
"Compare Apple's Q2 and Q3 2024 10-Q filings"
Historical Revenue Trend
"Show me Microsoft's revenue history from SEC EDGAR"
The LLM calls xbrl_search_sec_concept(cik="789019", concept="Revenues") — no filing load needed.
Architecture
Core Design Decisions
1. Single-Session Lock — Arelle uses global state that isn't thread-safe. All operations are serialized via asyncio.Lock and offloaded to a ThreadPoolExecutor to avoid blocking the MCP event loop.
2. LRU Filing Cache — Each loaded filing consumes 30-60MB. An OrderedDict-based LRU cache (default: 5 filings) automatically evicts the oldest filing when capacity is reached, calling model.close() to free memory.
3. Lazy Imports — Arelle is heavy (~200MB with taxonomies). All Arelle imports happen lazily inside tool functions, keeping server startup fast.
Project Structure
src/arelle_mcp/
├── server.py # FastMCP instance, lifespan, registration
├── arelle_wrapper.py # ArelleManager — session lifecycle, concurrency, caching
├── serializers.py # Arelle objects → JSON/markdown
├── constants.py # Arcroles, disclosure systems, SEC config
├── tools/
│ ├── filing.py # Load, summary, compare, close, list
│ ├── validation.py # Validate against disclosure systems
│ ├── facts.py # Extract and filter facts
│ ├── taxonomy.py # Browse concepts, get details
│ ├── relationships.py # Presentation, calculation, dimension trees
│ ├── edgar.py # SEC EDGAR API integration
│ └── rendering.py # Financial statement rendering
├── resources/ # Reference data (disclosure systems, common concepts)
└── prompts/ # Guided analysis workflow templates
stdout is the protocol
Under the stdio transport, stdout is the JSON-RPC wire. A single stray byte on it is a framing error, and a compliant client will tear the transport down and lose every in-flight call.
Arelle is chatty: left to its defaults it prints iXBRL namespace and validation
messages (ix11, xmlSchema, ...) to stdout while loading a filing. In v2.1.0
that output landed on the wire and killed long extraction sessions. Since
v2.1.1 the server reserves stdout for the protocol at startup
(arelle_mcp.stdio_guard), on three independent levels:
- the real stdout is duplicated to a private descriptor and fd 1 is re-pointed at stderr, so even C-level writes are safe;
sys.stdoutis replaced by a proxy whose.bufferis that private descriptor — what the MCP transport wraps — while every text write goes to stderr;- the
arellelogger is pinned to stderr, Arelle runs withlogFile="logToStdErr", and every synchronous Arelle call is wrapped inredirect_arelle_output().
Nothing is silenced — all diagnostics still appear on stderr, where your
MCP client shows them. tests/test_stdout_is_clean.py proves it end to end by
running a real MCP handshake and a real iXBRL load in a child process and
asserting the parent sees only parseable JSON-RPC.
Configuration
| Environment Variable | Default | Description |
|---|---|---|
ARELLE_MCP_MAX_FILINGS |
5 |
Max filings cached in memory |
ARELLE_MCP_CACHE_DIR |
(none) | Directory for taxonomy cache |
ARELLE_MCP_TRANSPORT |
stdio |
Transport: stdio or streamable-http |
ARELLE_MCP_PORT |
8000 |
HTTP port (when using streamable-http) |
ARELLE_MCP_LOG_LEVEL |
INFO |
Logging level |
Development
git clone https://github.com/TheKingHippopotamus/Arelle-MCP.git
cd Arelle-MCP
pip install -e ".[dev]"
# Run tests
pytest
# Type check
mypy src/arelle_mcp
# Lint
ruff check src/
# Test with MCP Inspector
npx @modelcontextprotocol/inspector arelle-mcp
Supported File Formats
- XBRL Instance Documents (
.xbrl,.xml) - Inline XBRL (
.htm,.html) — SEC mandated since June 2021 - iXBRL Document Sets
- ZIP archives containing XBRL
- SEC EDGAR URLs (auto-fetched)
- Taxonomy Packages (
.zip)
Supported Disclosure Systems
- SEC EFM — US Securities and Exchange Commission
- ESEF — European Single Electronic Format (EU/ESMA)
- HMRC — UK HM Revenue & Customs
- GFM — Global Filing Manual
License
Apache 2.0 — same as Arelle itself.
Built by King Hippopotamus — with zero compromises.
