UNPKG

mg-mcp-server

Version:

MCP server for financial data APIs (Alpha Vantage + Yahoo Finance)

536 lines 24.7 kB
import { z } from 'zod'; import { AlphaVantageClient } from './alphavantage-client.js'; const client = new AlphaVantageClient(); export const tools = { // Stock Tools get_stock_quote: { description: 'Get real-time stock quote for a symbol', parameters: z.object({ symbol: z.string().describe('Stock symbol (e.g., AAPL, MSFT, GOOGL)'), }), execute: async ({ symbol }) => { const data = await client.getQuote(symbol); const quote = data['Global Quote']; return { symbol: quote['01. symbol'], price: quote['05. price'], change: quote['09. change'], changePercent: quote['10. change percent'], volume: quote['06. volume'], latestTradingDay: quote['07. latest trading day'], open: quote['02. open'], high: quote['03. high'], low: quote['04. low'], previousClose: quote['08. previous close'], }; }, }, get_stock_daily: { description: 'Get daily historical stock data', parameters: z.object({ symbol: z.string().describe('Stock symbol'), outputsize: z.enum(['compact', 'full']).optional().default('compact'), }), execute: async ({ symbol, outputsize }) => { const data = await client.getTimeSeriesDaily(symbol, outputsize); const timeSeries = data['Time Series (Daily)']; return Object.entries(timeSeries).map(([date, values]) => ({ date, open: values['1. open'], high: values['2. high'], low: values['3. low'], close: values['4. close'], volume: values['5. volume'], })); }, }, get_stock_intraday: { description: 'Get intraday stock data with customizable intervals', parameters: z.object({ symbol: z.string().describe('Stock symbol'), interval: z.enum(['1min', '5min', '15min', '30min', '60min']).optional().default('5min'), }), execute: async ({ symbol, interval }) => { const data = await client.getTimeSeriesIntraday(symbol, interval); const key = `Time Series (${interval})`; const timeSeries = data[key]; return Object.entries(timeSeries).map(([datetime, values]) => ({ datetime, open: values['1. open'], high: values['2. high'], low: values['3. low'], close: values['4. close'], volume: values['5. volume'], })); }, }, get_stock_weekly: { description: 'Get weekly historical stock data', parameters: z.object({ symbol: z.string().describe('Stock symbol'), }), execute: async ({ symbol }) => { const data = await client.getTimeSeriesWeekly(symbol); const timeSeries = data['Weekly Time Series']; return Object.entries(timeSeries).map(([date, values]) => ({ date, open: values['1. open'], high: values['2. high'], low: values['3. low'], close: values['4. close'], volume: values['5. volume'], })); }, }, get_stock_monthly: { description: 'Get monthly historical stock data', parameters: z.object({ symbol: z.string().describe('Stock symbol'), }), execute: async ({ symbol }) => { const data = await client.getTimeSeriesMonthly(symbol); const timeSeries = data['Monthly Time Series']; return Object.entries(timeSeries).map(([date, values]) => ({ date, open: values['1. open'], high: values['2. high'], low: values['3. low'], close: values['4. close'], volume: values['5. volume'], })); }, }, // Forex Tools get_exchange_rate: { description: 'Get current exchange rate between two currencies', parameters: z.object({ fromCurrency: z.string().describe('Source currency code (e.g., USD, EUR, JPY)'), toCurrency: z.string().describe('Target currency code (e.g., USD, EUR, JPY)'), }), execute: async ({ fromCurrency, toCurrency }) => { const data = await client.getExchangeRate(fromCurrency, toCurrency); const rate = data['Realtime Currency Exchange Rate']; return { fromCurrency: rate['1. From_Currency Code'], toCurrency: rate['3. To_Currency Code'], rate: rate['5. Exchange Rate'], lastRefreshed: rate['6. Last Refreshed'], timeZone: rate['7. Time Zone'], bidPrice: rate['8. Bid Price'], askPrice: rate['9. Ask Price'], }; }, }, // Crypto Tools get_crypto_daily: { description: 'Get daily cryptocurrency data', parameters: z.object({ symbol: z.string().describe('Cryptocurrency symbol (e.g., BTC, ETH, ADA)'), market: z.string().optional().default('USD'), }), execute: async ({ symbol, market }) => { const data = await client.getCryptoDaily(symbol, market); const timeSeries = data['Time Series (Digital Currency Daily)']; return Object.entries(timeSeries).map(([date, values]) => ({ date, open: values['1a. open'], high: values['2a. high'], low: values['3a. low'], close: values['4a. close'], volume: values['5. volume'], marketCap: values['6. market cap (USD)'], })); }, }, // Technical Indicators get_sma: { description: 'Get Simple Moving Average (SMA) technical indicator', parameters: z.object({ symbol: z.string().describe('Stock symbol'), interval: z.enum(['1min', '5min', '15min', '30min', '60min', 'daily', 'weekly', 'monthly']).optional().default('daily'), timePeriod: z.string().optional().default('20'), seriesType: z.enum(['open', 'high', 'low', 'close']).optional().default('close'), }), execute: async ({ symbol, interval, timePeriod, seriesType }) => { const data = await client.getTechnicalIndicator(symbol, 'SMA', interval, timePeriod, seriesType); const key = `Technical Analysis: SMA`; const smaData = data[key]; return Object.entries(smaData).map(([date, values]) => ({ date, sma: values.SMA, })); }, }, get_rsi: { description: 'Get Relative Strength Index (RSI) technical indicator', parameters: z.object({ symbol: z.string().describe('Stock symbol'), interval: z.enum(['1min', '5min', '15min', '30min', '60min', 'daily', 'weekly', 'monthly']).optional().default('daily'), timePeriod: z.string().optional().default('14'), seriesType: z.enum(['open', 'high', 'low', 'close']).optional().default('close'), }), execute: async ({ symbol, interval, timePeriod, seriesType }) => { const data = await client.getTechnicalIndicator(symbol, 'RSI', interval, timePeriod, seriesType); const key = `Technical Analysis: RSI`; const rsiData = data[key]; return Object.entries(rsiData).map(([date, values]) => ({ date, rsi: values.RSI, })); }, }, get_macd: { description: 'Get MACD technical indicator', parameters: z.object({ symbol: z.string().describe('Stock symbol'), interval: z.enum(['1min', '5min', '15min', '30min', '60min', 'daily', 'weekly', 'monthly']).optional().default('daily'), seriesType: z.enum(['open', 'high', 'low', 'close']).optional().default('close'), }), execute: async ({ symbol, interval, seriesType }) => { const data = await client.getTechnicalIndicator(symbol, 'MACD', interval, undefined, seriesType); const key = `Technical Analysis: MACD`; const macdData = data[key]; return Object.entries(macdData).map(([date, values]) => ({ date, macd: values.MACD, signal: values.MACD_Signal, histogram: values.MACD_Hist, })); }, }, // News Sentiment get_news_sentiment: { description: 'Get news sentiment for stocks or topics', parameters: z.object({ tickers: z.array(z.string()).optional().describe('Array of stock symbols'), topics: z.array(z.string()).optional().describe('Array of news topics'), limit: z.number().min(1).max(1000).optional().default(50), }), execute: async ({ tickers, topics, limit }) => { const data = await client.getNewsSentiment(tickers, topics, limit); return { items: data.feed?.map((item) => ({ title: item.title, url: item.url, timePublished: item.time_published, authors: item.authors, summary: item.summary, source: item.source, sentimentScore: item.overall_sentiment_score, sentimentLabel: item.overall_sentiment_label, tickers: item.ticker_sentiment?.map((t) => ({ ticker: t.ticker, relevance: t.relevance_score, sentiment: t.ticker_sentiment_score, })), })), }; }, }, // ==================== 付费版功能 (Premium+) ==================== // 基本面数据工具 get_company_overview: { description: 'Get company overview and fundamental data (Premium+ only)', parameters: z.object({ symbol: z.string().describe('Stock symbol'), }), execute: async ({ symbol }) => { const data = await client.getCompanyOverview(symbol); return { symbol: data.Symbol, name: data.Name, description: data.Description, sector: data.Sector, industry: data.Industry, marketCap: data.MarketCapitalization, peRatio: data.PERatio, pegRatio: data.PEGRatio, bookValue: data.BookValue, dividendPerShare: data.DividendPerShare, dividendYield: data.DividendYield, eps: data.EPS, revenuePerShareTTM: data.RevenuePerShareTTM, profitMargin: data.ProfitMargin, operatingMarginTTM: data.OperatingMarginTTM, returnOnAssetsTTM: data.ReturnOnAssetsTTM, returnOnEquityTTM: data.ReturnOnEquityTTM, revenueTTM: data.RevenueTTM, grossProfitTTM: data.GrossProfitTTM, dilutedEPSTTM: data.DilutedEPSTTM, quarterlyEarningsGrowthYOY: data.QuarterlyEarningsGrowthYOY, quarterlyRevenueGrowthYOY: data.QuarterlyRevenueGrowthYOY, analystTargetPrice: data.AnalystTargetPrice, trailingPE: data.TrailingPE, forwardPE: data.ForwardPE, priceToSalesRatioTTM: data.PriceToSalesRatioTTM, priceToBookRatio: data.PriceToBookRatio, evToRevenue: data.EVToRevenue, evToEBITDA: data.EVToEBITDA, beta: data.Beta, week52High: data['52WeekHigh'], week52Low: data['52WeekLow'], day50MovingAverage: data['50DayMovingAverage'], day200MovingAverage: data['200DayMovingAverage'], sharesOutstanding: data.SharesOutstanding, }; }, }, get_earnings: { description: 'Get earnings data for a company (Premium+ only)', parameters: z.object({ symbol: z.string().describe('Stock symbol'), }), execute: async ({ symbol }) => { const data = await client.getEarnings(symbol); return { symbol: data.symbol, annualEarnings: data.annualEarnings?.map((earning) => ({ fiscalDateEnding: earning.fiscalDateEnding, reportedEPS: earning.reportedEPS, })), quarterlyEarnings: data.quarterlyEarnings?.map((earning) => ({ fiscalDateEnding: earning.fiscalDateEnding, reportedDate: earning.reportedDate, reportedEPS: earning.reportedEPS, estimatedEPS: earning.estimatedEPS, surprise: earning.surprise, surprisePercentage: earning.surprisePercentage, })), }; }, }, get_balance_sheet: { description: 'Get balance sheet data (Premium+ only)', parameters: z.object({ symbol: z.string().describe('Stock symbol'), }), execute: async ({ symbol }) => { const data = await client.getBalanceSheet(symbol); return { symbol: data.symbol, annualReports: data.annualReports?.slice(0, 3).map((report) => ({ fiscalDateEnding: report.fiscalDateEnding, reportedCurrency: report.reportedCurrency, totalAssets: report.totalAssets, totalCurrentAssets: report.totalCurrentAssets, totalLiabilities: report.totalLiabilities, totalCurrentLiabilities: report.totalCurrentLiabilities, totalShareholderEquity: report.totalShareholderEquity, cashAndCashEquivalentsAtCarryingValue: report.cashAndCashEquivalentsAtCarryingValue, inventory: report.inventory, currentNetReceivables: report.currentNetReceivables, propertyPlantEquipment: report.propertyPlantEquipment, goodwill: report.goodwill, longTermDebt: report.longTermDebt, retainedEarnings: report.retainedEarnings, commonStock: report.commonStock, commonStockSharesOutstanding: report.commonStockSharesOutstanding, })), quarterlyReports: data.quarterlyReports?.slice(0, 4).map((report) => ({ fiscalDateEnding: report.fiscalDateEnding, totalAssets: report.totalAssets, totalLiabilities: report.totalLiabilities, totalShareholderEquity: report.totalShareholderEquity, })), }; }, }, get_income_statement: { description: 'Get income statement data (Premium+ only)', parameters: z.object({ symbol: z.string().describe('Stock symbol'), }), execute: async ({ symbol }) => { const data = await client.getIncomeStatement(symbol); return { symbol: data.symbol, annualReports: data.annualReports?.slice(0, 3).map((report) => ({ fiscalDateEnding: report.fiscalDateEnding, reportedCurrency: report.reportedCurrency, totalRevenue: report.totalRevenue, grossProfit: report.grossProfit, operatingIncome: report.operatingIncome, netIncome: report.netIncome, costOfRevenue: report.costOfRevenue, operatingExpenses: report.operatingExpenses, researchAndDevelopment: report.researchAndDevelopment, sellingGeneralAndAdministrative: report.sellingGeneralAndAdministrative, incomeBeforeTax: report.incomeBeforeTax, incomeTaxExpense: report.incomeTaxExpense, ebit: report.ebit, ebitda: report.ebitda, })), quarterlyReports: data.quarterlyReports?.slice(0, 4).map((report) => ({ fiscalDateEnding: report.fiscalDateEnding, totalRevenue: report.totalRevenue, grossProfit: report.grossProfit, operatingIncome: report.operatingIncome, netIncome: report.netIncome, })), }; }, }, get_cash_flow: { description: 'Get cash flow statement data (Premium+ only)', parameters: z.object({ symbol: z.string().describe('Stock symbol'), }), execute: async ({ symbol }) => { const data = await client.getCashFlow(symbol); return { symbol: data.symbol, annualReports: data.annualReports?.slice(0, 3).map((report) => ({ fiscalDateEnding: report.fiscalDateEnding, reportedCurrency: report.reportedCurrency, operatingCashflow: report.operatingCashflow, capitalExpenditures: report.capitalExpenditures, cashflowFromInvestment: report.cashflowFromInvestment, cashflowFromFinancing: report.cashflowFromFinancing, netIncome: report.netIncome, depreciationDepletionAndAmortization: report.depreciationDepletionAndAmortization, changeInReceivables: report.changeInReceivables, changeInInventory: report.changeInInventory, dividendPayout: report.dividendPayout, changeInCashAndCashEquivalents: report.changeInCashAndCashEquivalents, })), quarterlyReports: data.quarterlyReports?.slice(0, 4).map((report) => ({ fiscalDateEnding: report.fiscalDateEnding, operatingCashflow: report.operatingCashflow, capitalExpenditures: report.capitalExpenditures, netIncome: report.netIncome, })), }; }, }, // 高级技术指标 get_bollinger_bands: { description: 'Get Bollinger Bands technical indicator (Premium+ only)', parameters: z.object({ symbol: z.string().describe('Stock symbol'), interval: z.enum(['1min', '5min', '15min', '30min', '60min', 'daily', 'weekly', 'monthly']).optional().default('daily'), timePeriod: z.string().optional().default('20'), seriesType: z.enum(['open', 'high', 'low', 'close']).optional().default('close'), nbdevup: z.string().optional().default('2'), nbdevdn: z.string().optional().default('2'), }), execute: async ({ symbol, interval, timePeriod, seriesType, nbdevup, nbdevdn }) => { const data = await client.getBollingerBands(symbol, interval, timePeriod, seriesType, nbdevup, nbdevdn); const key = `Technical Analysis: BBANDS`; const bbandsData = data[key]; return Object.entries(bbandsData).map(([date, values]) => ({ date, upperBand: values['Real Upper Band'], middleBand: values['Real Middle Band'], lowerBand: values['Real Lower Band'], })); }, }, get_stochastic: { description: 'Get Stochastic Oscillator technical indicator (Premium+ only)', parameters: z.object({ symbol: z.string().describe('Stock symbol'), interval: z.enum(['1min', '5min', '15min', '30min', '60min', 'daily', 'weekly', 'monthly']).optional().default('daily'), fastkPeriod: z.string().optional().default('5'), slowkPeriod: z.string().optional().default('3'), slowdPeriod: z.string().optional().default('3'), }), execute: async ({ symbol, interval, fastkPeriod, slowkPeriod, slowdPeriod }) => { const data = await client.getStochastic(symbol, interval, fastkPeriod, slowkPeriod, slowdPeriod); const key = `Technical Analysis: STOCH`; const stochData = data[key]; return Object.entries(stochData).map(([date, values]) => ({ date, slowK: values.SlowK, slowD: values.SlowD, })); }, }, get_williams_r: { description: 'Get Williams %R technical indicator (Premium+ only)', parameters: z.object({ symbol: z.string().describe('Stock symbol'), interval: z.enum(['1min', '5min', '15min', '30min', '60min', 'daily', 'weekly', 'monthly']).optional().default('daily'), timePeriod: z.string().optional().default('14'), }), execute: async ({ symbol, interval, timePeriod }) => { const data = await client.getWilliamsR(symbol, interval, timePeriod); const key = `Technical Analysis: WILLR`; const willrData = data[key]; return Object.entries(willrData).map(([date, values]) => ({ date, willr: values.WILLR, })); }, }, get_atr: { description: 'Get Average True Range (ATR) technical indicator (Premium+ only)', parameters: z.object({ symbol: z.string().describe('Stock symbol'), interval: z.enum(['1min', '5min', '15min', '30min', '60min', 'daily', 'weekly', 'monthly']).optional().default('daily'), timePeriod: z.string().optional().default('14'), }), execute: async ({ symbol, interval, timePeriod }) => { const data = await client.getATR(symbol, interval, timePeriod); const key = `Technical Analysis: ATR`; const atrData = data[key]; return Object.entries(atrData).map(([date, values]) => ({ date, atr: values.ATR, })); }, }, // ==================== 企业版独有功能 ==================== get_options_data: { description: 'Get options data for a stock (Enterprise only)', parameters: z.object({ symbol: z.string().describe('Stock symbol'), }), execute: async ({ symbol }) => { return await client.getOptionsData(symbol); }, }, get_etf_profile: { description: 'Get ETF profile and holdings data (Enterprise only)', parameters: z.object({ symbol: z.string().describe('ETF symbol'), }), execute: async ({ symbol }) => { return await client.getETFProfile(symbol); }, }, get_economic_indicator: { description: 'Get economic indicator data (Enterprise only)', parameters: z.object({ functionName: z.enum(['REAL_GDP', 'REAL_GDP_PER_CAPITA', 'TREASURY_YIELD', 'FEDERAL_FUNDS_RATE', 'CPI', 'INFLATION', 'RETAIL_SALES', 'DURABLES', 'UNEMPLOYMENT', 'NONFARM_PAYROLL']).describe('Economic indicator function name'), interval: z.enum(['monthly', 'quarterly', 'annual']).optional().default('monthly'), }), execute: async ({ functionName, interval }) => { return await client.getEconomicIndicator(functionName, interval); }, }, get_real_time_quote: { description: 'Get real-time stock quote with no delay (Enterprise only)', parameters: z.object({ symbol: z.string().describe('Stock symbol'), }), execute: async ({ symbol }) => { return await client.getRealTimeQuote(symbol); }, }, // ==================== 工具方法 ==================== get_subscription_info: { description: 'Get current Alpha Vantage subscription information and limits', parameters: z.object({}), execute: async () => { return client.getSubscriptionInfo(); }, }, get_available_features: { description: 'Get list of available features based on current subscription', parameters: z.object({}), execute: async () => { return client.getAvailableFeatures(); }, }, }; //# sourceMappingURL=tools.js.map