Skip to main content
Glama

pequod-mcp — "the Gam"

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.

Related MCP server: edgar-mcp

Install

# with uv
uv pip install pequod-mcp

# or with pip
pip install pequod-mcp

Run it directly (stdio):

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:

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.

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:

{
  "mcpServers": {
    "pequod": {
      "command": "pequod-mcp",
      "env": {
        "API_OpenFIGI": "your-key-here"
      }
    }
  }
}

Claude Code:

claude mcp add pequod -e API_OpenFIGI=your-key-here -- pequod-mcp

Agent workflow examples

1. "What does SCHD actually hold?"

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?"

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."

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

pip install -e '.[dev]'
pytest            # fully offline — fixture filings, no live network

License

Apache-2.0 — see LICENSE. Copyright 2026 AB Evergreen Analytics LLC.

Available Tools

5 tools
get_etf_holdingsA

Get the complete holdings of any US-registered ETF via SEC EDGAR.

Uses Form N-PORT filings (filed monthly by all US ETFs) as the single, consistent primary source. Each holding includes name, ticker, ISIN, FIGI, LEI, shares, USD value, percent of net assets, country, and currency. (CUSIPs are deliberately not included in output.)

ParametersJSON Schema
NameRequiredDescriptionDefault
cikNoOptional 10-digit SEC CIK (from lookup_cik). Skips the ticker→CIK lookup if provided.
tickerYesThe ETF ticker symbol (e.g. 'QQQ', 'SPY', 'SCHD', 'IHDG').

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description takes on full disclosure responsibility. It specifies the data source (monthly N-PORT filings), the exact fields returned, and deliberately notes that CUSIPs are excluded. This adds meaningful behavioral context beyond the schema, though it does not mention potential limitations like filing delays.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two concise paragraphs, front-loaded with the core action in the first sentence, followed by essential context and output details. Every sentence provides value; there is no redundancy or filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite moderate complexity, the description covers the tool's purpose, data source, returned fields, and an explicit exclusion (no CUSIPs). With an output schema present, detailed return structure is unnecessary, making this description complete for an AI agent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, with both parameters well-documented: ticker has examples and cik explains its optional role and the lookup-cik shortcut. The description itself adds no further parameter-level semantics, so the baseline score of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with 'Get the complete holdings of any US-registered ETF via SEC EDGAR,' clearly stating the tool's specific action, resource, and scope. It distinguishes itself from sibling tools (lookup_cik, resolve_ticker, etc.) which are identifier-resolution utilities rather than data-retrieval tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context about when the tool applies (any US-registered ETF, using Form N-PORT filings) but does not explicitly state when-not-to-use or compare with alternatives. It references lookup_cik only in the schema, not the description, so the guidance is contextually clear but lacks explicit exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

lookup_cikA

Look up a ticker's SEC Central Index Key (CIK) and entity metadata.

This is the first step before calling get_etf_holdings. The CIK is the SEC's unique identifier for every filing entity. The submissions endpoint also returns the entity name, SIC code, tickers, exchanges, fiscal year end, and addresses.

The ticker→CIK mapping comes from SEC's company_tickers.json (covers 10,000+ US tickers), cached on disk with a 24-hour freshness window.

ParametersJSON Schema
NameRequiredDescriptionDefault
tickerYesStock or ETF ticker symbol (e.g. 'SCHD', 'QQQ', 'AAPL').

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It discloses the data source (SEC's company_tickers.json), coverage (10,000+ US tickers), cache freshness (24-hour window), and the metadata returned (entity name, SIC code, tickers, exchanges, fiscal year end, addresses). This is strong context, though it doesn't explicitly state the operation is read-only.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is six sentences, front-loaded with the core purpose. Each sentence adds value—explaining the CIK, the workflow, metadata, data source, and caching—though it could be slightly tightened without losing meaning.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite having no annotations and only one parameter, the description covers the tool's purpose, role in the pipeline, data source, freshness, and returned metadata. With an output schema present, it doesn't need to describe return values. Minor gaps like error handling or invalid ticker behavior are acceptable for this simple lookup tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with a clear description for the 'ticker' parameter ('Stock or ETF ticker symbol'). The description adds context about US ticker coverage but does not meaningfully enrich the parameter beyond what the schema already provides, so the baseline score of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's function with a specific verb and resource: 'Look up a ticker's SEC Central Index Key (CIK) and entity metadata.' It distinguishes itself from sibling resolvers by focusing on SEC CIK and explicitly positions itself as a prerequisite step for get_etf_holdings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly says 'This is the first step before calling get_etf_holdings,' providing clear when-to-use context. However, it does not mention when not to use the tool or compare it directly with sibling tools like resolve_ticker, resolve_cusip, or resolve_figi.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

resolve_cusipA

Resolve a CUSIP (or SEDOL) identifier to a Yahoo-convention ticker symbol.

Queries OpenFIGI (one batched request trying both ID_CUSIP and ID_SEDOL), maps the result to a Yahoo-convention symbol via pure suffix mapping, and verifies the mapping against SEC company_tickers.json name/ticker agreement. A gross name mismatch between OpenFIGI and SEC vetoes the mapping.

Note: the CUSIP is accepted as INPUT only — tool outputs carry ticker/ISIN/FIGI identifiers, never CUSIPs.

ParametersJSON Schema
NameRequiredDescriptionDefault
cusipYesA 9-character CUSIP (or 7-character SEDOL) identifier.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries full burden. It transparently discloses the OpenFIGI batched query, suffix mapping, SEC verification, and veto on gross name mismatch. The note that CUSIP is input-only and outputs carry different identifiers is valuable. It stops short of 5 by not describing failure modes or error behavior, but it is unusually rich.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is three sentences, front-loaded with the core purpose, followed by concise process details and a critical input/output note. Every sentence earns its place with no fluff or repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the multi-step resolution process (OpenFIGI query, mapping, verification), the description covers the key behaviors and constraints. An output schema exists, so return-value details are not needed. Minor gaps like failure handling or rate limits keep it from a 5, but it is highly complete for a complex tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema covers 100% of parameter documentation with a clear description ('9-character CUSIP (or 7-character SEDOL) identifier'). The tool description adds no additional parameter-level meaning beyond what the schema provides, so the baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a clear, specific verb+resource+outcome: 'Resolve a CUSIP (or SEDOL) identifier to a Yahoo-convention ticker symbol.' This precisely states what the tool does and naturally distinguishes it from siblings like resolve_figi or lookup_cik by input type and output.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is strongly implied through the purpose statement and process details (e.g., handling both CUSIP and SEDOL, mapping to Yahoo ticker). However, it does not explicitly name alternatives or state when not to use it, so it falls short of a 5. The sibling tool names provide additional context but are not referenced.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

resolve_figiA

Resolve a Bloomberg FIGI (Financial Instrument Global Identifier) to a Yahoo-convention ticker symbol.

Queries OpenFIGI, maps the exchange code to a Yahoo suffix (pure string mapping), and verifies the mapping against SEC company_tickers.json name/ticker agreement.

ParametersJSON Schema
NameRequiredDescriptionDefault
figiYesA Bloomberg FIGI identifier (e.g. 'BBG000BVRVT1').

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden. It discloses that the tool queries OpenFIGI, performs a pure string mapping, and verifies against SEC data, providing useful process context. It does not detail error handling or failure modes, but these are less critical for a lookup tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences long, front-loaded with the primary purpose, and each sentence adds meaningful process detail without redundancy. It is concise and well-structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description adequately covers the main process steps and external dependencies. Since an output schema exists, return values are likely documented there. Minor gaps include not mentioning what happens if the FIGI is not found or the mapping fails, but overall it is complete enough for most use cases.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already provides a complete description of the 'figi' parameter, including an example. The description adds no additional semantic meaning or constraints beyond what the schema already states, so the baseline of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'Resolve' and the resource 'Bloomberg FIGI' to a 'Yahoo-convention ticker symbol'. It distinguishes itself from sibling tools like resolve_cusip and resolve_ticker by specifying the exact input and output format.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The usage context is implied by the description: if you have a FIGI and need a Yahoo ticker, you would use this tool. However, there is no explicit guidance on when to use this over alternatives or any when-not-to-use conditions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

resolve_tickerA

Resolve a raw ticker symbol to its Yahoo-convention equivalent.

Applies exchange suffix mapping and known manual fixes as a pure string transformation (no Yahoo network calls), then verifies the mapping against SEC company_tickers.json and/or OpenFIGI.

ParametersJSON Schema
NameRequiredDescriptionDefault
symbolYesRaw ticker symbol (e.g. 'AAPL', 'SCMN', 'BHP').
exchange_codeNoOptional exchange code — MIC format like 'XASX' or short format like 'AU', 'LN', 'SW', 'JP'.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are present, so the description carries the burden. It discloses important behaviors: the transformation is a 'pure string transformation (no Yahoo network calls)' and that it 'verifies against SEC company_tickers.json and/or OpenFIGI'. This adds meaningful context beyond the schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, zero waste, with the core purpose front-loaded. The second sentence provides valuable technical context without unnecessary elaboration.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-parameter tool with an output schema and no annotations, the description covers the core process, clarifies network usage, and mentions external verification sources. It lacks some edge-case behavior details but is reasonably complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema documents both parameters adequately. The description hints at 'exchange suffix mapping' but does not add significant detail beyond what the schema already provides, matching the baseline for full schema coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Resolve') and resource ('raw ticker symbol to its Yahoo-convention equivalent'), clearly identifying the tool's unique function. This distinguishes it from sibling tools that resolve other identifiers (CIK, CUSIP, FIGI).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The context is clear: use when a raw ticker needs conversion to Yahoo format. However, it does not explicitly contrast with sibling tools or provide exclusions, so it stops short of a full 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

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

  1. 5 tool updatesv0.2.2
    • First observedget_etf_holdings
    • First observedlookup_cik
    • First observedresolve_cusip
    • First observedresolve_figi
    • First observedresolve_ticker

TDQS

A4.3/5.0

Scored across 5 tools

Disambiguation5/5

Each tool targets a distinct input identifier or action: lookup_cik maps tickers to CIK, resolve_ticker/cusip/figi convert different identifier types to Yahoo tickers, and get_etf_holdings retrieves ETF data. Despite three resolve tools, their input types (ticker, CUSIP/SEDOL, FIGI) are clearly differentiated.

Naming Consistency5/5

All tools follow a verb_noun pattern: lookup_cik, resolve_ticker, resolve_cusip, resolve_figi, get_etf_holdings. The verbs are simple and consistent, with 'resolve_' forming a clear subgroup for identifier conversion.

Tool Count5/5

Five tools is well within the ideal 3-15 range for a focused server. Each tool has a distinct role, and the count neither feels thin nor bloated.

Completeness4/5

The core workflow (lookup CIK, then get ETF holdings) is covered, and the most common identifier types (ticker, CUSIP/SEDOL, FIGI) have resolvers. Minor gaps exist, such as missing ISIN or LEI resolvers, but these are edge cases rather than critical missing operations.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    B
    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
    1
    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
    355
    AGPL 3.0
  • A
    license
    Not graded
    quality
    D
    maintenance
    Hosted MCP server that gives AI agents real-time access to SEC EDGAR filings search, 10-K/8-K reading, XBRL financial facts, and insider-trade (Form 4) alerts.
    15
    1
    MIT