Earnings Call Transcripts via MCP and API

Say your team wants an agent to answer "compare what AMD and NVIDIA management said about data-center demand last quarter, with citations." You could scrape two transcripts, chunk them, embed them, and hope your retrieval is good. Or you could call an earnings call transcripts API that returns the cited passages directly. This is a hands-on walkthrough of the second path — over REST when your code drives, and over MCP when the model drives — using FocusAlpha's real endpoints. It's written for the research and quant teams who build tools for professional investors, where the end product is a defensible answer, not just a working call. Every endpoint, field and config below was checked against the live FocusAlpha docs in September 2026.

TLDR:

  • REST: POST /v1/retrieve with a natural-language query and tickers/year/quarter filters returns cited transcript passages you feed to your own model.
  • MCP: connect Claude to the hosted MCP endpoint and it retrieves those same passages on its own through the retrieve tool, no retrieval code.
  • Either way you get the verbatim evidenceText plus a source — the model reasons, you keep the citation.

The REST call

The retrieval endpoint takes a plain-English query and optional filters. Authenticate with your fa_live_ key; everything except query is optional.

curl https://api.focusalpha.ai/v1/retrieve \
  -H "Authorization: Bearer fa_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "data center demand and capex plans",
    "filters": { "tickers": ["NVDA", "AMD"], "year": 2025, "quarter": "Q1" },
    "top_k": 8
  }'
Request field Meaning
query Natural-language search (required)
filters.tickers Scope to one or more companies
filters.year / filters.quarter Scope to a period
top_k How many passages to return

Source: request shape per the FocusAlpha Quick Start.

Reading the response

You get back an array of chunks. The field that matters is evidenceText — the verbatim span — and the source object that makes it citeable.

{
  "chunks": [
    {
      "text": "Data center revenue grew 23% sequentially to a record $22.6 billion...",
      "score": 0.18,
      "evidenceText": "Data center revenue grew 23% sequentially to a record $22.6 billion.",
      "source": {
        "documentTitle": "NVIDIA Q1 2025 Earnings Call",
        "documentType": "earnings_call",
        "ticker": "NVDA", "year": 2025, "quarter": "Q1"
      }
    }
  ],
  "meta": { "total": 8, "periodMismatch": null }
}
Response field What it carries
evidenceText The 1–3 sentence quoted span
source.ticker / year / quarter Company + period of the passage
source.documentType earnings_call
score Cosine distance — lower is closer (not a 0–1 confidence)
meta.periodMismatch Non-null when it served a nearby period instead

Source: response fields per the Quick Start and Retrieve reference. The sample is abridged from the docs; year and quarter follow the company's fiscal calendar, so NVIDIA's "Q1 2025" is the call held in May 2024.

Flow: a natural-language query with filters goes to POST /v1/retrieve, which returns cited chunks with evidenceText and source, which you concatenate into your own model's prompt to answer with citations

Figure 1: Retrieval you feed to your own model. Source: FocusAlpha Docs.

Then you concatenate the chunks into your prompt and let your model reason — the API deliberately stops at the cited passages and hands generation to you:

const { chunks } = await (await fetch("https://api.focusalpha.ai/v1/retrieve", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.FOCUSALPHA_API_KEY}`,
             "Content-Type": "application/json" },
  body: JSON.stringify({ query: "data center demand",
    filters: { tickers: ["NVDA", "AMD"] }, top_k: 8 }),
})).json();

const context = chunks
  .map((c, i) => `[${i + 1}] (${c.source.documentTitle}) ${c.evidenceText}`)
  .join("\n\n");
// ...pass `context` into your Claude / GPT / open-model prompt, and cite [1], [2]...

The MCP path: let the model retrieve

If you're working inside Claude, you can skip the plumbing entirely. The MCP server is a hosted endpoint at https://mcp.focusalpha.ai/mcp (Streamable HTTP) — nothing to install. On claude.ai, add it as a custom connector (Settings → Connectors → Add custom connector, paste the URL) and approve with one-click OAuth. In Claude Desktop or Claude Code, point your client at the URL with your API key in the Authorization header — for Claude Desktop, merge this into claude_desktop_config.json:

{
  "mcpServers": {
    "focusalpha": {
      "type": "http",
      "url": "https://mcp.focusalpha.ai/mcp",
      "headers": {
        "Authorization": "Bearer fa_live_your_key_here"
      }
    }
  }
}

Retrieval is one of 16 tools the endpoint exposes: alongside retrieve (semantic search over transcripts and filings, returning cited passages), Claude can call get_institutional_holdings for 13F data, get_insider_trades for Form 4 activity, financial-statement tools, and the SEC filing index — deciding on its own when to use each.

Then just ask, and Claude calls retrieve once per company and answers with citations:

Compare what AMD and NVIDIA management said about data center
demand on their most recent earnings calls, and cite the sources.

Four-step MCP flow: user asks to compare AMD vs NVIDIA with citations, Claude calls the retrieve tool per company, the server returns cited passages, Claude answers with citations

Figure 2: The same data, retrieved autonomously. Source: FocusAlpha MCP docs.

Two things worth knowing from the docs. Setup really is just the endpoint: the MCP server is hosted, so there's no package to install — you point your client at the URL, and your key stays in the client config (on claude.ai, the OAuth approval creates a dedicated key behind the scenes). And retrieval is honest about coverage: ask for a quarter it doesn't hold and it serves the nearest prior period, flagging it in meta.periodMismatch rather than returning nothing or something off-target.

What it won't do

A walkthrough that only shows the happy path isn't much use, so here are the edges, all from the Retrieve reference:

  • US tickers only. filters.tickers takes US-listed symbols, at most 25 per request.
  • No generation. The endpoint returns passages and stops. Summarizing, comparing and deciding are your model's job, which is also where summaries tend to go wrong.
  • score is not confidence. It's a cosine distance for ranking. Don't threshold on it as if it were a probability.
  • source.sourceUrl can be null. The ticker, period and document title are always there; the click-through link isn't guaranteed.
  • A period can be substituted. Always read meta.periodMismatch before telling a user "in Q4 they said…".

REST or MCP?

Use REST when… Use MCP when…
Your app controls each retrieval call The model should retrieve on its own in-chat
You're building a backend or pipeline You're in Claude Desktop / Claude Code
You want deterministic, testable requests You want the fastest path to a working demo

Source: guidance per the MCP docs.

The thing to hold onto across both paths: what comes back is the quote and its source, not a summary. That's what lets your agent answer "what did management say about data-center demand" with the actual sentence and a link — the point of an earnings call transcripts API built for agents rather than a scraper you maintain. The same retrieval pattern works for 10-K and 10-Q text; only documentType changes.

FAQ

How do I query earnings call transcripts from an agent?

Call POST https://api.focusalpha.ai/v1/retrieve with a natural-language query and optional tickers/year/quarter filters, using your fa_live_ key. You get back cited passages (evidenceText plus a source) that you concatenate into your own model's prompt.

How do I connect earnings-call retrieval to Claude over MCP?

Add the hosted MCP endpoint https://mcp.focusalpha.ai/mcp as a custom connector on claude.ai (one-click OAuth), or configure it in claude_desktop_config.json as an HTTP server with your fa_live_ key in the Authorization header. Then ask Claude naturally — it calls the retrieve tool itself. There's nothing to install, and the same endpoint exposes 15 more tools covering 13F holdings, insider trades, financials, and filings.

What does the retrieval API return for an earnings-call query?

An array of chunks, each with the verbatim evidenceText span, a relevance score (cosine distance, lower is closer), and a source object with the company, year, quarter, and document. There's no LLM on the retrieval side — you run the model over the cited passages.

What happens if the quarter I asked for isn't available?

The API is honest about coverage: it serves the nearest prior period rather than returning nothing, and flags that substitution in meta.periodMismatch so your agent can tell the user it answered from an adjacent quarter.

What should I look for in an earnings call transcripts API or MCP server?

Three things: whether results carry the verbatim quote and its source, whether REST and MCP run on the same corpus so code and chat agree, and what the coverage is. You have options: earningscalls.dev and Equibles offer both an API and an MCP server, and FMP and Finnhub offer transcript APIs. They differ mainly on coverage and on whether you get full transcripts or retrieved passages. FocusAlpha's retrieval API returns passages for US companies; if you need full-text dumps or non-US calls, check the alternatives.

What is FocusAlpha?

FocusAlpha is a SEC filings API and agent-ready financial data layer: it turns SEC filings (10-K, 10-Q, 8-K, 13F), earnings-call transcripts, and other trusted company communications into structured, normalized data where every value keeps its citation back to the source document. AI agents connect via API or MCP to research public companies from complete, trusted information.

FOR AGENTS

This post is available as plain markdown with structured metadata — no scraping required.

GET .md →