Skip to main content
Glama

Financial Data MCP Server

server_mcp.py8.48 kB
import yfinance as yf import httpx from duckduckgo_search import DDGS from markdownify import markdownify from fastmcp import FastMCP mcp = FastMCP("TutorialMCPServer") ## Função auxiliar para acessar sites e converter em Markdown: def buscar_conteudo_completo_site(url: str): """ Busca o conteúdo HTML de uma URL e o converte para o formato markdown. Utiliza um tempo limite de 10 segundos para evitar travamentos em sites lentos ou páginas muito grandes. """ try: with httpx.Client(timeout=10.0) as client: response = client.get(url) response.raise_for_status() return markdownify(response.text) except Exception as e: print(f"Aviso: Falha ao buscar o conteúdo completo da página para {url}: {str(e)}") return None ## Ferramentas MCPs: @mcp.tool() def duckduckgo_pesquisa(consulta: str, max_resultados: int = 2): """Realiza uma busca na web usando o DuckDuckGo e retorna os resultados formatados. :argument: consulta (str): A consulta de busca a ser executada max_resultados (int, opcional): Número máximo de resultados a serem retornados. Padrão é 2. :return: Dicionário com a resposta da busca contendo. """ try: print(f"Ferramenta de pesquisa chamada com - consulta: {consulta} e max_resultados: {max_resultados}") with DDGS() as ddgs: resultados = [] resultados_pesquisa = list(ddgs.text(consulta, max_results=max_resultados)) for r in resultados_pesquisa: url = r.get('href') titulo = r.get('title') conteudo_resumido = r.get('body') if not all([url, titulo, conteudo_resumido]): print(f"Aviso: Resultado incompleto do DuckDuckGo. Ignorar: {r}") continue conteudo_completo = buscar_conteudo_completo_site(url) # Adiciona os resultados na lista de sites pesquisados dicionario_resultados = { "titulo": titulo, "url": url, "conteudo_resumido": conteudo_resumido, "conteudo_completo": conteudo_completo } resultados.append(dicionario_resultados) print(f"Ferramenta de pesquisa finalizou - resultados: {resultados}") return {"resultados": resultados} except Exception as e: print(f"Erro em DuckDuckGo: {str(e)}") return {"resultados": []} @mcp.tool() def busca_resumo_de_acao(ticker: str) -> str: """ Busca um resumo da ação especificada incluindo preço de fechamento, volume e data. Args: ticker (str): Símbolo da ação (ex: 'AAPL', 'VALE3.SA') Returns: str: Resumo formatado com preço de fechamento, volume e data da última negociação """ try: print(f"Ferramenta de resumo de ação iniciada - ticker: {ticker}") stock = yf.Ticker(ticker) hist = stock.history(period="5d") if hist.empty: return f"No recent data found for {ticker.upper()}." latest = hist.iloc[-1] summary = ( f"{ticker.upper()} Summary:\n" f"Close Price: ${latest['Close']:.2f}\n" f"Volume: {int(latest['Volume'])}\n" f"Date: {latest.name.date()}\n" ) return summary except Exception as e: return f"Error retrieving stock data for {ticker}: {str(e)}" @mcp.tool() def busca_estimativas_de_preco_de_analistas(ticker: str) -> dict: """ Busca as estimativas de preço dos analistas para uma ação específica. Args: ticker (str): Símbolo da ação (ex: 'AAPL', 'VALE3.SA') Returns: dict: Dicionário com as estimativas de preço-alvo dos analistas ou mensagem de erro """ try: print(f"Ferramenta de busca_estimativas_de_preco_de_analistas iniciada - ticker: {ticker}") stock = yf.Ticker(ticker) return stock.analyst_price_targets except Exception as e: return {"error": str(e)} @mcp.tool() def busca_recomendacoes(ticker: str) -> list: """ Busca as recomendações dos analistas para uma ação específica. Args: ticker (str): Símbolo da ação (ex: 'AAPL', 'VALE3.SA') Returns: list: Lista com as recomendações dos analistas (Buy, Hold, Sell) ou mensagem de erro """ try: print(f"Ferramenta de busca_recomendacoes iniciada - ticker: {ticker}") stock = yf.Ticker(ticker) recs = stock.recommendations return recs.to_dict("records") if hasattr(recs, 'to_dict') else list(recs) except Exception as e: return [{"error": str(e)}] @mcp.tool() def busca_dividendos(ticker: str) -> dict: """ Busca o histórico de dividendos pagos por uma ação específica. Args: ticker (str): Símbolo da ação (ex: 'AAPL', 'VALE3.SA') Returns: dict: Dicionário com as datas e valores dos dividendos pagos ou mensagem de erro """ try: print(f"Ferramenta de busca_dividendos iniciada - ticker: {ticker}") stock = yf.Ticker(ticker) divs = stock.dividends return divs.to_dict() if hasattr(divs, 'to_dict') else dict(divs) except Exception as e: return {"error": str(e)} @mcp.tool() def busca_setor_da_acao(ticker: str) -> dict: """ Busca informações sobre o setor e indústria de uma ação específica. Args: ticker (str): Símbolo da ação (ex: 'AAPL', 'VALE3.SA') Returns: dict: Dicionário com informações do setor e indústria da empresa ou mensagem de erro """ try: print(f"Ferramenta de busca_setor_da_acao iniciada - ticker: {ticker}") stock = yf.Ticker(ticker) info = stock.info sector = info.get('sector') industry = info.get('industry') return {"sector": sector, "industry": industry} except Exception as e: return {"error": str(e)} @mcp.tool() def busca_demonstracoes_financeiras(ticker: str) -> dict: """ Busca as principais demonstrações financeiras de uma empresa. Args: ticker (str): Símbolo da ação (ex: 'AAPL', 'VALE3.SA') Returns: dict: Dicionário contendo balanço patrimonial, demonstração de resultados e fluxo de caixa ou mensagem de erro """ try: print(f"Ferramenta de busca_demonstracoes_financeiras iniciada - ticker: {ticker}") stock = yf.Ticker(ticker) return { "balanco_patrimonial": stock.balance_sheet.to_dict() if hasattr(stock.balance_sheet, 'to_dict') else dict(stock.balance_sheet), "demonstracao_de_resultados": stock.income_stmt.to_dict() if hasattr(stock.income_stmt, 'to_dict') else dict(stock.income_stmt), "fluxo_de_caixa": stock.cashflow.to_dict() if hasattr(stock.cashflow, 'to_dict') else dict(stock.cashflow) } except Exception as e: return {"error": str(e)} # Servindo Prompts Personalizados @mcp.prompt() def prompt_stock_summary(ticker: str) -> str: """ Gera um prompt para solicitar um resumo abrangente de uma ação específica. Args: ticker (str): Símbolo da ação (ex: 'AAPL', 'VALE3.SA') Returns: str: Prompt formatado solicitando resumo completo incluindo preço, volume, notícias e eventos """ return f"Por favor, forneça um resumo abrangente para a ação '{ticker}'. Inclua preço recente, volume, notícias e quaisquer eventos notáveis." @mcp.prompt() def prompt_investment_thesis(ticker: str) -> str: """ Gera um prompt para elaborar uma tese de investimento detalhada para uma ação. Args: ticker (str): Símbolo da ação (ex: 'AAPL', 'VALE3.SA') Returns: str: Prompt formatado solicitando análise SWOT e recomendações de analistas """ return f"Elabore uma tese de investimento para '{ticker}'. Inclua forças da empresa, fraquezas, oportunidades, ameaças e um resumo das recomendações recentes dos analistas." # Executando nosso MCP if __name__ == "__main__": mcp.run(transport="http", port=4200) # transporte via http # mcp.run() # transporte via stdio ## Testando o MCP via interface de teste: npx @modelcontextprotocol/inspector uv run server_mcp.py ## Para iniciar o servidor: uv run server_mcp.py

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/gustavo-sacchi/tutorial_mcp_langgraph'

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