Skip to main content
Glama
ross-jill-ws

Alpha Vantage MCP Server

by ross-jill-ws
MCP-SERVER-README.md9.22 kB
# Alpha Vantage MCP Server A Model Context Protocol (MCP) server that provides access to Alpha Vantage stock price and financial news data stored in MongoDB. ## Overview This MCP server exposes two tools for querying financial data: - `get_stock_prices` - Query stock price data (OHLCV) from MongoDB - `get_news` - Query financial news articles with sentiment analysis from MongoDB ## Installation Dependencies are already installed. The server requires: - `@modelcontextprotocol/sdk` - MCP SDK - `express` - For SSE transport mode - `mongodb` - MongoDB driver - `zod` - Schema validation ## Running the Server The MCP server supports two transport modes: ### Stdio Mode (Default) For use with MCP clients that communicate via standard input/output: ```bash bun src/mcp.ts --stdio ``` ### SSE Mode (HTTP) For HTTP-based communication with Server-Sent Events: ```bash bun src/mcp.ts --sse --port 3001 ``` Or use a custom port: ```bash bun src/mcp.ts --sse --port 8080 ``` ## Tools ### 1. get_stock_prices Query stock price data from MongoDB for a given stock symbol. **Automatically pulls data from Alpha Vantage API if not found.** **Parameters:** - `symbol` (string, required) - Stock ticker symbol (e.g., "AAPL", "IBM", "MSFT", "GOOGL") - `date` (string, optional) - Specific date in YYYYMMDD format (e.g., "20251223") **Behavior:** - First queries MongoDB for the requested stock data - **If not found:** Automatically calls Alpha Vantage API to pull the data, then queries again - If `date` is provided: Returns stock data for that specific date - If `date` is omitted: Returns the latest 100 stock prices sorted by date descending - Response message indicates if data was "freshly pulled from API" **Auto-Pull Feature:** This tool intelligently handles missing data by automatically fetching it from the Alpha Vantage API. This means you can query any valid stock symbol without having to manually pull the data first. The tool will: 1. Check if the data exists in MongoDB 2. If not found, pull from Alpha Vantage API (respects rate limits with 5-second delay) 3. Query MongoDB again and return the freshly pulled data **Example Request (stdio):** ```json { "jsonrpc": "2.0", "method": "tools/call", "params": { "name": "get_stock_prices", "arguments": { "symbol": "AAPL", "date": "20251223" } }, "id": 1 } ``` **Example Response (data already in MongoDB):** ```json { "message": "Stock data for AAPL on 2025-12-23", "data": { "symbol": "AAPL", "date": "2025-12-23", "open": 270.84, "high": 272.5, "low": 269.56, "close": 272.36, "volume": 29641999 } } ``` **Example Response (auto-pulled from API):** ```json { "message": "Stock data for MSFT on 2025-12-23 (freshly pulled from API)", "data": { "symbol": "MSFT", "date": "2025-12-23", "open": 442.91, "high": 445.67, "low": 441.23, "close": 444.85, "volume": 18234567 } } ``` ### 2. get_news Query financial news articles from MongoDB within a date range, with optional keyword filtering. **Parameters:** - `from` (string, required) - Start date in YYYYMMDD format (e.g., "20251221") - `to` (string, required) - End date in YYYYMMDD format (e.g., "20251222") - `keyword` (string, optional) - Keyword to filter news by title and summary (case-insensitive) **Behavior:** - Queries the `news` collection in the `finance` database - Filters by `time_published` field using the date range - If `keyword` is provided: Additionally filters using case-insensitive regex on both `title` and `summary` fields **Example Request (stdio):** ```json { "jsonrpc": "2.0", "method": "tools/call", "params": { "name": "get_news", "arguments": { "from": "20251223", "to": "20251223", "keyword": "market" } }, "id": 2 } ``` **Example Response:** ```json { "message": "Found 5 news articles between 20251223 and 20251223 matching keyword \"market\"", "count": 5, "data": [ { "title": "Exxon Mobil Stock (XOM) After Hours Today: Price Action, Top News, and What to Watch Before Markets Open Dec. 24, 2025", "url": "https://...", "time_published": "20251223T234114", "summary": "...", "overall_sentiment_score": 0.045162, "overall_sentiment_label": "Neutral", "ticker_sentiment": [...] } ] } ``` ## Testing ### Verify Implementation Run the verification script to test underlying functionality: ```bash bun verify-mcp.ts # or bun run verify ``` This will test: - MongoDB connection - Stock price queries - News queries - Date formatting - Keyword filtering ### Test SSE Mode Run the SSE mode test to verify the HTTP transport works correctly: ```bash bun test-sse.ts ``` This verifies: - SSE server starts correctly - SSE endpoint accepts connections - No "stream is not readable" errors - Proper headers are set (text/event-stream) ### Manual Testing with stdio You can test the MCP server manually using echo and pipes: ```bash # List available tools echo '{"jsonrpc": "2.0", "method": "tools/list", "id": 1}' | bun src/mcp.ts --stdio 2>/dev/null # Get AAPL stock prices echo '{"jsonrpc": "2.0", "method": "tools/call", "params": {"name": "get_stock_prices", "arguments": {"symbol": "AAPL", "date": "20251223"}}, "id": 2}' | bun src/mcp.ts --stdio 2>/dev/null # Get news articles echo '{"jsonrpc": "2.0", "method": "tools/call", "params": {"name": "get_news", "arguments": {"from": "20251223", "to": "20251223"}}, "id": 3}' | bun src/mcp.ts --stdio 2>/dev/null ``` ## Environment Variables The server requires the following environment variables: **Required:** - `MONGODB_CONNECTION_STRING` - MongoDB connection string **For Auto-Pull Feature (Optional):** - A `.keylist` file in the project root containing Alpha Vantage API keys (one per line) The `.keylist` file is used for the auto-pull feature. Keys are rotated in round-robin fashion. **📖 See [SETUP-KEYLIST.md](SETUP-KEYLIST.md) for detailed setup instructions.** Example `.env` file: ```bash MONGODB_CONNECTION_STRING=mongodb://localhost:27017 ``` Example `.keylist` file: ``` YOUR_ALPHA_VANTAGE_API_KEY_1 YOUR_ALPHA_VANTAGE_API_KEY_2 ``` **Note:** - The auto-pull feature respects Alpha Vantage API rate limits by waiting 5 seconds after each API call - If `.keylist` is not found, the server will still work for querying existing data, but auto-pull will fail with a helpful error message - You can manually pull data using: `bun src/run-stocks.ts --pull-stock SYMBOL` ## Data Schema ### StockData ```typescript interface StockData { symbol: string; // Stock ticker symbol date: string; // Date in YYYY-MM-DD format open: number; // Opening price high: number; // Highest price of the day low: number; // Lowest price of the day close: number; // Closing price volume: number; // Trading volume } ``` ### NewsItem ```typescript interface NewsItem { title: string; url: string; time_published: string; // YYYYMMDDTHHMMSS format authors: string[]; summary: string; banner_image: string | null; source: string; category_within_source: string; source_domain: string; topics: Topic[]; overall_sentiment_score: number; // -1 to 1 overall_sentiment_label: string; // "Bearish" | "Neutral" | "Bullish" etc. ticker_sentiment: TickerSentiment[]; } ``` ## Architecture The MCP server is implemented following the [bun-mcp-template](https://github.com/ross-jill-ws/bun-mcp-template) structure: - **Transport Support**: Both stdio (for CLI) and SSE (for HTTP) modes - **Tool-Only**: No resources or prompts - focused on data query tools - **MongoDB Integration**: Reuses existing `mongo.ts` utilities - **Type Safety**: Fully typed with TypeScript using business types ## Error Handling The server includes comprehensive error handling: - Invalid date formats are rejected with descriptive messages - Missing MongoDB collections return empty results with informative messages - Connection errors are caught and reported - Graceful shutdown on SIGINT ## Database Collections - `finance.stock-{SYMBOL}` - Stock price data (one collection per symbol) - `finance.news` - Financial news articles with sentiment analysis ## Troubleshooting ### SSE Mode: "stream is not readable" Error **Problem**: When running in SSE mode, you get an error "InternalServerError: stream is not readable" **Solution**: This error occurs when Express middleware (like `express.json()`) consumes the request body stream before the SSE transport can read it. **Fix Applied**: The server implementation does NOT use `express.json()` middleware. The SSE transport reads the raw request body directly. ```typescript // ✓ Correct - No body parser middleware const app = express(); app.get("/sse", ...); app.post("/messages", ...); // ✗ Wrong - express.json() consumes the stream const app = express(); app.use(express.json()); // DON'T DO THIS ``` ### TypeScript Deprecation Warnings You may see deprecation warnings about `Server` and `SSEServerTransport` from the `@modelcontextprotocol/sdk`. These are warnings from the SDK itself and can be safely ignored. They don't affect functionality.

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/ross-jill-ws/alphavantage'

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