Building MCP Servers Like a Pro (With a Little Help from yfinance and LLMs)
If you've been in the AI space for a minute, you've likely noticed the growing interest in hooking Large Language Models (LLMs) up to real-world data and services. That's where the Model Context Protocol (MCP) steps in. Think of MCP as a standardized "plug" that lets AI models talk to APIs, file systems, and more—all without you having to do a ton of custom integration work each time. In this post, we'll walk through what MCP is and how to create a practical MCP server that integrates with the yfinance library for real-time stock data. Along the way, we'll also see how LLMs can speed up the development process.
Part 1: Getting Familiar with MCP
What Is MCP?
The Model Context Protocol (MCP) is a way for applications to reliably pass data, prompts, and tool instructions to LLMs. You can think of it as a universal interface for hooking an LLM into various data sources—like hooking up your phone to different devices via USB-C. It aims to:
- Provide a standardized communication layer between LLMs and the outside world
- Enforce security and permissions out of the box
- Encourage reuse across different LLM platforms
- Keep data retrieval and model prompting nicely separated
MCP Basics
MCP servers expose three main asset types:
- Resources – These are read-only data sources such as file contents or API endpoints.
- Tools – These are callable functions you might want the LLM to execute (with user permission).
- Prompts – Pre-crafted text templates that the LLM can use for specific tasks or contexts.
Part 2: Spinning Up a yfinance MCP Server
Let's jump into a concrete example and build an MCP server that gives LLMs access to real-time financial data. We'll use yfinance to fetch market information, so an LLM can perform data-driven analysis on stocks.
Environment Setup
First, create a project folder and install dependencies:
# Initialize a new project and create a virtual environment
uv init yfinance-mcp
cd yfinance-mcp
uv venv
source .venv/bin/activate # or .venv\Scripts\activate on Windows
# Install required packages
uv add "mcp[cli]" yfinance pandas
Core Server Code
Here's a straightforward MCP server using FastMCP. It defines two MCP tools to retrieve stock info and historical data, plus one prompt for a guided stock analysis. Drop this into server.py:
from mcp.server.fastmcp import FastMCP
import yfinance as yf
import pandas as pd
from typing import Optional, Dict, Any
# Initialize FastMCP server
mcp = FastMCP("yfinance-mcp")
@mcp.tool()
def get_stock_info(symbol: str) -> str:
"""Get detailed information about a stock.
Args:
symbol: Stock ticker symbol (e.g., AAPL, GOOGL)
"""
try:
ticker = yf.Ticker(symbol)
info = ticker.info
return {
"name": info.get("longName"),
"sector": info.get("sector"),
"industry": info.get("industry"),
"market_cap": info.get("marketCap"),
"current_price": info.get("currentPrice"),
}
except Exception as e:
return f"Error fetching stock info: {str(e)}"
@mcp.tool()
def get_historical_data(symbol: str, period: str = "1mo") -> str:
"""Get historical price data for a stock.
Args:
symbol: Stock ticker symbol
period: Time period (1d, 5d, 1mo, 3mo, etc.)
"""
try:
ticker = yf.Ticker(symbol)
hist = ticker.history(period=period)
return hist.to_string()
except Exception as e:
return f"Error fetching historical data: {str(e)}"
@mcp.prompt()
def analyze_stock(symbol: str) -> str:
"""Create a comprehensive stock analysis prompt."""
return f"""Please analyze this stock:
Symbol: {symbol}
1. Basic Information:
{{{{ get_stock_info(symbol="{symbol}") }}}}
2. Recent Performance:
{{{{ get_historical_data(symbol="{symbol}", period="1mo") }}}}
Please provide:
1. Key insights about the company
2. Recent performance analysis
3. Notable trends or patterns
"""
if __name__ == "__main__":
mcp.run()
That's it! Fire up this server and your LLM can call it to retrieve stock data, or use the "Analyze Stock" prompt to generate a deeper analysis.
Part 3: Speeding Up Development with LLMs
Now, let's talk about one of the real superpowers here: letting LLMs help you build these servers. If you've used something like ChatGPT or Claude for coding, you know it can significantly speed up prototyping and testing.
1. Prep Work
Before you drag an LLM into your dev loop:
- Round up the right docs: MCP specs, your API references, your language SDK docs—whatever you'll need to answer the LLM's questions.
- Write a clear project spec: What capabilities do you need in your server? Which external services should it tap into? Any constraints or requirements?
2. Developing with an LLM
Here's a typical approach:
- Design Discussion
- Provide the LLM with your specs and key documentation.
- Ask for a proposed architecture or any caveats it might see.
- Implementation
- Work in chunks. Have the LLM generate a piece of the code, then discuss or refine it.
- Get the LLM to explain non-trivial parts or incorporate best practices.
- Use the LLM to scaffold your testing strategy.
- Refinement
- Ask for performance optimizations or design tweaks.
- Consult it for security and error handling suggestions.
3. Best Practices
- Break down big features into bite-sized tasks.
- Ask the LLM to clarify or document the trickier sections of code.
- Let it review your code to spot potential issues or style improvements.
Part 4: Testing and Deploying
Testing with MCP Inspector
You can do interactive testing of your server using the MCP Inspector:
mcp dev server.py
Hooking into Claude Desktop
If you're using Claude Desktop, just add your MCP server configuration in its JSON setup:
{
"mcpServers": {
"yfinance": {
"command": "python",
"args": ["path/to/server.py"]
}
}
}
Security Pitfalls to Avoid
- Validate inputs to make sure you're not accepting random or malicious data.
- Rate-limit calls if you're dealing with APIs that charge per request.
- Protect credentials—don't store secrets in plain text on GitHub.
- Monitor resource usage to prevent abuse.
- Be robust with error handling and logging.
Wrapping Up
MCP servers are a powerful way to feed LLMs the data and tools they need—without reinventing the wheel for every new integration. By combining MCP's straightforward structure with LLM-assisted development, you can move faster and ship more reliable integrations.
Here are the key points to remember:
- MCP is a unifying protocol for hooking up LLMs to external data sources.
- LLMs can dramatically speed up building and testing your MCP servers.
- Security and robust error handling matter—especially when you're working with production systems.
- The MCP ecosystem is growing quickly, so keep an eye out for new best practices and prebuilt integrations.
Our yfinance-based server is just a small peek at what's possible. If you're looking to build out other functionalities—say hooking into custom databases or enterprise APIs—the same basic approach applies. Happy coding!