Most people building financial AI agents connect four or five APIs by hand.
One for prices. One for fundamentals. One for news. One for earnings dates.
The problem isn't lack of data. It's fragmentation.
If you're:
- building a research copilot for equities,
- automating pre-earnings screening,
- or designing an agent that reasons across price, fundamentals, and sentiment,
this matters.
Here's how to build an AI financial agent that pulls all four together, using EODHD's financial data API as the backbone.
The Traditional Financial Data API Approach Breaks Down Fast
Here's what building a financial agent usually looks like with a plain REST API.
You write a function to fetch prices. Another to fetch fundamentals. Another for news. Then you write orchestration logic so your agent knows which endpoint to call, in what order, and how to merge the responses into something the model can reason about.
Each new data type means a new wrapper function.
Each wrapper function is a new failure point.
And every time the agent needs to answer a question that spans two data types, like "is this company's fundamentals strong enough to justify holding through earnings," you're the one stitching the context together, not the model.
Developers usually discover this the hard way. The agent works fine in a demo with one data source. Then a real question comes in that needs prices, fundamentals, and news at once, and the whole orchestration layer has to be rebuilt.
The Real Problem Is Context, Not Data
Financial agents don't need more APIs.
They need a way to reach every data type through one consistent interface, so the model can decide what to call and combine it, instead of you hardcoding that logic in advance.
That's what MCP (Model Context Protocol) is built for.
What an MCP Server Changes for Financial Data APIs
MCP (Model Context Protocol) standardizes how an AI model discovers and calls external tools. Instead of you writing a custom wrapper for every endpoint, the model sees a list of available tools with their schemas, and decides which ones to call based on the question it's answering. It's the same underlying idea as Claude function calling, just extended to a whole catalog of tools instead of one function at a time.
For financial data, this matters because a single question rarely maps to a single endpoint.
EODHD ships an official MCP server with over 70 tools covering fundamentals, historical and real-time prices, earnings calendars, news, and sentiment. You point your agent at the server, and it gets access to all of it without you writing a single API wrapper.
Skip the wrapper functions
EODHD's MCP server exposes 70+ financial data tools out of the box, ready for Claude and other AI agents.
→ Get your EODHD API key
Building the AI Financial Agent with EODHD's MCP Server
Let's build an agent that can answer a question spanning multiple data types in a single call: fundamentals, upcoming earnings, and recent price action for a given ticker.
Setup
pip install anthropic
You'll need an EODHD API token and an Anthropic API key. EODHD's MCP server is available as a hosted endpoint, so there's no server to run yourself.
Connecting the agent to EODHD's MCP server in Python
EODHD's MCP server has two versions: v1 takes your API key directly in the URL, v2 uses OAuth 2.1 for clients that support it (like Claude Desktop). For a server-side script like this one, v1 is simpler.
import anthropic
client = anthropic.Anthropic(api_key="YOUR_ANTHROPIC_API_KEY")
EODHD_API_KEY = "YOUR_EODHD_API_TOKEN"
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1500,
messages=[
{
"role": "user",
"content": (
"Give me a quick pre-earnings health check on AAPL: "
"key fundamentals, the next earnings date, and how the "
"stock has moved over the last month."
)
}
],
mcp_servers=[
{
"type": "url",
"url": f"https://mcp.eodhd.com/v1/mcp?apikey={EODHD_API_KEY}",
"name": "eodhd-mcp"
}
]
)
for block in response.content:
if block.type == "text":
print(block.text)
What's actually happening here
The mcp_servers parameter is the whole trick. You're not calling three endpoints and merging the results yourself. You're handing the model a connection to EODHD's tool catalog and letting it decide what it needs.
For this one prompt, the model will typically:
- Call a fundamentals tool to pull margins, revenue growth, and valuation ratios
- Call an earnings calendar tool to find the next reporting date
- Call a historical prices tool to compute the recent price move
Three tool calls, one conversation, zero orchestration code written by you.
Reading the response
The API returns a mix of content blocks: text for the model's answer, mcp_tool_use for each tool it called, and mcp_tool_result for the raw data. If you want to inspect what the agent actually pulled (useful for debugging or logging), filter by block type instead of assuming a fixed order:
tool_calls = [
{"name": b.name, "input": b.input}
for b in response.content
if b.type == "mcp_tool_use"
]
for call in tool_calls:
print(call["name"], call["input"])
This is worth doing early. It shows you exactly which tools the model reached for, which helps you spot when it's calling something unnecessary or missing a data type your prompt implied.
Scoring Stock Opportunities with EODHD's Financial Data API
The MCP agent above decides on its own which EODHD tools to call. That's convenient, but it also hides what's happening. If you want to actually understand (and customize) the logic behind "which stocks look like good opportunities," it helps to call the same EODHD endpoints directly and build the scoring yourself.
This is also useful if you want a scheduled script that scans the market every morning instead of waiting for you to ask a chat agent.
Let's build that: a short pipeline that pulls candidates from the Screener API, pulls fundamentals and recent price action for each one, checks the news sentiment, and combines all of it into a single opportunity score.
Step 1: Shortlist candidates with the Screener API
Instead of pulling fundamentals for thousands of tickers, start narrow. The Screener API filters the entire market down to a shortlist in one request.
import requests
API_TOKEN = "YOUR_EODHD_API_TOKEN"
def get_candidates():
url = "https://eodhd.com/api/screener"
params = {
"api_token": API_TOKEN,
"sort": "market_capitalization.desc",
"filters": '[["market_capitalization",">",1000000000],'
'["exchange","=","us"],'
'["sector","=","Technology"]]',
"limit": 20,
"fmt": "json",
}
response = requests.get(url, params=params)
return response.json()["data"]
candidates = get_candidates()
tickers = [c["code"] for c in candidates]
print(tickers)
This pulls US tech stocks above $1B market cap, sorted by size. Swap the filters for whatever criteria define a "good price" to you: low P/E, high dividend yield, positive EPS growth, or a 52-week low signal.
Step 2: Pull fundamentals for each candidate
Once you have a shortlist, fetch the fundamentals for each ticker. This is where you check whether the price is actually backed by solid financials, not just cheap for a reason.
def get_fundamentals(symbol):
url = f"https://eodhd.com/api/fundamentals/{symbol}.US"
params = {"api_token": API_TOKEN, "fmt": "json"}
data = requests.get(url, params=params).json()
highlights = data.get("Highlights", {})
return {
"pe_ratio": highlights.get("PERatio"),
"peg_ratio": highlights.get("PEGRatio"),
"profit_margin": highlights.get("ProfitMargin"),
"eps_growth": highlights.get("EPSEstimateNextYear"),
}
Step 3: Check recent price action
Fundamentals tell you if a company is healthy. Price history tells you if the market has already priced that in, or if there's a gap worth paying attention to.
import pandas as pd
from datetime import date, timedelta
def get_price_trend(symbol):
url = f"https://eodhd.com/api/eod/{symbol}.US"
params = {
"api_token": API_TOKEN,
"period": "d",
"order": "d",
"from": (date.today() - timedelta(days=90)).isoformat(),
"fmt": "json",
}
prices = requests.get(url, params=params).json()
df = pd.DataFrame(prices)
last_close = df.iloc[0]["close"]
month_ago_close = df.iloc[21]["close"] if len(df) > 21 else df.iloc[-1]["close"]
change_pct = ((last_close - month_ago_close) / month_ago_close) * 100
return {"last_close": last_close, "change_30d_pct": round(change_pct, 2)}
A stock with strong fundamentals that just dropped 15% in a month is a very different opportunity than one that already ran up 40%.
Step 4: Read the news sentiment
Price and fundamentals don't tell you why a stock moved. Sentiment fills that gap, and it's often what separates a real opportunity from a value trap.
def get_sentiment(symbol):
url = "https://eodhd.com/api/sentiments"
params = {
"s": f"{symbol}.US",
"api_token": API_TOKEN,
"from": (date.today() - timedelta(days=14)).isoformat(),
"fmt": "json",
}
data = requests.get(url, params=params).json()
entries = data.get(f"{symbol}.US", [])
if not entries:
return {"avg_sentiment": None}
avg = sum(e["normalized"] for e in entries) / len(entries)
return {"avg_sentiment": round(avg, 3)}
Step 5: Combine everything into a single score
This is the part a raw API can't do for you. Each endpoint gives you one dimension. Deciding what a "good opportunity" means is a judgment call, and it belongs in your code, not buried in someone else's black-box score.
def score_opportunity(symbol):
fundamentals = get_fundamentals(symbol)
price = get_price_trend(symbol)
sentiment = get_sentiment(symbol)
score = 0
if fundamentals["pe_ratio"] and fundamentals["pe_ratio"] < 25:
score += 1
if fundamentals["profit_margin"] and fundamentals["profit_margin"] > 0.10:
score += 1
if price["change_30d_pct"] < -5:
score += 1
if sentiment["avg_sentiment"] and sentiment["avg_sentiment"] > 0.15:
score += 1
return {
"symbol": symbol,
"score": score,
**fundamentals,
**price,
**sentiment,
}
results = [score_opportunity(t) for t in tickers]
ranked = sorted(results, key=lambda r: r["score"], reverse=True)
for r in ranked[:5]:
print(r["symbol"], "score:", r["score"], "| P/E:", r["pe_ratio"],
"| 30d change:", r["change_30d_pct"], "%",
"| sentiment:", r["avg_sentiment"])
Four data points, one loop, one ranked list. Reasonable valuation, healthy margins, a recent dip, and improving sentiment together are a much stronger signal than any one of them alone.
This scoring logic is intentionally simple. You'll want to weight it differently depending on your strategy: a value investor cares more about P/E and margins, a swing trader cares more about the price drop and sentiment shift. The point is that the four EODHD endpoints give you the raw material, and the decision logic is yours to tune.
None of this is financial advice. It's a framework for turning scattered data into a shortlist worth researching further, not a signal to buy.
Wiring this back into the agent
Once this scoring pipeline works as a standalone script, you can expose it to your MCP agent as a custom tool alongside EODHD's built-in ones. Then a prompt like "find me tech stocks that dropped recently but still look fundamentally solid" runs your exact scoring logic instead of the model guessing at criteria on its own.
That's the real advantage of combining direct API calls with MCP: you get full control over the decision logic, and the model still handles the natural-language layer on top of it.
This is, in practice, what it means to build an AI financial agent: not a single clever prompt, but a data layer you trust plus a model that knows when to reach for it.
From Here You Can Build
Once the agent can combine fundamentals, prices, earnings, and news on its own, the use cases stop being single-question demos.
- pre-earnings screeners that flag weak fundamentals before a reporting date
- sentiment-aware alerts that combine news tone with price moves
- research copilots that answer multi-part questions without a rigid script
None of this requires new wrapper code. It requires better prompts and, occasionally, a narrower system prompt telling the agent which tools to prioritize.
Key Takeaways
- Traditional REST integrations force you to write and maintain orchestration logic for every combination of data types
- MCP moves that orchestration into the model itself, so one conversation can span fundamentals, prices, earnings, and news
- Combining the Screener, fundamentals, price, and sentiment endpoints directly gives you full control over what counts as a "good opportunity," instead of relying on a single metric
- EODHD's MCP server gives you 70+ financial tools without writing a single wrapper function, and you can add your own scoring logic as a custom tool on top of it
FAQs
❓ Do I need to run my own MCP server to use EODHD's tools?
✅ No. EODHD hosts the MCP server, so you connect to it with a URL and your API token, the same way you'd call a REST endpoint.
❓ Does MCP replace the EODHD REST API?
✅ No, it sits on top of it. The REST API still powers every tool call, MCP just gives the AI model a structured way to discover and use those endpoints without custom wrapper code.
❓ Can I limit which tools the agent has access to?
✅ Yes. You can scope the system prompt or restrict the conversation to specific tool categories if you don't want the agent reaching for endpoints outside a given use case, like keeping it to fundamentals and earnings only.
❓ Is this approach only useful with Claude?
✅ No. MCP is an open protocol, so EODHD's server works with any MCP-compatible client, including ChatGPT, Cursor, and Windsurf, not just Claude.
❓ How many API calls does a scan like this use?
✅ It depends on your shortlist size. Each screener request counts as 5 calls, and each fundamentals, price, or sentiment call for a ticker counts as 1. Scanning 20 candidates works out to roughly 65 calls, well within EODHD's free tier for occasional runs.
❓ Can I use this scoring script to automate actual trades?
✅ The script only ranks and prints candidates. Connecting it to a broker's execution API is a separate step, and it's worth adding manual review before any live-money decision, no matter how the shortlist was generated.
If you're a software or API company looking to explain your product through high-quality educational content (not marketing fluff), feel free to connect with me on LinkedIn.
Want more content like this?
Python, APIs, fintech, and AI agent tutorials for developers.
→ Visit kevinmeneses.com
Looking for technical content for your company? I can help — LinkedIn · kevinmenesesgonzalez@gmail.com
Top comments (0)