arelle-mcp
# arelle-mcp
**The definitive MCP server for XBRL processing, validation, and financial analysis.**
[](https://pypi.org/project/arelle-mcp/)
[](https://pypi.org/project/arelle-mcp/)
[](LICENSE)
Built by **[King Hippopotamus](https://github.com/TheKingHippopotamus)**.
Uses [Arelle](https://arelle.org) — 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:
```bash
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
```bash
pip install arelle-mcp
```
### Claude Desktop
Add to `claude_desktop_config.json`:
```json
{
"mcpServers": {
"arelle-mcp": {
"command": "arelle-mcp",
"env": {
"ARELLE_MCP_MAX_FILINGS": "5"
}
}
}
}
```
### Claude Code
```bash
claude mcp add arelle-mcp -- arelle-mcp
```
### Cursor / Other MCP Clients
```json
{
"arelle-mcp": {
"command": "python",
"args": ["-m", "arelle_mcp"]
}
}
```
### HTTP Mode (Remote)
```bash
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:
1. Call `xbrl_fetch_sec_filing(ticker="AAPL", filing_type="10-K")`
2. Extract key metrics with `xbrl_extract_facts`
3. 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.stdout` is replaced by a proxy whose `.buffer` is that private
descriptor — what the MCP transport wraps — while every text write goes to
stderr;
- the `arelle` logger is pinned to stderr, Arelle runs with
`logFile="logToStdErr"`, and every synchronous Arelle call is wrapped in
`redirect_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
```bash
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](https://github.com/TheKingHippopotamus) — with zero compromises.
TDQS
Scored across 46 tools
Several tools have overlapping purposes (e.g., multiple fact extraction tools like xbrl_extract_facts, xbrl_fact_details, xbrl_company_facts), and the distinction between them may not be immediately clear to an agent. However, each tool has a specific use case described, reducing ambiguity somewhat.
All tools start with 'xbrl_' and use snake_case, providing a consistent prefix. However, the naming pattern mixes verb-first (e.g., xbrl_load_filing) and noun-first (e.g., xbrl_anomaly_detection) approaches, leading to minor inconsistency.
With 46 tools, the server is on the high end of tool counts. While the XBRL domain is complex and justifies many tools, there is some redundancy (e.g., multiple export formats) that could be consolidated.
The tool set covers a wide range of XBRL operations: loading, browsing, extraction, validation, comparison, and EDGAR-specific features. Minor gaps exist, such as no direct tool for modifying metadata, but overall the surface is comprehensive for its domain.