get-stock-alerts
Set up automated alerts for stock price movements using customizable percentage thresholds to monitor specific stocks and receive notifications when significant changes occur.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| symbol | Yes | Stock symbol (e.g., IBM, AAPL) | |
| threshold | No | Percentage threshold for price movement alerts (default: 5) |
Implementation Reference
- src/index.ts:68-81 (handler)The inline handler function for the get-stock-alerts tool. It calls the getStockAlerts helper, returns the alerts as text content, or an error response.async ({ symbol, threshold = 5 }) => { try { const alerts = await getStockAlerts(symbol, threshold); return { content: [{ type: "text", text: alerts }] }; } catch (error) { return { content: [{ type: "text", text: `Error generating stock alerts: ${error instanceof Error ? error.message : String(error)}` }], isError: true }; } } );
- src/index.ts:64-67 (schema)Zod input schema defining parameters: symbol (required string) and threshold (optional number, default 5).{ symbol: z.string().describe("Stock symbol (e.g., IBM, AAPL)"), threshold: z.number().optional().describe("Percentage threshold for price movement alerts (default: 5)") },
- src/index.ts:62-81 (registration)Registration of the get-stock-alerts tool on the MCP server, specifying name, input schema, and handler function.server.tool( "get-stock-alerts", { symbol: z.string().describe("Stock symbol (e.g., IBM, AAPL)"), threshold: z.number().optional().describe("Percentage threshold for price movement alerts (default: 5)") }, async ({ symbol, threshold = 5 }) => { try { const alerts = await getStockAlerts(symbol, threshold); return { content: [{ type: "text", text: alerts }] }; } catch (error) { return { content: [{ type: "text", text: `Error generating stock alerts: ${error instanceof Error ? error.message : String(error)}` }], isError: true }; } } );
- src/alphaVantage.ts:104-166 (helper)The main helper function implementing the stock alerts logic: fetches daily time series data from Alpha Vantage API, calculates percentage changes over recent days, and generates alert messages for movements exceeding the threshold.export async function getStockAlerts(symbol: string | string[], threshold: number = 5): Promise<string> { try { // Ensure symbol is a string, not an array const symbolStr = Array.isArray(symbol) ? symbol[0] : symbol; // Get daily stock data for analysis const url = `${BASE_URL}?function=TIME_SERIES_DAILY&symbol=${symbolStr}&outputsize=compact&apikey=${API_KEY}`; const response = await axios.get(url); if (response.data['Error Message']) { throw new Error(response.data['Error Message']); } const timeSeries = response.data['Time Series (Daily)']; if (!timeSeries) { throw new Error('No time series data found in the response'); } // Get dates sorted from newest to oldest const dates = Object.keys(timeSeries).sort().reverse(); if (dates.length < 2) { return `Not enough historical data available for ${symbolStr} to generate alerts.`; } let alerts = `Stock Alerts for ${symbolStr.toUpperCase()} (${threshold}% threshold):\n\n`; let alertCount = 0; // Analyze the last 10 days (or less if not available) const daysToAnalyze = Math.min(10, dates.length - 1); for (let i = 0; i < daysToAnalyze; i++) { const currentDate = dates[i]; const previousDate = dates[i + 1]; const currentClose = parseFloat(timeSeries[currentDate]['4. close']); const previousClose = parseFloat(timeSeries[previousDate]['4. close']); // Calculate percentage change const percentChange = ((currentClose - previousClose) / previousClose) * 100; const absPercentChange = Math.abs(percentChange); // Check if change exceeds threshold if (absPercentChange >= threshold) { const direction = percentChange >= 0 ? 'increased' : 'decreased'; alerts += `${currentDate}: Price ${direction} by ${absPercentChange.toFixed(2)}% from ${previousClose} to ${currentClose}\n`; alertCount++; } } if (alertCount === 0) { alerts += `No significant price movements (>=${threshold}%) detected in the last ${daysToAnalyze} trading days.\n`; } return alerts; } catch (error) { if (axios.isAxiosError(error)) { throw new Error(`API request failed: ${error.message}`); } throw error; } }