Blog / AI and MCP
AI and MCP

13F MCP: Pulling 13F Holdings Into Claude, Cursor or ChatGPT

How to query 13F institutional holdings from an AI assistant over MCP, the exact tool schema involved, and what you get back with and without an API key.

By the SecFeed teamNovember 3, 20266 min read
Key takeaways

"13F MCP" means connecting an AI assistant to a Model Context Protocol server that can look up 13F institutional holdings as a callable tool, instead of asking the model to recall a filing from training data that may be outdated or simply wrong. This guide shows exactly what that tool call looks like: the schema an MCP client sees when it lists the tool, a real request against it, and what comes back with and without an API key.

Why look up 13F data through MCP at all

A 13F filing reports an institutional manager's long equity positions as of a quarter end, and new filings are published continuously on EDGAR. A model's training data has a cutoff, so without a live data source, asking an assistant "what does this manager hold" either returns a stale answer or an invented one. An MCP server fixes that by giving the assistant a tool it can call during the conversation, which returns the actual filing rows rather than a description of what the filing probably says. Our MCP server for SEC filings guide covers the protocol and setup across clients in general; this one focuses specifically on the 13F tool.

The 13F tool's exact schema

SecFeed's MCP server exposes a tool named form_13f_holdings. A tools/list call, which needs no API key, returns its schema:

curl -s https://secfeedapi.com/mcp -H "Content-Type: application/json" \
  -d '{"jsonrpc": "2.0", "id": 1, "method": "tools/list", "params": {}}'

The response includes this entry alongside the other 39 tools:

{
  "name": "form_13f_holdings",
  "description": "13F holdings rows by CUSIP or filer CIK.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "cusip": {"type": "string", "description": "CUSIP"},
      "cik": {"type": "string", "description": "filer CIK"},
      "period": {"type": "string", "description": "MM-DD-YYYY quarter end"}
    }
  }
}
The tool's arguments are the same filters the REST 13F holdings API takes: a CUSIP to find every holder of one security, or a filer CIK to pull one manager's whole portfolio, plus a period in the form's own MM-DD-YYYY date format rather than a plain quarter label.

Get this data as clean JSON

SecFeed turns SEC filings into structured data with one API call: GET /v1/form-13f/holdings?cusip=037833100&period=06-30-2026. Free key, no card needed.

Get a free API key →

Calling the tool: what a key gets you

An MCP client calls a tool with tools/call, naming the tool and passing its arguments:

curl -s https://secfeedapi.com/mcp -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{"jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": {"name": "form_13f_holdings", "arguments": {"cusip": "037833100", "period": "06-30-2026"}}}'

The result comes back as an MCP tool result, with the actual holdings rows serialized as text inside the content array:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "[{\"accession\": \"0001234567-26-012345\", \"filer_cik\": 1067983, \"filer\": \"EXAMPLE CAPITAL MANAGEMENT LLC\", \"period\": \"06-30-2026\", \"issuer\": \"APPLE INC\", \"cusip\": \"037833100\", \"value\": 182400000, \"shares\": 915000}]"
      }
    ]
  }
}

The client is then responsible for turning that text back into structured data if it wants to reason over individual fields; an agent that only needs to summarize the holdings for a user can often just pass the text straight into its answer.

What happens without a key

tools/call on SecFeed's MCP server checks for a key, even though tools/list does not. A real call made for this post, with no Authorization header at all, returned this instead of the holdings:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "SecFeed: missing API key. Get a free key in a minute at https://secfeedapi.com/signup/ (25 calls, no card; 125 with a card, never charged; every dataset), then send it as the header Authorization: Bearer <key>. In your MCP client config, add the same header to the secfeed server."
      }
    ],
    "isError": true
  }
}

That matters for agent use specifically: it is a normal MCP tool result with isError: true, not a bare HTTP 401 that some clients swallow silently. An agent sees the plain-English message and, if it is capable of it, can relay the signup step to the person using it, rather than just failing with no explanation.

Four ways to reach the same 13F data

MCP is one interface among several to the same underlying rows, each suited to a different caller:

MethodWhat it returnsWho calls itNeeds a key
tools/list over MCPThe tool's name, description and schema only, no filing dataA client discovering what the server can doNo
tools/call over MCPThe actual holdings rows, as text inside the tool resultAn AI agent acting on a user's requestYes
GET /v1/form-13f/holdingsThe same holdings rows, as JSONCode you write yourselfYes
sf.holdings_13f(...) in the Python SDKThe same rows, already parsed into Python objectsA script, without building the HTTP request by handYes

None of these change what the data covers or how far back it goes; they change how a caller reaches it. An agent that only has MCP access and a script you write yourself will see identical values for the same CUSIP and period.

Setting it up in an MCP client

Most MCP clients that support remote servers over HTTP take the same shape of configuration, pointing at the server URL with the key in a header:

{"mcpServers": {"secfeed": {"url": "https://secfeedapi.com/mcp", "headers": {"Authorization": "Bearer YOUR_KEY"}}}}

Once connected, asking the assistant something like "pull the 13F holdings for CUSIP 037833100 in the second quarter of 2026" gives it enough to call form_13f_holdings with the right arguments on its own, without you writing the request by hand. Our 13F filings API guide covers the same data over plain REST, including how value_unit and pre-2013 text-era rows differ from the structured XML era, details that apply identically whether you call the endpoint directly or reach it through this tool.

Frequently asked questions

Does the 13F MCP tool return different data than the REST API?

No. form_13f_holdings calls the same underlying 13F holdings data as /v1/form-13f/holdings; MCP is a different calling convention for an AI client, not a separate dataset with different coverage or fields.

Can an AI agent list the 13F tool without an API key?

Yes. tools/list, the discovery step that returns the tool's name, description and schema, needs no key on SecFeed's MCP server. Only tools/call, the step that returns actual filing data, requires one.

What format does the period argument take?

MM-DD-YYYY, matching the quarter-end date as the 13F form itself states it, for example 06-30-2026 for the second quarter of 2026. It is not a quarter label like "2026 Q2".

Can I look up a manager's full portfolio instead of one security?

Yes. Pass cik, the filer's CIK, instead of cusip, with the same period argument, to get every position that manager reported for that quarter rather than every holder of a single security.

Get this data as clean JSON

SecFeed turns SEC filings into structured data with one API call: GET /v1/form-13f/holdings?cusip=037833100&period=06-30-2026. Free key, no card needed.

Get a free API key →

For information only, not investment advice. Data from public SEC filings; verify important figures on SEC.gov. See our AI Disclosure.