Skip to main content
Glama

Yahoo Finance MCP Server

by 16Coffee
MIT License
  • Apple
server.py40.5 kB
import json import os from dotenv import load_dotenv load_dotenv() from enum import Enum import pandas as pd import requests from mcp.server.fastmcp import FastMCP # Define an enum for the type of financial statement class FinancialType(str, Enum): income_stmt_annual = "income_stmt_annual" income_stmt_quarterly = "income_stmt_quarterly" balance_sheet_annual = "balance_sheet_annual" balance_sheet_quarterly = "balance_sheet_quarterly" cashflow_annual = "cashflow_annual" cashflow_quarterly = "cashflow_quarterly" # Initialize FastMCP server fmp_server = FastMCP( "financialmodelingprep", instructions=""" # Financial Modeling Prep MCP Server 本服务器通过 Financial Modeling Prep API 提供股票与财务数据。 使用这些工具前,请将环境变量 `FMP_API_KEY` 设置为你的 API 密钥。 可用工具: - get_historical_stock_prices:获取指定股票的历史价格。 - get_stock_info:获取公司概况和关键指标。 - get_news_sentiment:获取股票相关新闻。 - get_stock_actions:获取股票分红与拆股记录。 - get_financial_statement:获取公司财报(收入表、资产负债表、现金流量表)。 - get_option_expiration_dates:获取股票可用的期权到期日。 - get_option_chain:获取期权链数据。 - search_companies:根据关键字搜索公司。 - get_top_gainers:获取今日涨幅榜。 - get_top_losers:获取今日跌幅榜。 - get_stock_grades:获取分析师最新评级。 - get_stock_grades_historical:获取分析师评级历史记录。 - get_stock_grades_summary:获取分析师评级汇总。 - get_stock_grade_news:获取指定股票的评级新闻。 - get_stock_grade_latest_news:获取最新评级新闻。 """, ) @fmp_server.tool( name="get_historical_stock_prices", description="""获取指定股票的历史价格,返回日期、开盘价、最高价、最低价、收盘价和成交量。 参数说明: ticker: str 股票代码,例如 "AAPL" period : str 支持的周期:1d,5d,1mo,3mo,6mo,1y,2y,5y,10y,ytd,max; 也可以使用开始和结束日期;默认 "1mo" interval : str 支持的间隔:1m,2m,5m,15m,30m,60m,90m,1h,1d,5d,1wk,1mo,3mo; 分钟级数据最多可追溯60天;默认 "1d" """, ) async def get_historical_stock_prices( ticker: str, period: str = "1mo", interval: str = "1d" ) -> str: """Get historical stock prices for a given ticker symbol""" api_key = os.environ.get("FMP_API_KEY") if not api_key: return "Error: FMP_API_KEY environment variable not set." base = "https://financialmodelingprep.com/api/v3" try: if interval in ["1min", "5min", "15min", "30min", "1hour", "4hour"]: url = f"{base}/historical-chart/{interval}/{ticker}" resp = requests.get(url, params={"apikey": api_key}, timeout=10) resp.raise_for_status() data = resp.json() else: url = f"{base}/historical-price-full/{ticker}" resp = requests.get(url, params={"apikey": api_key}, timeout=10) resp.raise_for_status() data = resp.json().get("historical", []) except Exception as e: return f"Error: getting historical stock prices for {ticker}: {e}" df = pd.DataFrame(data) if not df.empty: if "date" in df.columns: df.rename(columns={"date": "Date"}, inplace=True) df = df[["Date", "open", "high", "low", "close", "volume"]] df.columns = [c.title() for c in df.columns] # Convert the Date column to datetime for proper comparison df["Date"] = pd.to_datetime(df["Date"]) period_map = { "1d": pd.Timedelta(days=1), "5d": pd.Timedelta(days=5), "1mo": pd.Timedelta(days=30), "3mo": pd.Timedelta(days=90), "6mo": pd.Timedelta(days=180), "1y": pd.Timedelta(days=365), "2y": pd.Timedelta(days=730), "5y": pd.Timedelta(days=1825), "10y": pd.Timedelta(days=3650), } if period == "ytd": start = pd.Timestamp.now().replace(month=1, day=1) elif period != "max" and period in period_map: start = pd.Timestamp.now() - period_map[period] else: start = None if start is not None and not df.empty: df = df[df["Date"] >= start] return df.to_json(orient="records", date_format="iso") @fmp_server.tool( name="get_stock_info", description="""获取公司概况及关键财务指标。 参数说明: ticker: str 股票代码,例如 "AAPL" """, ) async def get_stock_info(ticker: str) -> str: """Get stock information for a given ticker symbol""" api_key = os.environ.get("FMP_API_KEY") if not api_key: return "Error: FMP_API_KEY environment variable not set." url = f"https://financialmodelingprep.com/api/v3/profile/{ticker}" try: resp = requests.get(url, params={"apikey": api_key}, timeout=10) resp.raise_for_status() data = resp.json() except Exception as e: return f"Error: getting stock information for {ticker}: {e}" return json.dumps(data[0] if isinstance(data, list) and data else data) @fmp_server.tool( name="get_news_sentiment", description="""获取指定股票的相关新闻列表。 参数说明: ticker: str 股票代码,例如 "AAPL" """, ) async def get_news_sentiment(ticker: str) -> str: """Get news for a given ticker symbol""" api_key = os.environ.get("FMP_API_KEY") if not api_key: return "Error: FMP_API_KEY environment variable not set." url = "https://financialmodelingprep.com/api/v4/general_news" try: resp = requests.get( url, params={"tickers": ticker, "page": 0, "size": 50, "apikey": api_key}, timeout=10 ) resp.raise_for_status() data = resp.json() except Exception as e: return f"Error: getting news for {ticker}: {e}" news_list = [] for item in data: title = item.get("title", "") summary = item.get("text", "") link = item.get("url", "") news_list.append(f"Title: {title}\nSummary: {summary}\nURL: {link}") if not news_list: return f"No news found for {ticker}" return "\n\n".join(news_list) @fmp_server.tool( name="get_stock_actions", description="""获取股票的分红与拆股历史。 参数说明: ticker: str 股票代码,例如 "AAPL" """, ) async def get_stock_actions(ticker: str) -> str: """Get stock dividends and stock splits for a given ticker symbol""" api_key = os.environ.get("FMP_API_KEY") if not api_key: return "Error: FMP_API_KEY environment variable not set." base = "https://financialmodelingprep.com/api/v3" try: div_resp = requests.get( f"{base}/historical-price-full/stock_dividend/{ticker}", params={"apikey": api_key}, timeout=10, ) div_resp.raise_for_status() div_df = pd.DataFrame(div_resp.json().get("historical", [])) split_resp = requests.get( f"{base}/historical-price-full/stock_split/{ticker}", params={"apikey": api_key}, timeout=10, ) split_resp.raise_for_status() split_df = pd.DataFrame(split_resp.json().get("historical", [])) except Exception as e: return f"Error: getting stock actions for {ticker}: {e}" return json.dumps( { "dividends": div_df.to_dict("records"), "splits": split_df.to_dict("records"), } ) @fmp_server.tool( name="get_financial_statement", description="""获取公司财报,类型包括年度/季度的收入表、资产负债表和现金流量表。 参数说明: ticker: str 股票代码,例如 "AAPL" financial_type: str 财报类型:income_stmt_annual、income_stmt_quarterly、balance_sheet_annual、balance_sheet_quarterly、cashflow_annual、cashflow_quarterly """, ) async def get_financial_statement(ticker: str, financial_type: str) -> str: """Get financial statement for a given ticker symbol""" api_key = os.environ.get("FMP_API_KEY") if not api_key: return "Error: FMP_API_KEY environment variable not set." base = "https://financialmodelingprep.com/api/v3" period = "annual" if financial_type in [ FinancialType.income_stmt_quarterly, FinancialType.balance_sheet_quarterly, FinancialType.cashflow_quarterly, ]: period = "quarter" endpoint_map = { FinancialType.income_stmt_annual: "income-statement", FinancialType.income_stmt_quarterly: "income-statement", FinancialType.balance_sheet_annual: "balance-sheet-statement", FinancialType.balance_sheet_quarterly: "balance-sheet-statement", FinancialType.cashflow_annual: "cash-flow-statement", FinancialType.cashflow_quarterly: "cash-flow-statement", } endpoint = endpoint_map.get(FinancialType(financial_type)) if not endpoint: return "Error: invalid financial type" url = f"{base}/{endpoint}/{ticker}" try: resp = requests.get(url, params={"period": period, "apikey": api_key}, timeout=10) resp.raise_for_status() data = resp.json() except Exception as e: return f"Error: getting financial statement for {ticker}: {e}" return json.dumps(data) @fmp_server.tool( name="get_calendar_data", description="""获取分红、收益、IPO、拆股等日历信息。 参数说明: event_type: str 可选值:dividends、dividends_calendar、earnings、earnings_calendar、 ipos_calendar、ipos_disclosure、ipos_prospectus、splits、splits_calendar symbol: str 部分类型需要股票代码 page: int 页码,默认 0 limit: int 返回数量,默认 100""", ) async def get_calendar_data( event_type: str, symbol: str = "", page: int = 0, limit: int = 100, ) -> str: """根据事件类型获取相关日历数据""" api_key = os.environ.get("FMP_API_KEY") if not api_key: return "Error: FMP_API_KEY environment variable not set." base = "https://financialmodelingprep.com/stable" endpoint_map = { "dividends": "dividends", "dividends_calendar": "dividends-calendar", "earnings": "earnings", "earnings_calendar": "earnings-calendar", "ipos_calendar": "ipos-calendar", "ipos_disclosure": "ipos-disclosure", "ipos_prospectus": "ipos-prospectus", "splits": "splits", "splits_calendar": "splits-calendar", } endpoint = endpoint_map.get(event_type.lower()) if not endpoint: return "Error: invalid event type" params = {"apikey": api_key} if event_type in ["dividends", "earnings", "splits"] and not symbol: return "Error: symbol is required for this event type" if symbol: params["symbol"] = symbol if event_type in ["ipos_calendar", "ipos_disclosure", "ipos_prospectus"]: params.update({"page": page, "limit": limit}) url = f"{base}/{endpoint}" try: resp = requests.get(url, params=params, timeout=10) resp.raise_for_status() data = resp.json() except Exception as e: return f"Error: getting calendar data {event_type}: {e}" return json.dumps(data) @fmp_server.tool( name="get_shares_float_info", description="""获取流通股数据或全部公司流通股列表。 参数说明: info_type: str single 或 all symbol: str 查询单个公司时必填 page: int 列表分页,默认 0 limit: int 返回数量,默认 1000""", ) async def get_shares_float_info( info_type: str, symbol: str = "", page: int = 0, limit: int = 1000, ) -> str: """获取流通股信息""" api_key = os.environ.get("FMP_API_KEY") if not api_key: return "Error: FMP_API_KEY environment variable not set." base = "https://financialmodelingprep.com/stable" endpoint_map = { "single": "shares-float", "all": "shares-float-all", } endpoint = endpoint_map.get(info_type.lower()) if not endpoint: return "Error: invalid info type" params = {"apikey": api_key} if info_type == "single": if not symbol: return "Error: symbol is required for single type" params["symbol"] = symbol else: params.update({"page": page, "limit": limit}) url = f"{base}/{endpoint}" try: resp = requests.get(url, params=params, timeout=10) resp.raise_for_status() data = resp.json() except Exception as e: return f"Error: getting shares float info {info_type}: {e}" return json.dumps(data) @fmp_server.tool( name="get_ma_data", description="""获取并购相关数据。 参数说明: action_type: str latest 或 search name: str 搜索模式下的公司名称 page: int 页码,默认 0 limit: int 返回数量,默认 100""", ) async def get_ma_data( action_type: str, name: str = "", page: int = 0, limit: int = 100, ) -> str: """获取并购信息""" api_key = os.environ.get("FMP_API_KEY") if not api_key: return "Error: FMP_API_KEY environment variable not set." base = "https://financialmodelingprep.com/stable" endpoint_map = { "latest": "mergers-acquisitions-latest", "search": "mergers-acquisitions-search", } endpoint = endpoint_map.get(action_type.lower()) if not endpoint: return "Error: invalid action type" params = {"apikey": api_key, "page": page, "limit": limit} if action_type == "search": if not name: return "Error: name is required for search" params["name"] = name url = f"{base}/{endpoint}" try: resp = requests.get(url, params=params, timeout=10) resp.raise_for_status() data = resp.json() except Exception as e: return f"Error: getting M&A data {action_type}: {e}" return json.dumps(data) @fmp_server.tool( name="get_executive_info", description="""获取公司高管信息或薪酬数据。 参数说明: info_type: str executives、compensation 或 benchmark symbol: str 当类型为 executives 或 compensation 时必填""", ) async def get_executive_info(info_type: str, symbol: str = "") -> str: """获取公司高管或薪酬相关数据""" api_key = os.environ.get("FMP_API_KEY") if not api_key: return "Error: FMP_API_KEY environment variable not set." base = "https://financialmodelingprep.com/stable" endpoint_map = { "executives": "key-executives", "compensation": "governance-executive-compensation", "benchmark": "executive-compensation-benchmark", } endpoint = endpoint_map.get(info_type.lower()) if not endpoint: return "Error: invalid info type" params = {"apikey": api_key} if info_type in ["executives", "compensation"]: if not symbol: return "Error: symbol is required for this info type" params["symbol"] = symbol url = f"{base}/{endpoint}" try: resp = requests.get(url, params=params, timeout=10) resp.raise_for_status() data = resp.json() except Exception as e: return f"Error: getting executive info {info_type} for {symbol}: {e}" return json.dumps(data) @fmp_server.tool( name="get_dcf_valuation", description="""获取 DCF 或杠杆 DCF 估值数据。 参数说明: valuation_type: str dcf 或 levered symbol: str 股票代码""", ) async def get_dcf_valuation(valuation_type: str, symbol: str) -> str: """根据类型获取 DCF 估值""" api_key = os.environ.get("FMP_API_KEY") if not api_key: return "Error: FMP_API_KEY environment variable not set." base = "https://financialmodelingprep.com/stable" endpoint_map = { "dcf": "discounted-cash-flow", "levered": "levered-discounted-cash-flow", } endpoint = endpoint_map.get(valuation_type.lower()) if not endpoint: return "Error: invalid valuation type" url = f"{base}/{endpoint}" try: resp = requests.get(url, params={"symbol": symbol, "apikey": api_key}, timeout=10) resp.raise_for_status() data = resp.json() except Exception as e: return f"Error: getting {valuation_type} DCF for {symbol}: {e}" return json.dumps(data) @fmp_server.tool( name="get_economic_data", description="""获取宏观经济数据。 参数说明: data_type: str treasury_rates、economic_indicators、economic_calendar、market_risk_premium name: str 经济指标名称,data_type 为 economic_indicators 时必填 from_date: str 起始日期,格式 YYYY-MM-DD to_date: str 结束日期,格式 YYYY-MM-DD""", ) async def get_economic_data( data_type: str, name: str = "", from_date: str = "", to_date: str = "", ) -> str: """根据类型获取经济数据""" api_key = os.environ.get("FMP_API_KEY") if not api_key: return "Error: FMP_API_KEY environment variable not set." base = "https://financialmodelingprep.com/stable" endpoint_map = { "treasury_rates": "treasury-rates", "economic_indicators": "economic-indicators", "economic_calendar": "economic-calendar", "market_risk_premium": "market-risk-premium", } endpoint = endpoint_map.get(data_type.lower()) if not endpoint: return "Error: invalid data type" params = {"apikey": api_key} if data_type == "economic_indicators": if not name: return "Error: name is required for economic_indicators" params["name"] = name if from_date and to_date: params.update({"from": from_date, "to": to_date}) url = f"{base}/{endpoint}" try: resp = requests.get(url, params=params, timeout=10) resp.raise_for_status() data = resp.json() except Exception as e: return f"Error: getting economic data {data_type}: {e}" return json.dumps(data) @fmp_server.tool( name="get_option_expiration_dates", description="""获取指定股票可用的期权到期日。 参数说明: ticker: str 股票代码,例如 "AAPL" """, ) async def get_option_expiration_dates(ticker: str) -> str: """Fetch the available options expiration dates for a given ticker symbol.""" api_key = os.environ.get("FMP_API_KEY") if not api_key: return "Error: FMP_API_KEY environment variable not set." base = "https://financialmodelingprep.com/api/v3" try: resp = requests.get( f"{base}/options/available-expirations/{ticker}", params={"apikey": api_key}, timeout=10 ) resp.raise_for_status() data = resp.json() except Exception as e: return f"Error: getting option expiration dates for {ticker}: {e}" expirations = data if isinstance(data, list) else data.get("expirations", []) return json.dumps(sorted(expirations)) @fmp_server.tool( name="get_option_chain", description="""根据股票代码、到期日和期权类型获取期权链数据。 参数说明: ticker: str 股票代码,例如 "AAPL" expiration_date: str 期权到期日,格式为 'YYYY-MM-DD' option_type: str 期权类型:'calls' 或 'puts' """, ) async def get_option_chain(ticker: str, expiration_date: str, option_type: str) -> str: """Fetch the option chain for a given ticker symbol, expiration date, and option type.""" api_key = os.environ.get("FMP_API_KEY") if not api_key: return "Error: FMP_API_KEY environment variable not set." base = "https://financialmodelingprep.com/api/v3" try: resp = requests.get( f"{base}/options/chain/{ticker}", params={"expiration": expiration_date, "apikey": api_key}, timeout=10, ) resp.raise_for_status() data = resp.json() except Exception as e: return f"Error: getting option chain for {ticker}: {e}" filtered = [ item for item in data if item.get("expirationDate") == expiration_date and item.get("optionType", "").lower() == option_type.lower() ] return json.dumps(filtered) @fmp_server.tool( name="search_companies", description="""根据关键字搜索公司信息。 参数说明: query: str 搜索关键字 limit: int 返回结果数量,默认 10 exchange: str 交易所代码,可选 """, ) async def search_companies(query: str, limit: int = 10, exchange: str = "") -> str: """根据关键字搜索公司""" api_key = os.environ.get("FMP_API_KEY") if not api_key: return "Error: FMP_API_KEY environment variable not set." params = {"query": query, "limit": limit, "apikey": api_key} if exchange: params["exchange"] = exchange url = "https://financialmodelingprep.com/api/v3/search" try: resp = requests.get(url, params=params, timeout=10) resp.raise_for_status() data = resp.json() except Exception as e: return f"Error: searching companies: {e}" return json.dumps(data) @fmp_server.tool( name="get_top_gainers", description="""获取今日涨幅最大的股票列表。""", ) async def get_top_gainers() -> str: """获取今日涨幅榜""" api_key = os.environ.get("FMP_API_KEY") if not api_key: return "Error: FMP_API_KEY environment variable not set." url = "https://financialmodelingprep.com/api/v3/stock_market/gainers" try: resp = requests.get(url, params={"apikey": api_key}, timeout=10) resp.raise_for_status() data = resp.json() except Exception as e: return f"Error: getting top gainers: {e}" return json.dumps(data) @fmp_server.tool( name="get_top_losers", description="""获取今日跌幅最大的股票列表。""", ) async def get_top_losers() -> str: """获取今日跌幅榜""" api_key = os.environ.get("FMP_API_KEY") if not api_key: return "Error: FMP_API_KEY environment variable not set." url = "https://financialmodelingprep.com/api/v3/stock_market/losers" try: resp = requests.get(url, params={"apikey": api_key}, timeout=10) resp.raise_for_status() data = resp.json() except Exception as e: return f"Error: getting top losers: {e}" return json.dumps(data) @fmp_server.tool( name="get_stock_grades", description="""获取分析师最新评级。 参数说明: ticker: str 股票代码,例如 "AAPL""", ) async def get_stock_grades(ticker: str) -> str: """获取指定股票的分析师最新评级""" api_key = os.environ.get("FMP_API_KEY") if not api_key: return "Error: FMP_API_KEY environment variable not set." url = "https://financialmodelingprep.com/stable/grades" try: resp = requests.get(url, params={"symbol": ticker, "apikey": api_key}, timeout=10) resp.raise_for_status() data = resp.json() except Exception as e: return f"Error: getting stock grades for {ticker}: {e}" return json.dumps(data) @fmp_server.tool( name="get_stock_grades_historical", description="""获取分析师评级历史记录。 参数说明: ticker: str 股票代码,例如 "AAPL" limit: int 返回记录数量,最大 1000,默认 100""", ) async def get_stock_grades_historical(ticker: str, limit: int = 100) -> str: """获取分析师评级历史数据""" api_key = os.environ.get("FMP_API_KEY") if not api_key: return "Error: FMP_API_KEY environment variable not set." url = "https://financialmodelingprep.com/stable/grades-historical" try: resp = requests.get( url, params={"symbol": ticker, "limit": limit, "apikey": api_key}, timeout=10, ) resp.raise_for_status() data = resp.json() except Exception as e: return f"Error: getting historical grades for {ticker}: {e}" return json.dumps(data) @fmp_server.tool( name="get_stock_grades_summary", description="""获取分析师评级汇总。 参数说明: ticker: str 股票代码,例如 "AAPL""", ) async def get_stock_grades_summary(ticker: str) -> str: """获取分析师评级汇总数据""" api_key = os.environ.get("FMP_API_KEY") if not api_key: return "Error: FMP_API_KEY environment variable not set." url = "https://financialmodelingprep.com/stable/grades-consensus" try: resp = requests.get(url, params={"symbol": ticker, "apikey": api_key}, timeout=10) resp.raise_for_status() data = resp.json() except Exception as e: return f"Error: getting grades summary for {ticker}: {e}" return json.dumps(data) @fmp_server.tool( name="get_stock_grade_news", description="""获取指定股票的评级新闻。 参数说明: ticker: str 股票代码,例如 "AAPL" page: int 页码,默认 0 limit: int 每页数量,最大 100,默认 1""", ) async def get_stock_grade_news(ticker: str, page: int = 0, limit: int = 1) -> str: """获取分析师评级相关新闻""" api_key = os.environ.get("FMP_API_KEY") if not api_key: return "Error: FMP_API_KEY environment variable not set." url = "https://financialmodelingprep.com/stable/grades-news" try: resp = requests.get( url, params={ "symbol": ticker, "page": page, "limit": limit, "apikey": api_key, }, timeout=10, ) resp.raise_for_status() data = resp.json() except Exception as e: return f"Error: getting grade news for {ticker}: {e}" return json.dumps(data) @fmp_server.tool( name="get_stock_grade_latest_news", description="""获取最新评级新闻。 参数说明: page: int 页码,默认 0 limit: int 每页数量,最大 1000,默认 10""", ) async def get_stock_grade_latest_news(page: int = 0, limit: int = 10) -> str: """获取所有股票的最新评级新闻""" api_key = os.environ.get("FMP_API_KEY") if not api_key: return "Error: FMP_API_KEY environment variable not set." url = "https://financialmodelingprep.com/stable/grades-latest-news" try: resp = requests.get( url, params={"page": page, "limit": limit, "apikey": api_key}, timeout=10, ) resp.raise_for_status() data = resp.json() except Exception as e: return f"Error: getting latest grade news: {e}" return json.dumps(data) @fmp_server.tool( name="lookup_identifier", description="""按标识类型查询股票代码、CIK、CUSIP 或 ISIN。 参数说明: identifier_type: str 可选值:symbol、name、cik、cusip、isin、exchange_variant query: str 对应的查询内容""", ) async def lookup_identifier(identifier_type: str, query: str) -> str: """根据不同标识类型搜索证券信息""" api_key = os.environ.get("FMP_API_KEY") if not api_key: return "Error: FMP_API_KEY environment variable not set." base = "https://financialmodelingprep.com/stable" endpoint_map = { "symbol": ("search-symbol", "query"), "name": ("search-name", "query"), "cik": ("search-cik", "cik"), "cusip": ("search-cusip", "cusip"), "isin": ("search-isin", "isin"), "exchange_variant": ("search-exchange-variants", "symbol"), } ep = endpoint_map.get(identifier_type.lower()) if not ep: return "Error: invalid identifier type" endpoint, param_name = ep url = f"{base}/{endpoint}" try: resp = requests.get(url, params={param_name: query, "apikey": api_key}, timeout=10) resp.raise_for_status() data = resp.json() except Exception as e: return f"Error: lookup failed for {query}: {e}" return json.dumps(data) @fmp_server.tool( name="get_directory_list", description="""获取市场或公司目录列表。 参数说明: list_type: str 可选值:stock、financial_statement_symbol、cik、symbol_change、etf、 actively_trading、earnings_transcript、available_exchanges、 available_sectors、available_industries、available_countries""", ) async def get_directory_list(list_type: str) -> str: """根据目录类型获取对应列表数据""" api_key = os.environ.get("FMP_API_KEY") if not api_key: return "Error: FMP_API_KEY environment variable not set." base = "https://financialmodelingprep.com/stable" endpoint_map = { "stock": "stock-list", "financial_statement_symbol": "financial-statement-symbol-list", "cik": "cik-list", "symbol_change": "symbol-change", "etf": "etf-list", "actively_trading": "actively-trading-list", "earnings_transcript": "earnings-transcript-list", "available_exchanges": "available-exchanges", "available_sectors": "available-sectors", "available_industries": "available-industries", "available_countries": "available-countries", } endpoint = endpoint_map.get(list_type.lower()) if not endpoint: return "Error: invalid list type" url = f"{base}/{endpoint}" try: resp = requests.get(url, params={"apikey": api_key}, timeout=10) resp.raise_for_status() data = resp.json() except Exception as e: return f"Error: getting directory list for {list_type}: {e}" return json.dumps(data) @fmp_server.tool( name="get_analyst_estimates", description="""获取分析师的财务预估数据。 参数说明: symbol: str 股票代码,例如 "AAPL" period: str annual 或 quarter,默认 annual page: int 页码,默认 0 limit: int 返回数量,默认 10""", ) async def get_analyst_estimates( symbol: str, period: str = "annual", page: int = 0, limit: int = 10 ) -> str: """获取分析师预估指标""" api_key = os.environ.get("FMP_API_KEY") if not api_key: return "Error: FMP_API_KEY environment variable not set." url = "https://financialmodelingprep.com/stable/analyst-estimates" try: resp = requests.get( url, params={ "symbol": symbol, "period": period, "page": page, "limit": limit, "apikey": api_key, }, timeout=10, ) resp.raise_for_status() data = resp.json() except Exception as e: return f"Error: getting analyst estimates for {symbol}: {e}" return json.dumps(data) @fmp_server.tool( name="get_ratings", description="""获取股票评级数据,可选择快照或历史记录。 参数说明: symbol: str 股票代码,例如 "AAPL" rating_type: str snapshot 或 historical,默认 snapshot limit: int 返回数量,默认 1""", ) async def get_ratings(symbol: str, rating_type: str = "snapshot", limit: int = 1) -> str: """根据类型获取评级信息""" api_key = os.environ.get("FMP_API_KEY") if not api_key: return "Error: FMP_API_KEY environment variable not set." base = "https://financialmodelingprep.com/stable" endpoint_map = { "snapshot": "ratings-snapshot", "historical": "ratings-historical", } endpoint = endpoint_map.get(rating_type.lower()) if not endpoint: return "Error: invalid rating type" url = f"{base}/{endpoint}" try: resp = requests.get( url, params={"symbol": symbol, "limit": limit, "apikey": api_key}, timeout=10, ) resp.raise_for_status() data = resp.json() except Exception as e: return f"Error: getting {rating_type} ratings for {symbol}: {e}" return json.dumps(data) @fmp_server.tool( name="get_price_target_info", description="""获取分析师目标价相关信息,可选择汇总、共识或新闻。 参数说明: info_type: str summary、consensus、news、latest_news symbol: str 股票代码,news/summary/consensus 必填 page: int 页码,默认 0 limit: int 返回数量,默认 10""", ) async def get_price_target_info( info_type: str, symbol: str = "", page: int = 0, limit: int = 10, ) -> str: """获取价格目标汇总、共识或相关新闻""" api_key = os.environ.get("FMP_API_KEY") if not api_key: return "Error: FMP_API_KEY environment variable not set." base = "https://financialmodelingprep.com/stable" endpoint_map = { "summary": "price-target-summary", "consensus": "price-target-consensus", "news": "price-target-news", "latest_news": "price-target-latest-news", } endpoint = endpoint_map.get(info_type.lower()) if not endpoint: return "Error: invalid info type" params = {"apikey": api_key} if info_type in ["summary", "consensus", "news"]: if not symbol: return "Error: symbol is required for this info type" params["symbol"] = symbol if info_type in ["news", "latest_news"]: params.update({"page": page, "limit": limit}) url = f"{base}/{endpoint}" try: resp = requests.get(url, params=params, timeout=10) resp.raise_for_status() data = resp.json() except Exception as e: return f"Error: getting price target info {info_type} for {symbol}: {e}" return json.dumps(data) @fmp_server.tool( name="get_crypto_list", description="""获取交易所上市的加密货币列表。""", ) async def get_crypto_list() -> str: """获取可交易的加密货币列表""" api_key = os.environ.get("FMP_API_KEY") if not api_key: return "Error: FMP_API_KEY environment variable not set." url = "https://financialmodelingprep.com/stable/cryptocurrency-list" try: resp = requests.get(url, params={"apikey": api_key}, timeout=10) resp.raise_for_status() data = resp.json() except Exception as e: return f"Error: getting cryptocurrency list: {e}" return json.dumps(data) @fmp_server.tool( name="get_crypto_quote", description="""获取指定加密货币的完整行情。""", ) async def get_crypto_quote(symbol: str) -> str: """获取加密货币报价""" api_key = os.environ.get("FMP_API_KEY") if not api_key: return "Error: FMP_API_KEY environment variable not set." url = "https://financialmodelingprep.com/stable/quote" try: resp = requests.get(url, params={"symbol": symbol, "apikey": api_key}, timeout=10) resp.raise_for_status() data = resp.json() except Exception as e: return f"Error: getting crypto quote for {symbol}: {e}" return json.dumps(data) @fmp_server.tool( name="get_crypto_quote_short", description="""获取指定加密货币的简要行情。""", ) async def get_crypto_quote_short(symbol: str) -> str: """获取加密货币简短报价""" api_key = os.environ.get("FMP_API_KEY") if not api_key: return "Error: FMP_API_KEY environment variable not set." url = "https://financialmodelingprep.com/stable/quote-short" try: resp = requests.get(url, params={"symbol": symbol, "apikey": api_key}, timeout=10) resp.raise_for_status() data = resp.json() except Exception as e: return f"Error: getting short crypto quote for {symbol}: {e}" return json.dumps(data) @fmp_server.tool( name="get_all_crypto_quotes", description="""获取全部加密货币的批量行情。""", ) async def get_all_crypto_quotes() -> str: """批量获取加密货币行情""" api_key = os.environ.get("FMP_API_KEY") if not api_key: return "Error: FMP_API_KEY environment variable not set." url = "https://financialmodelingprep.com/stable/batch-crypto-quotes" try: resp = requests.get(url, params={"apikey": api_key}, timeout=10) resp.raise_for_status() data = resp.json() except Exception as e: return f"Error: getting batch crypto quotes: {e}" return json.dumps(data) @fmp_server.tool( name="get_crypto_price_eod", description="""获取加密货币的历史收盘价,可选简略或完整模式。""", ) async def get_crypto_price_eod(symbol: str, mode: str = "light") -> str: """获取加密货币 EOD 数据""" api_key = os.environ.get("FMP_API_KEY") if not api_key: return "Error: FMP_API_KEY environment variable not set." base = "https://financialmodelingprep.com/stable/historical-price-eod" endpoint_map = {"light": "light", "full": "full"} endpoint = endpoint_map.get(mode.lower()) if not endpoint: return "Error: invalid mode" url = f"{base}/{endpoint}" try: resp = requests.get(url, params={"symbol": symbol, "apikey": api_key}, timeout=10) resp.raise_for_status() data = resp.json() except Exception as e: return f"Error: getting {mode} crypto prices for {symbol}: {e}" return json.dumps(data) @fmp_server.tool( name="get_crypto_intraday", description="""按时间间隔获取加密货币的分时价格,支持 1min、5min 和 1hour。""", ) async def get_crypto_intraday(symbol: str, interval: str = "1min") -> str: """获取加密货币的分时价格""" api_key = os.environ.get("FMP_API_KEY") if not api_key: return "Error: FMP_API_KEY environment variable not set." allowed = {"1min", "5min", "1hour"} if interval not in allowed: return "Error: invalid interval" url = f"https://financialmodelingprep.com/stable/historical-chart/{interval}" try: resp = requests.get(url, params={"symbol": symbol, "apikey": api_key}, timeout=10) resp.raise_for_status() data = resp.json() except Exception as e: return f"Error: getting {interval} crypto data for {symbol}: {e}" return json.dumps(data) @fmp_server.tool( name="get_crypto_news", description="""搜索加密货币相关新闻。""", ) async def get_crypto_news(symbols: str) -> str: """获取加密货币新闻""" api_key = os.environ.get("FMP_API_KEY") if not api_key: return "Error: FMP_API_KEY environment variable not set." url = "https://financialmodelingprep.com/stable/news/crypto" try: resp = requests.get(url, params={"symbols": symbols, "apikey": api_key}, timeout=10) resp.raise_for_status() data = resp.json() except Exception as e: return f"Error: getting crypto news for {symbols}: {e}" return json.dumps(data) @fmp_server.tool( name="get_crypto_latest_news", description="""获取加密货币最新新闻列表。""", ) async def get_crypto_latest_news(page: int = 0, limit: int = 20) -> str: """获取最新加密货币新闻""" api_key = os.environ.get("FMP_API_KEY") if not api_key: return "Error: FMP_API_KEY environment variable not set." url = "https://financialmodelingprep.com/stable/news/crypto-latest" try: resp = requests.get( url, params={"page": page, "limit": limit, "apikey": api_key}, timeout=10, ) resp.raise_for_status() data = resp.json() except Exception as e: return f"Error: getting latest crypto news: {e}" return json.dumps(data) if __name__ == "__main__": # Initialize and run the server print("Starting Financial Modeling Prep MCP server...") fmp_server.run(transport="stdio")

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/16Coffee/finance-mcp'

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