io.github.ABWerks/pequod-mcp
Complete US ETF holdings from SEC N-PORT filings + ticker/CUSIP/FIGI crosswalk. Primary source.
Open source Open in the app JSON README (API)
About
Complete US ETF holdings from SEC N-PORT filings + ticker/CUSIP/FIGI crosswalk. Primary source.
Details
- Kind
- MCP servers
- Topic
- Finance & crypto
- Publisher
- abwerks
- Origin
- official
- Category
- ferramentas
- Transport
- local
- Version
- 0.2.2
- Last push
- 2026-08-15T17:08:18Z
- Repository state
- ativo
- Language
- Python
- License
- Apache-2.0
- Added
- 2026-08-29 03:01:38
- Updated
- 2026-08-29 03:01:38
- Origin id
io.github.ABWerks/pequod-mcp
README
# pequod-mcp — "the Gam"
<!-- mcp-name: io.github.ABWerks/pequod-mcp -->
**SEC-primary-source ETF holdings + identifier crosswalk for agents.**
An MCP (Model Context Protocol) server that gives AI agents the *complete*
holdings of any US-registered ETF straight from SEC EDGAR N-PORT filings —
not a top-10 scrape — plus a set of identifier-crosswalk tools (ticker,
CUSIP/SEDOL, FIGI → resolved symbol) backed by OpenFIGI and SEC reference
data. Runs locally over stdio; no vendor market-data subscriptions required.
## Tools
| Tool | What it does | Sources |
|---|---|---|
| `lookup_cik` | Ticker → SEC CIK + entity metadata (name, SIC, exchanges, fiscal year end) | SEC `company_tickers.json` + submissions API |
| `resolve_ticker` | Raw ticker + optional exchange code → Yahoo-convention symbol, verified | Exchange-suffix map (pure string mapping) + SEC + OpenFIGI |
| `resolve_cusip` | CUSIP (or SEDOL) → symbol, with cross-source verification | OpenFIGI (one batched request) + SEC name/ticker agreement |
| `resolve_figi` | Bloomberg FIGI → symbol, with cross-source verification | OpenFIGI + SEC name/ticker agreement |
| `get_etf_holdings` | Any US ETF → **complete** holdings list from its latest monthly N-PORT filing (name, ticker, ISIN, FIGI, LEI, shares, USD value, % of net assets, country, currency) | SEC EDGAR N-PORT XML |
All tools are read-only.
### How verification works
Crosswalk results are verified without any market-data vendor:
1. **SEC registry check** — if the mapped ticker is a US SEC registrant, the
entity title in `company_tickers.json` must agree with the OpenFIGI
security name. A gross name mismatch **vetoes** the mapping
(`verification: "name_veto"`) rather than returning a plausible-looking
wrong symbol.
2. **OpenFIGI mapping** — non-US symbols (outside SEC's registry) verify on
the OpenFIGI mapping itself, labeled `verification: "openfigi"` so you
can tell the confidence tiers apart.
Yahoo Finance *symbology* (`.SW`, `.T`, `.L`, … suffixes) is applied as a
pure string convention — the default path makes **no network calls to
Yahoo**.
## Install
```bash
# with uv
uv pip install pequod-mcp
# or with pip
pip install pequod-mcp
```
Run it directly (stdio):
```bash
pequod-mcp
```
### Optional: OpenFIGI API key
The server works without a key (OpenFIGI anonymous rate limits apply). For
heavier use, get a free key at <https://www.openfigi.com/api> and set:
```bash
export API_OpenFIGI="your-key-here"
```
### Optional: Yahoo enrichment extra
An opt-in extra adds a live Yahoo quote block to crosswalk results. It is
**off by default** and never used otherwise; enabling it means you accept
the Yahoo Finance terms of use yourself.
```bash
pip install 'pequod-mcp[yahoo]'
export PEQUOD_YAHOO_VERIFY=1
```
## Configure in Claude
**Claude Desktop** (`claude_desktop_config.json`) or any MCP client with a
stdio transport:
```json
{
"mcpServers": {
"pequod": {
"command": "pequod-mcp",
"env": {
"API_OpenFIGI": "your-key-here"
}
}
}
}
```
**Claude Code:**
```bash
claude mcp add pequod -e API_OpenFIGI=your-key-here -- pequod-mcp
```
## Agent workflow examples
**1. "What does SCHD actually hold?"**
```text
Agent: lookup_cik("SCHD")
→ { cik: "0000884394", entity_name: "SCHWAB STRATEGIC TRUST", found: true }
Agent: get_etf_holdings("SCHD", cik="0000884394")
→ { fund_name, report_date, source_url (the actual EDGAR filing),
total_holdings: ~100, holdings: [ { name, ticker, isin, figi,
balance, value_usd, pct_val, ... } ] }
```
The agent gets every position with weights, plus the EDGAR URL for citation
— auditable back to the primary source.
**2. "I have a CUSIP from a 13F — what stock is this?"**
```text
Agent: resolve_cusip("594918104")
→ { yahoo_symbol: "MSFT", verified: true, verification: "openfigi+sec",
company_name: "MICROSOFT CORP", cik: "0000789019",
openfigi: { figi: "BBG000BPH459", ... } }
```
If OpenFIGI's mapping disagrees with SEC's registry on who the ticker
belongs to, the tool refuses (`verification: "name_veto"`) instead of
handing back a wrong symbol.
**3. "Compare two dividend ETFs' overlap."**
```text
Agent: get_etf_holdings("SCHD") → complete holdings A
Agent: get_etf_holdings("VYM") → complete holdings B
Agent: joins on isin (or ticker), computes overlap weight, reports the
shared names — all from two tool calls, both citing SEC filings.
```
## Data provenance
- **All holdings data comes from SEC EDGAR primary sources** (Form N-PORT
filings, the submissions API, and `company_tickers.json`). Identifier
crosswalks come from the **OpenFIGI API** (FIGI is an open OMG standard).
- **No CUSIPs in output.** Tool outputs carry ticker, ISIN, FIGI, and LEI;
CUSIP fields present in the underlying filings are deliberately stripped.
- **SEC fair access respected:** a declared User-Agent on every request, a
throttle well under EDGAR's published rate limit, and an on-disk cache
(`.cache/` next to the module, override with `PEQUOD_CACHE_DIR`) for
`company_tickers.json` (24 h) and N-PORT documents (30 days — filed
documents are immutable).
- **Fail-loud policy:** if EDGAR is unreachable or a filing cannot be
parsed, tools return an error. There is no degraded or partial fallback
source — you either get filing-backed data or a clear failure.
- N-PORT filings are published on a lag (holdings are typically ~1–2 months
behind). The `report_date` and `source_url` fields tell you exactly which
period you are looking at.
- **Not investment advice.** This server relays public regulatory filings
and open identifier mappings; verify independently before making
investment decisions.
## Environment variables
| Variable | Default | Purpose |
|---|---|---|
| `API_OpenFIGI` | *(unset)* | OpenFIGI API key (higher rate limits) |
| `PEQUOD_CACHE_DIR` | `.cache/` next to the module | On-disk cache location |
| `PEQUOD_YAHOO_VERIFY` | *(off)* | Opt-in Yahoo enrichment (needs the `[yahoo]` extra) |
| `LOG_LEVEL` | `INFO` | Server log verbosity |
## Development
```bash
pip install -e '.[dev]'
pytest # fully offline — fixture filings, no live network
```
## License
Apache-2.0 — see [LICENSE](LICENSE). Copyright 2026 AB Evergreen Analytics LLC.