Skip to main content
Glama
digital-duck

Model Context Protocol Demo

by digital-duck
mcp_server.py7.35 kB
from fastmcp import FastMCP import logging import yfinance as yf import math # Configure logging for better visibility logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') # --- Initialize the MCP Server --- mcp = FastMCP("Demo 🚀") # --- Define the Calculator Tool --- @mcp.tool() def calculator(operation: str, num1: float, num2: float) -> dict: """ Performs arithmetic operations on two numbers. Supports: add, subtract, multiply, divide, power """ logging.info(f"Calculator called: {operation} {num1} {num2}") try: if operation == "add": result = num1 + num2 elif operation == "subtract": result = num1 - num2 elif operation == "multiply": result = num1 * num2 elif operation == "divide": if num2 == 0: return {"error": "Cannot divide by zero"} result = num1 / num2 elif operation == "power": if num1 == 0: return {"error": "Base cannot be 0"} result = pow(num1, num2) else: return {"error": f"Unsupported operation: {operation}. Use: add, subtract, multiply, divide, power"} return { "operation": operation, "num1": num1, "num2": num2, "result": result, "expression": f"{num1} {operation} {num2} = {result}" } except Exception as e: logging.error(f"Calculator error: {e}") return {"error": str(e)} @mcp.tool() def trig(operation: str, num1: float, unit: str) -> dict: """ Performs trigonometric operations, with input/output angle (in unit of degree or radian). Supports: both regular operations (such as sine, cosine, tangent) and inverse operations (such as arc sine, arc cosine, arc tangent) """ logging.info(f"Trig called: {operation} {num1} in {unit}") try: unit = unit.lower() if operation == "sine": arg1 = num1 if unit.startswith("rad") else math.radians(num1) result = math.sin(arg1) elif operation == "cosine": arg1 = num1 if unit.startswith("rad") else math.radians(num1) result = math.cos(arg1) elif operation == "tangent": arg1 = num1 if unit.startswith("rad") else math.radians(num1) result = math.tan(arg1) elif operation == "arc sine": result = math.asin(num1) if not unit.startswith("rad"): result = math.degrees(result) elif operation == "arc cosine": result = math.acos(num1) if not unit.startswith("rad"): result = math.degrees(result) elif operation == "arc tangent": result = math.atan(num1) if not unit.startswith("rad"): result = math.degrees(result) else: return {"error": f"Unsupported operation: {operation}. Use: sine, cosine, tangent, arc sine, arc cosine, arc tangent"} return { "operation": operation, "num1": num1, "unit": unit, "result": result, "expression": f"{operation} ( {num1} ) = {result}" } except Exception as e: logging.error(f"Trig error: {e}") return {"error": str(e)} # --- Define the Yahoo Finance Tool --- @mcp.tool() def stock_quote(ticker: str) -> dict: """ Retrieves live stock data for a given ticker symbol. Example: AAPL, GOOGL, MSFT, TSLA """ logging.info(f"Stock quote requested for: {ticker}") try: ticker_data = yf.Ticker(ticker.upper()) info = ticker_data.info # Get current price - try multiple fields current_price = info.get('currentPrice') or info.get('regularMarketPrice') or info.get('previousClose') # Fallback to recent historical data if current_price is None: try: hist = ticker_data.history(period="1d") if not hist.empty: current_price = float(hist['Close'].iloc[-1]) except Exception: pass if current_price is None: return { "ticker": ticker.upper(), "error": f"Could not retrieve price data for {ticker}. Ticker may be invalid." } return { "ticker": ticker.upper(), "current_price": round(float(current_price), 2), "currency": info.get('currency', 'USD'), "company_name": info.get('longName', info.get('shortName', 'Unknown')), "market_cap": info.get('marketCap'), "previous_close": info.get('previousClose'), "volume": info.get('volume'), "day_high": info.get('dayHigh'), "day_low": info.get('dayLow') } except Exception as e: logging.error(f"Yahoo Finance error for {ticker}: {e}") return { "ticker": ticker.upper(), "error": f"Failed to get stock data: {str(e)}" } # --- Define a Health Check Tool --- @mcp.tool() def health() -> dict: """ Simple health check to verify server is running. """ return { "status": "healthy", "message": "MCP Server is running properly", "available_tools": ["calculator", "stock_quote", "health", "echo", ], "server_name": "Demo 🚀" } # --- Add a simple echo tool for testing --- @mcp.tool() def echo(message: str) -> dict: """ Echo back the provided message. Useful for testing. """ return { "original_message": message, "echo": f"Echo: {message}", "length": len(message), "timestamp": "2025-05-28" } # --- Add a resource for server info --- @mcp.resource("info://server") def server_info() -> str: """ Provides basic information about this MCP server. """ return "This is a demo MCP server built with FastMCP. It provides calculator and stock quote tools." # --- Add a dynamic resource for stock info --- @mcp.resource("stock://{ticker}") def stock_info(ticker: str) -> str: """ Provides basic stock information as a resource. """ try: ticker_data = yf.Ticker(ticker.upper()) info = ticker_data.info company_name = info.get('longName', ticker.upper()) return f"{company_name} ({ticker.upper()}) - A publicly traded company" except: return f"Stock ticker: {ticker.upper()}" # --- Main execution block --- if __name__ == "__main__": logging.info("Starting MCP Server with FastMCP...") print("🚀 MCP Server Starting...") print("📊 Available tools:") print(" • calculator - Perform arithmetic operations") print(" • trig - Perform Trigonometric operations") print(" • stock_quote - Get stock price data") print(" • health - Server health check") print(" • echo - Echo messages for testing") print("📚 Available resources:") print(" • info://server - Server information") print(" • stock://{ticker} - Stock information") print("✅ Server ready! Starting on default port...") # Run the server using FastMCP's built-in method mcp.run()

Latest Blog Posts

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/digital-duck/mcp_demo'

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