The Model Context Protocol (MCP) sets one standard for connecting tools, files, and databases to LLM agents. This works for both local and remote sources. When we wrap a data source into an MCP server, any agent framework can discover and call it on the fly.
In this blog, we build a stock analysis assistant. It uses the Yahoo Finance MCP server to fetch stock quotes, historical actions, recommendations, and recent news.
Implementing the Yahoo Finance MCP Module
Create the background connector module scripts/yahoo_mcp.py to launch the server and bind its tools:
import warnings
warnings.filterwarnings("ignore")
import os
import sys
import asyncio
# Enforce UTF-8 encoding for Windows terminal consoles
if sys.platform == "win32":
sys.stdout.reconfigure(encoding="utf-8")
from dotenv import load_dotenv
from langchain_core.messages import HumanMessage
from langchain.agents import create_agent
from langchain_google_genai import ChatGoogleGenerativeAI
from langchain_mcp_adapters.client import MultiServerMCPClient
load_dotenv()
llm = ChatGoogleGenerativeAI(model="gemini-2.5-flash")
system_prompt = """
You are a financial research assistant helping users analyze stocks and financial data using Yahoo Finance.
Available Tools:
- get_historical_stock_prices: Get historical stock prices (ticker required)
- get_stock_info: Get comprehensive stock info (price, metrics, valuation)
- get_yahoo_finance_news: Get recent news articles for a stock
- get_stock_actions: Get dividends and stock splits history
- get_financial_statement: Get income statements or balance sheets
- get_holder_info: Get major/institutional holder data
- get_option_expiration_dates: Get options expiration dates
- get_option_chain: Get option chain pricing data
- get_recommendations: Get analyst buy/sell/hold consensus
Instructions:
1. ALWAYS use the relevant tool to fetch stock metrics before attempting to answer a stock-specific query.
2. Formulate concise, structured summaries citing exact dollar values and percentages.
"""
async def get_tools():
# Launches the yahoo-finance-mcp-server via uvx stdio transport
client = MultiServerMCPClient(
{
"yahoo-finance": {
"command": "uvx",
"args": ["yahoo-finance-mcp-server"],
"transport": "stdio",
}
}
)
tools = await client.get_tools()
return tools
async def finance_research(query):
tools = await get_tools()
agent = create_agent(model=llm, tools=tools, system_prompt=system_prompt)
result = await agent.ainvoke({"messages": [HumanMessage(query)]})
response = result["messages"][-1].text
return response
Verify that the background subprocess correctly launches and queries the server:
query = "What is the current stock price and recent performance of Apple (AAPL)? Also show me the latest news."
response = asyncio.run(finance_research(query))
print(response)
Loaded 9 tools
Tools available: ['get_historical_stock_prices', 'get_stock_info', 'get_yahoo_finance_news', 'get_stock_actions', 'get_financial_statement', 'get_holder_info', 'get_option_expiration_dates', 'get_option_chain', 'get_recommendations']
Apple (AAPL) Current Price: $278.78 (up +$1.60/+0.58% today).
Performance (last month): Started at $275.25 on Nov 11, traded between $266.25 and $286.19, closing at $278.78 (+1.28%).
Here, we can see 9 tools load and the agent return Apple's live price and a short performance summary.
The Stock Researcher Agent
Create a custom @tool that launches the script subprocess and returns stdout directly to our main agent:

import subprocess
import sys
from langchain_core.tools import tool
@tool
def finance_researcher(query: str) -> str:
"""Research stocks using the Yahoo Finance MCP async function.
Call this tool whenever you need to answer finance or stock-related questions.
"""
code = f"""
import asyncio
from scripts.yahoo_mcp import finance_research
asyncio.run(finance_research("{query}"))
"""
result = subprocess.run([sys.executable, '-c', code], capture_output=True, text=True)
return result.stdout
Define the system constraints and system prompt to keep the agent in its lane. This stops it from answering general-knowledge queries outside stock analysis:
system_prompt = """You are a professional stock research analyst specializing in financial analysis.
**Your Responsibilities:**
1. Analyze stock performance and financial metrics
2. Research company fundamentals
3. Provide data-driven investment recommendations
4. You must use available tools to answer user queries
**Analysis Framework:**
- Company name and ticker symbol
- Current stock price
- Key metrics: P/E ratio, Market Cap, Revenue
- Financial health assessment
- Clear recommendation: Buy, Hold, or Sell
**Important Guidelines:**
- Only respond to finance and stock market related questions
- For non-finance questions, politely decline: "I apologize, but I can only assist with stock market and financial analysis questions. Please ask me about stocks, companies, or financial metrics."
- Always cite specific data and metrics
- Maintain professional and objective tone
Provide concise, actionable insights for investors."""
Compile the agent with task-planning middleware (TodoListMiddleware):
from langchain.agents.middleware import TodoListMiddleware
model = ChatGoogleGenerativeAI(model='gemini-2.5-flash')
agent = create_agent(
model=model,
tools=[finance_researcher],
system_prompt=system_prompt,
middleware=[TodoListMiddleware()]
)
Verifying Domain Safeguards and Planning Execution
Let's verify that the agent politely refuses general-knowledge questions outside finance:
response = agent.invoke({'messages': [HumanMessage('what is the weather in mumbai?')]})
print(response['messages'][-1].text)
I apologize, but I can only assist with stock market and financial analysis questions. Please ask me about stocks, companies, or financial metrics.
Execute a financial comparison query:
query = "Analyze Apple (AAPL) stock and its competitors like MSFT and Google. Present data clearly in a table."
response = agent.invoke({'messages': [HumanMessage(query)]})
Here, we can see the agent break the instructions into a set of steps:
write_todos arguments:
{
"todos": [
{"status": "in_progress", "content": "Research Apple (AAPL) stock performance."},
{"status": "pending", "content": "Research Microsoft (MSFT) stock performance."},
{"status": "pending", "content": "Research Google (GOOGL) stock performance."},
{"status": "pending", "content": "Compile comparison metrics into a markdown table."}
]
}
The final answer compiles the structured data returned by finance_researcher:
| Ticker | Price | Market Cap | P/E Ratio | Recommendation |
|---|---|---|---|---|
| AAPL | 4.18T | 42.96 | Moderate Buy | |
| MSFT | 3.65T | 35.40 | Buy | |
| GOOGL | 2.26T | 26.80 | Buy |
This is how an MCP stock researcher agent works. We launched the Yahoo Finance MCP server over stdio and wrapped it as a tool. Then we added a todo planner and domain guardrails. Now the agent fetches live data and answers only finance questions.