Skip to main content
Glama

MCP Yahoo Finance

by maxscheijen
MIT License
15
server.py9.49 kB
import json from typing import Any, Literal import pandas as pd from mcp.server import Server from mcp.server.stdio import stdio_server from mcp.types import TextContent, Tool from requests import Session from yfinance import Ticker from mcp_yahoo_finance.utils import generate_tool class YahooFinance: def __init__(self, session: Session | None = None, verify: bool = True) -> None: self.session = session if self.session: self.session.verify = verify def get_current_stock_price(self, symbol: str) -> str: """Get the current stock price based on stock symbol. Args: symbol (str): Stock symbol in Yahoo Finance format. """ stock = Ticker(ticker=symbol, session=self.session).info current_price = stock.get( "regularMarketPrice", stock.get("currentPrice", "N/A") ) return ( f"{current_price:.4f}" if current_price else f"Couldn't fetch {symbol} current price" ) def get_stock_price_by_date(self, symbol: str, date: str) -> str: """Get the stock price for a given stock symbol on a specific date. Args: symbol (str): Stock symbol in Yahoo Finance format. date (str): The date in YYYY-MM-DD format. """ stock = Ticker(ticker=symbol, session=self.session) price = stock.history(start=date, period="1d") return f"{price.iloc[0]['Close']:.4f}" def get_stock_price_date_range( self, symbol: str, start_date: str, end_date: str ) -> str: """Get the stock prices for a given date range for a given stock symbol. Args: symbol (str): Stock symbol in Yahoo Finance format. start_date (str): The start date in YYYY-MM-DD format. end_date (str): The end date in YYYY-MM-DD format. """ stock = Ticker(ticker=symbol, session=self.session) prices = stock.history(start=start_date, end=end_date) prices.index = prices.index.astype(str) return f"{prices['Close'].to_json(orient='index')}" def get_historical_stock_prices( self, symbol: str, period: Literal[ "1d", "5d", "1mo", "3mo", "6mo", "1y", "2y", "5y", "10y", "ytd", "max" ] = "1mo", interval: Literal["1d", "5d", "1wk", "1mo", "3mo"] = "1d", ) -> str: """Get historical stock prices for a given stock symbol. Args: symbol (str): Stock symbol in Yahoo Finance format. period (str): The period for historical data. Defaults to "1mo". Valid periods: "1d", "5d", "1mo", "3mo", "6mo", "1y", "2y", "5y", "10y", "ytd", "max" interval (str): The interval beween data points. Defaults to "1d". Valid intervals: "1d", "5d", "1wk", "1mo", "3mo" """ stock = Ticker(ticker=symbol, session=self.session) prices = stock.history(period=period, interval=interval) if hasattr(prices.index, "date"): prices.index = prices.index.date.astype(str) # type: ignore return f"{prices['Close'].to_json(orient='index')}" def get_dividends(self, symbol: str) -> str: """Get dividends for a given stock symbol. Args: symbol (str): Stock symbol in Yahoo Finance format. """ stock = Ticker(ticker=symbol, session=self.session) dividends = stock.dividends if hasattr(dividends.index, "date"): dividends.index = dividends.index.date.astype(str) # type: ignore return f"{dividends.to_json(orient='index')}" def get_income_statement( self, symbol: str, freq: Literal["yearly", "quarterly", "trainling"] = "yearly" ) -> str: """Get income statement for a given stock symbol. Args: symbol (str): Stock symbol in Yahoo Finance format. freq (str): At what frequency to get cashflow statements. Defaults to "yearly". Valid freqencies: "yearly", "quarterly", "trainling" """ stock = Ticker(ticker=symbol, session=self.session) income_statement = stock.get_income_stmt(freq=freq, pretty=True) if isinstance(income_statement, pd.DataFrame): income_statement.columns = [ str(col.date()) for col in income_statement.columns ] return f"{income_statement.to_json()}" return f"{income_statement}" def get_cashflow( self, symbol: str, freq: Literal["yearly", "quarterly", "trainling"] = "yearly" ): """Get cashflow for a given stock symbol. Args: symbol (str): Stock symbol in Yahoo Finance format. freq (str): At what frequency to get cashflow statements. Defaults to "yearly". Valid freqencies: "yearly", "quarterly", "trainling" """ stock = Ticker(ticker=symbol, session=self.session) cashflow = stock.get_cashflow(freq=freq, pretty=True) if isinstance(cashflow, pd.DataFrame): cashflow.columns = [str(col.date()) for col in cashflow.columns] return f"{cashflow.to_json(indent=2)}" return f"{cashflow}" def get_earning_dates(self, symbol: str, limit: int = 12) -> str: """Get earning dates. Args: symbol (str): Stock symbol in Yahoo Finance format. limit (int): max amount of upcoming and recent earnings dates to return. Default value 12 should return next 4 quarters and last 8 quarters. Increase if more history is needed. """ stock = Ticker(ticker=symbol, session=self.session) earning_dates = stock.get_earnings_dates(limit=limit) if isinstance(earning_dates, pd.DataFrame): earning_dates.index = earning_dates.index.date.astype(str) # type: ignore return f"{earning_dates.to_json(indent=2)}" return f"{earning_dates}" def get_news(self, symbol: str) -> str: """Get news for a given stock symbol. Args: symbol (str): Stock symbol in Yahoo Finance format. """ stock = Ticker(ticker=symbol, session=self.session) return json.dumps(stock.news, indent=2) def get_recommendations(self, symbol: str) -> str: """Get analyst recommendations for a given symbol. Args: symbol (str): Stock symbol in Yahoo Finance format. """ stock = Ticker(ticker=symbol, session=self.session) recommendations = stock.get_recommendations() print(recommendations) if isinstance(recommendations, pd.DataFrame): return f"{recommendations.to_json(orient='records', indent=2)}" return f"{recommendations}" async def serve() -> None: server = Server("mcp-yahoo-finance") yf = YahooFinance() @server.list_tools() async def list_tools() -> list[Tool]: return [ generate_tool(yf.get_current_stock_price), generate_tool(yf.get_stock_price_by_date), generate_tool(yf.get_stock_price_date_range), generate_tool(yf.get_historical_stock_prices), generate_tool(yf.get_dividends), generate_tool(yf.get_income_statement), generate_tool(yf.get_cashflow), generate_tool(yf.get_earning_dates), generate_tool(yf.get_news), generate_tool(yf.get_recommendations), ] @server.call_tool() async def call_tool(name: str, args: dict[str, Any]) -> list[TextContent]: match name: case "get_current_stock_price": price = yf.get_current_stock_price(**args) return [TextContent(type="text", text=price)] case "get_stock_price_by_date": price = yf.get_stock_price_by_date(**args) return [TextContent(type="text", text=price)] case "get_stock_price_date_range": price = yf.get_stock_price_date_range(**args) return [TextContent(type="text", text=price)] case "get_historical_stock_prices": price = yf.get_historical_stock_prices(**args) return [TextContent(type="text", text=price)] case "get_dividends": price = yf.get_dividends(**args) return [TextContent(type="text", text=price)] case "get_income_statement": price = yf.get_income_statement(**args) return [TextContent(type="text", text=price)] case "get_cashflow": price = yf.get_cashflow(**args) return [TextContent(type="text", text=price)] case "get_earning_dates": price = yf.get_earning_dates(**args) return [TextContent(type="text", text=price)] case "get_news": price = yf.get_news(**args) return [TextContent(type="text", text=price)] case "get_recommendations": recommendations = yf.get_recommendations(**args) return [TextContent(type="text", text=recommendations)] case _: raise ValueError(f"Unknown tool: {name}") options = server.create_initialization_options() async with stdio_server() as (read_stream, write_stream): await server.run(read_stream, write_stream, options, raise_exceptions=True)

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/maxscheijen/mcp-yahoo-finance'

If you have feedback or need assistance with the MCP directory API, please join our Discord server