Skip to main content
Glama

Get Fund Holdings

secedgar_get_fund_holdings
Read-onlyIdempotent

List what an ETF or mutual fund holds, parsed from the NPORT-P portfolio report it files with the SEC every quarter. The input is the fund — a ticker like VOO, a fund series ID, or the registrant trust — which is the opposite direction from the ownership tools: secedgar_get_institutional_holdings and secedgar_find_holders answer who owns a company, this answers what a fund owns. Each position carries the security name, CUSIP/ISIN/LEI where the filer reports them, share balance, market value in USD, and percent of the fund's net assets, alongside fund-level net assets and total assets. Positions are returned largest-first by percent of net assets, one page of limit rows starting at offset; the full report registers as df_ when a canvas is available — inspect it with secedgar_dataframe_describe, then analyze it with secedgar_dataframe_query, which is how a fund running to thousands of positions is aggregated or joined against the 13F and insider dataframes. An NPORT-P covers exactly one fund series and a registrant trust files one report per series, so a trust with several funds needs the specific fund named — pass its ticker or series_id. Reports publish roughly two months after the period they cover, so every result is dated: the holdings are the portfolio as of report_period_date, not as of today.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
fundYesThe fund whose portfolio you want — a fund ticker ("VOO", "SCHD"), an SEC fund series ID ("S000002839"), or a 10-digit CIK. A ticker names one share class of one series and routes directly; a CIK names the registrant, which files a separate report per series and needs series_id when it runs more than one fund. Fund trusts are indexed by ticker and series, not by name, so a trust name only resolves for a fund that trades under its own name ("SPDR S&P 500 ETF Trust") — pass the CIK otherwise.
limitNoNumber of positions to return inline, largest first by percent of net assets. Default 20. A broad index fund reports thousands of positions, so the inline list is a preview — read the whole portfolio from the dataframe, or page it with offset.
offsetNoPosition to start the page at, 0-based, over the full ordered holdings list. Pass the returned next_offset to read the next page — the report is parsed whole and sliced, so paging is stable and gap-free.
series_idNoSEC fund series identifier ("S000002839"), naming which fund of the registrant to report. Takes precedence over any series the fund input implies. Series IDs come back on fund results from secedgar_company_search and in the series list of a series_required error.
report_dateNoTarget a specific reporting period by its last day (YYYY-MM-DD), e.g. "2025-12-31". Omit for the most recent report. Period ends follow the fund's own fiscal quarters, which are not always calendar quarters — Direxion funds report to February, May, August, and November. available_report_periods in the response lists the ones this call identified; a period missing from that list is still worth requesting directly, since a report the submissions window no longer dates is dated by reading it.

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
capNoThe limit cap applied.
formNoEDGAR form name — "NPORT-P", or "NPORT-P/A" for an amended report.
fundNoThe fund input, echoed.
as_ofNoThe portfolio date these holdings are reported as of, and the publication lag behind it.
errorNoPresent when the call failed. Absent on success.
shownNoNumber of positions shown inline.
noticeNoGuidance when the report carried no positions or the page fell past the end.
offsetNoPosition the returned page starts at, 0-based.
datasetNoDataframe of every position, each row carrying the fund keys; joins 13F and insider dataframes on cusip. Absent when canvas is unavailable or the report had no positions.
holdingsNoOne page of positions, `limit` rows starting at `offset`, largest first by percent of net assets.
class_idsNoSEC class IDs covered; one report covers every class of the series.
series_idNoSEC series ID of the fund. Absent when the registrant files as a single fund with no series.
truncatedNoTrue when the inline holdings list was capped by limit.
filing_dateNoDate the report was submitted to EDGAR (YYYY-MM-DD).
next_offsetNoOffset for the next page. Absent on the last page.
series_nameNoFund name on the report; a single-registrant closed-end fund names itself here, with no series_id. Absent when blank or "N/A".
net_assets_usdNoFund net assets in USD at the report date — the denominator of percent_of_net_assets.
registrant_cikNoCIK of the registrant trust, zero-padded to 10 digits.
total_holdingsNoPositions in the full report, before offset and limit.
is_final_filingNoTrue when the fund marks this its last filing for the series (liquidation or merger). Absent when unstated.
registrant_nameNoEDGAR-conformed name of the registrant trust.
accession_numberNoAccession number — pass to secedgar_get_filing for the full document.
total_assets_usdNoFund total assets in USD at the report date.
report_period_endNoFiscal year end the reporting period falls in (YYYY-MM-DD), not the portfolio date.
report_period_dateNoPortfolio date (YYYY-MM-DD): positions as of this date, not today. Absent only when the filer omits it.
publication_lag_daysNoDays from the portfolio date to the filing date. Absent when the report omits its period date.
total_liabilities_usdNoFund total liabilities in USD at the report date.
available_report_periodsNoPeriod end dates of this fund's reports, newest first: what report_date can address, about a decade back. A trust filing thousands of reports a year can miss periods here that report_date still reaches.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed17 schema fields changed
    • changedOutput schema / properties / available_report_periods / description
      Previous value: -"Period end dates of this fund's reports, newest first — the horizon report_date can address, not the fund's full history. It reaches back roughly a decade of quarterly reports, and a period older than that is refused rather than served. A period inside the horizon can still be missing from the list: the dates come from the registrant's recent submissions window, which a trust filing thousands of reports a year outruns in months, and a report the window no longer reaches is dated by reading it only when report_date asks for it."New value: +"Period end dates of this fund's reports, newest first: what report_date can address, about a decade back. A trust filing thousands of reports a year can miss periods here that report_date still reaches."
    • changedOutput schema / properties / class_ids / description
      Previous value: -"SEC class IDs of the share classes covered. One report covers every class of the series, so a fund with both an ETF and an admiral-share class reports them together."New value: +"SEC class IDs covered; one report covers every class of the series."
    • changedOutput schema / properties / dataset / description
      Previous value: -"Canvas dataframe holding every position in the report (the inline holdings[] is a preview capped at limit). Each row carries the fund keys — series_id, registrant_cik, report_period_date, accession_number — alongside the position fields, so it joins against the 13F and insider dataframes on cusip. Absent when canvas is unavailable or the report had no positions."New value: +"Dataframe of every position, each row carrying the fund keys; joins 13F and insider dataframes on cusip. Absent when canvas is unavailable or the report had no positions."
    • changedOutput schema / properties / dataset / properties / name / description
      Previous value: -"Dataframe handle (df_XXXXX_XXXXX) — inspect its columns with secedgar_dataframe_describe, then query it with secedgar_dataframe_query."New value: +"Dataframe handle (df_XXXXX_XXXXX) for secedgar_dataframe_describe, then secedgar_dataframe_query."
    • changedOutput schema / properties / holdings / items / properties / asset_category / description
      Previous value: -"SEC asset-type code — EC equity-common, EP equity-preferred, DBT debt, RA repurchase agreement, STIV short-term investment vehicle, DE derivative. A filer that classifies a position as Other reports its own label here instead of a code (\"Right\"), because the code in that case is just \"OTHER\"."New value: +"SEC asset-type code (EC equity-common, EP equity-preferred, DBT debt, RA repurchase agreement, STIV short-term investment vehicle, DE derivative), or the filer's own label for Other (\"Right\")."
    • changedOutput schema / properties / holdings / items / properties / balance / description
      Previous value: -"Units held, counted in whatever `units` names — shares, principal, or contracts."New value: +"Units held, in whatever `units` names (shares, principal, or contracts)."
    • changedOutput schema / properties / holdings / items / properties / issuer_category / description
      Previous value: -"SEC issuer-type code — CORP corporate, MUN municipal, USGSE US government-sponsored, RF registered fund. A filer that classifies an issuer as Other reports its own label here instead of a code (\"Future\", \"Warrant\")."New value: +"SEC issuer-type code (CORP corporate, MUN municipal, USGSE US government-sponsored, RF registered fund), or the filer's own label for Other (\"Future\")."
    • changedOutput schema / properties / holdings / items / properties / name / description
      Previous value: -"Issuer name as the fund reports it. A derivative position routinely reports the literal \"N/A\" here and names the instrument in title instead, so group and label positions by title when asset_category marks a derivative."New value: +"Issuer name as reported. Derivatives often report \"N/A\" and name the instrument in title."
    • changedOutput schema / properties / holdings / items / properties / percent_of_net_assets / description
      Previous value: -"Percent of the fund's net assets, as the filer computes it. Negative on a short position — a leveraged fund's swap or futures leg regularly reports several percent below zero — so this is not bounded at 0."New value: +"Percent of the fund's net assets as the filer computes it; negative on short positions, so not bounded at 0."
    • changedOutput schema / properties / is_final_filing / description
      Previous value: -"True when the fund reports this as its last filing on the series, which marks a liquidation or merger. Absent when the filing does not answer."New value: +"True when the fund marks this its last filing for the series (liquidation or merger). Absent when unstated."
    • changedOutput schema / properties / next_offset / description
      Previous value: -"Offset to pass on the next call to continue through the portfolio. Absent on the last page."New value: +"Offset for the next page. Absent on the last page."
    • changedOutput schema / properties / publication_lag_days / description
      Previous value: -"Days between the portfolio date and the filing date. Absent when the report omits its period date."New value: +"Days from the portfolio date to the filing date. Absent when the report omits its period date."
    • changedOutput schema / properties / report_period_date / description
      Previous value: -"Last day of the period this portfolio is reported as of (YYYY-MM-DD). Holdings are the fund's positions on this date, not today's. Absent only when the filer omits it."New value: +"Portfolio date (YYYY-MM-DD): positions as of this date, not today. Absent only when the filer omits it."
    • changedOutput schema / properties / report_period_end / description
      Previous value: -"Last day of the fiscal year the reporting period falls in (YYYY-MM-DD) — the fund's fiscal year end, not the portfolio date."New value: +"Fiscal year end the reporting period falls in (YYYY-MM-DD), not the portfolio date."
    • changedOutput schema / properties / series_id / description
      Previous value: -"SEC series ID of the fund this report covers. Absent when the registrant files as a single fund with no series structure, which is how some older exchange-traded trusts are organized."New value: +"SEC series ID of the fund. Absent when the registrant files as a single fund with no series."
    • changedOutput schema / properties / series_name / description
      Previous value: -"Fund name as the filer states it on the report. A closed-end fund organized as a single registrant names itself here with no series_id alongside; absent only when the filer leaves the field blank or writes \"N/A\"."New value: +"Fund name on the report; a single-registrant closed-end fund names itself here, with no series_id. Absent when blank or \"N/A\"."
    • changedOutput schema / properties / total_holdings / description
      Previous value: -"Positions in the report, before offset and limit — the size of the full portfolio."New value: +"Positions in the full report, before offset and limit."
  2. Changed2 schema fields changed
    • changedOutput schema / properties / error / properties / data / properties / reason / description
      Previous value: -"Machine-readable failure mode. Declared by this tool: `fund_not_found`: The fund input resolves to neither an EDGAR company nor a known fund series `ambiguous_fund`: The fund name matches several EDGAR companies `series_required`: The input resolves to a registrant trust that files reports for more than one fund series `no_filings_found`: No NPORT-P report exists for this fund, or none for the requested report_date Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `fund_not_found`: The fund input resolves to neither an EDGAR company nor a known fund series. `ambiguous_fund`: The fund name matches several EDGAR companies. `series_required`: The input resolves to a registrant trust that files reports for more than one fund series. `no_filings_found`: No NPORT-P report exists for this fund, or none covers the report_date requested. `rate_limited`: SEC is rate-limiting this server's IP — SEC answered 429, or the call was refused without being sent while the cool-down after one runs. Other values are possible when a failure originates below the handler."
    • changedOutput schema / properties / error / properties / data / properties / reason / examples
      Previous value: -[
      -  "fund_not_found",
      -  "ambiguous_fund",
      -  "series_required",
      -  "no_filings_found"
      -]New value: +[
      +  "fund_not_found",
      +  "ambiguous_fund",
      +  "series_required",
      +  "no_filings_found",
      +  "rate_limited"
      +]
  3. Changed1 schema field changed
    • changedOutput schema / properties / dataset / properties / name / description
      Previous value: -"Dataframe handle (df_XXXXX_XXXXX) — pass to secedgar_dataframe_query."New value: +"Dataframe handle (df_XXXXX_XXXXX) — inspect its columns with secedgar_dataframe_describe, then query it with secedgar_dataframe_query."
  4. Changed6 schema fields changed
    • changedInput schema / $schema
      Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • addedInput schema / additionalProperties
      Added value: +false
    • changedOutput schema / $schema
      Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • addedOutput schema / anyOf
      Added value: +[
      +  {
      +    "not": {
      +      "required": [
      +        "error"
      +      ]
      +    },
      +    "required": [
      +      "fund",
      +      "class_ids",
      +      "registrant_cik",
      +      "registrant_name",
      +      "filing_date",
      +      "form",
      +      "accession_number",
      +      "total_holdings",
      +      "offset",
      +      "available_report_periods",
      +      "holdings",
      +      "as_of"
      +    ]
      +  },
      +  {
      +    "required": [
      +      "error"
      +    ]
      +  }
      +]
    • addedOutput schema / properties / error
      Added value: +{
      +  "additionalProperties": {},
      +  "description": "Present when the call failed. Absent on success.",
      +  "properties": {
      +    "code": {
      +      "description": "JSON-RPC error code for this failure.",
      +      "maximum": 9007199254740991,
      +      "minimum": -9007199254740991,
      +      "type": "integer"
      +    },
      +    "data": {
      +      "additionalProperties": {},
      +      "properties": {
      +        "reason": {
      +          "description": "Machine-readable failure mode. Declared by this tool: `fund_not_found`: The fund input resolves to neither an EDGAR company nor a known fund series `ambiguous_fund`: The fund name matches several EDGAR companies `series_required`: The input resolves to a registrant trust that files reports for more than one fund series `no_filings_found`: No NPORT-P report exists for this fund, or none for the requested report_date Other values are possible when a failure originates below the handler.",
      +          "examples": [
      +            "fund_not_found",
      +            "ambiguous_fund",
      +            "series_required",
      +            "no_filings_found"
      +          ],
      +          "type": "string"
      +        },
      +        "recovery": {
      +          "additionalProperties": {},
      +          "description": "Actionable next step for the caller.",
      +          "properties": {
      +            "hint": {
      +              "type": "string"
      +            }
      +          },
      +          "required": [
      +            "hint"
      +          ],
      +          "type": "object"
      +        },
      +        "retryable": {
      +          "description": "Whether retrying may succeed.",
      +          "type": "boolean"
      +        }
      +      },
      +      "type": "object"
      +    },
      +    "message": {
      +      "description": "Human-readable description of what went wrong.",
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "code",
      +    "message"
      +  ],
      +  "type": "object"
      +}
    • removedOutput schema / required
      Removed value: -[
      -  "fund",
      -  "class_ids",
      -  "registrant_cik",
      -  "registrant_name",
      -  "filing_date",
      -  "form",
      -  "accession_number",
      -  "total_holdings",
      -  "offset",
      -  "available_report_periods",
      -  "holdings",
      -  "as_of"
      -]
  5. Added

TDQS

A4.8/5.0
Behavior5/5

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

Annotations already cover the safety profile (readOnly, idempotent, openWorld), yet the description adds substantial context: source filing (NPORT-P), a ~2-month publication lag, that results are as-of report_period_date not today, and that paging is stable/gap-free. This is far beyond what structured fields supply.

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?

Long but dense and front-loaded: the core purpose and direction distinction come first, then paging, then the dataframe escalation, then the trust/series caveat and dating. Nearly every sentence carries distinct information, though it is close to overlong.

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?

With an output schema present, the description need not explain return fields, yet it still names them (CUSIP/ISIN/LEI, share balance, market value, percent of net assets) and describes ordering and pagination. Nothing needed to invoke or interpret the tool is missing.

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

Parameters4/5

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

Schema coverage is 100%, so the baseline is 3, but the description adds real meaning beyond the schema: series_id takes precedence over the implied series, ticker routes directly while CIK names a multi-series registrant, and report_date quarters follow fund fiscal calendars (Direxion example). It enriches rather than repeats.

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 (list) and resource (what an ETF/mutual fund holds), and explicitly separates itself from siblings by describing the opposite direction from secedgar_get_institutional_holdings and secedgar_find_holders. An agent can pick between them without opening any schema.

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

Usage Guidelines5/5

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

Gives explicit when-to-use routing (fund vs. ownership tools), when a trust needs the specific fund named via ticker or series_id, and when to escalate to the dataframe tools for thousands of positions. No exclusion is left to inference.

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

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.