Skip to main content
Glama

Polygon MCP Server

index.ts11 kB
#!/usr/bin/env node import { Server } from "@modelcontextprotocol/sdk/server/index.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js"; import axios, { AxiosInstance } from 'axios'; import { z } from 'zod'; // Get API key from environment const API_KEY = process.env.POLYGON_API_KEY; if (!API_KEY) { throw new Error('POLYGON_API_KEY environment variable is required'); } // Create Polygon API client const polygonApi: AxiosInstance = axios.create({ baseURL: 'https://api.polygon.io', params: { apiKey: API_KEY } }); // Create MCP server const server = new Server( { name: "polygon-server", version: "0.1.0", }, { capabilities: { tools: {}, }, } ); // Tool handlers const toolHandlers = { get_ticker_details: async (args: { ticker: string }) => { try { const response = await polygonApi.get(`/v3/reference/tickers/${args.ticker}`); return { content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }] }; } catch (error: any) { return { content: [{ type: "text", text: `Error getting ticker details: ${error.response?.data?.message || error.message}` }], isError: true }; } }, get_latest_quote: async (args: { ticker: string }) => { try { const response = await polygonApi.get(`/v2/last/nbbo/${args.ticker}`); return { content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }] }; } catch (error: any) { return { content: [{ type: "text", text: `Error getting latest quote: ${error.response?.data?.message || error.message}` }], isError: true }; } }, get_aggregates: async (args: { ticker: string; timespan: string; from: string; to: string; adjusted?: boolean; sort?: string; limit?: number; }) => { try { const params: any = { adjusted: args.adjusted !== false, sort: args.sort || 'asc', limit: args.limit || 120 }; const response = await polygonApi.get( `/v2/aggs/ticker/${args.ticker}/range/1/${args.timespan}/${args.from}/${args.to}`, { params } ); return { content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }] }; } catch (error: any) { return { content: [{ type: "text", text: `Error getting aggregates: ${error.response?.data?.message || error.message}` }], isError: true }; } }, get_daily_open_close: async (args: { ticker: string; date: string }) => { try { const response = await polygonApi.get(`/v1/open-close/${args.ticker}/${args.date}`); return { content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }] }; } catch (error: any) { return { content: [{ type: "text", text: `Error getting daily open/close: ${error.response?.data?.message || error.message}` }], isError: true }; } }, get_market_status: async () => { try { const response = await polygonApi.get('/v1/marketstatus/now'); return { content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }] }; } catch (error: any) { return { content: [{ type: "text", text: `Error getting market status: ${error.response?.data?.message || error.message}` }], isError: true }; } }, get_ticker_news: async (args: { ticker: string; limit?: number }) => { try { const params: any = { limit: args.limit || 10 }; const response = await polygonApi.get(`/v2/reference/news`, { params: { ...params, ticker: args.ticker } }); return { content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }] }; } catch (error: any) { return { content: [{ type: "text", text: `Error getting ticker news: ${error.response?.data?.message || error.message}` }], isError: true }; } }, list_tickers: async (args: { search?: string; type?: string; market?: string; limit?: number }) => { try { const params: any = { limit: args.limit || 100, active: true }; if (args.search) params.search = args.search; if (args.type) params.type = args.type; if (args.market) params.market = args.market; const response = await polygonApi.get('/v3/reference/tickers', { params }); return { content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }] }; } catch (error: any) { return { content: [{ type: "text", text: `Error listing tickers: ${error.response?.data?.message || error.message}` }], isError: true }; } }, get_snapshot: async (args: { tickers: string }) => { try { const response = await polygonApi.get('/v2/snapshot/locale/us/markets/stocks/tickers', { params: { tickers: args.tickers } }); return { content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }] }; } catch (error: any) { return { content: [{ type: "text", text: `Error getting snapshot: ${error.response?.data?.message || error.message}` }], isError: true }; } } }; // List available tools server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: "get_ticker_details", description: "Get details about a ticker symbol", inputSchema: { type: "object", properties: { ticker: { type: "string", description: "Ticker symbol (e.g., AAPL)" } }, required: ["ticker"] } }, { name: "get_latest_quote", description: "Get real-time quote for a ticker", inputSchema: { type: "object", properties: { ticker: { type: "string", description: "Ticker symbol (e.g., AAPL)" } }, required: ["ticker"] } }, { name: "get_aggregates", description: "Get aggregate bars for a ticker", inputSchema: { type: "object", properties: { ticker: { type: "string", description: "Ticker symbol (e.g., AAPL)" }, timespan: { type: "string", enum: ["minute", "hour", "day", "week", "month", "quarter", "year"], description: "Size of the time window" }, from: { type: "string", description: "Start date (YYYY-MM-DD format)" }, to: { type: "string", description: "End date (YYYY-MM-DD format)" }, adjusted: { type: "boolean", description: "Whether to adjust for splits (default: true)" }, sort: { type: "string", enum: ["asc", "desc"], description: "Sort order (default: asc)" }, limit: { type: "number", description: "Number of results (default: 120, max: 50000)" } }, required: ["ticker", "timespan", "from", "to"] } }, { name: "get_daily_open_close", description: "Get daily open/close prices", inputSchema: { type: "object", properties: { ticker: { type: "string", description: "Ticker symbol (e.g., AAPL)" }, date: { type: "string", description: "Date (YYYY-MM-DD format)" } }, required: ["ticker", "date"] } }, { name: "get_market_status", description: "Check if markets are open", inputSchema: { type: "object", properties: {} } }, { name: "get_ticker_news", description: "Get news articles for a ticker", inputSchema: { type: "object", properties: { ticker: { type: "string", description: "Ticker symbol (e.g., AAPL)" }, limit: { type: "number", description: "Number of articles to return (default: 10)" } }, required: ["ticker"] } }, { name: "list_tickers", description: "Search/list available tickers", inputSchema: { type: "object", properties: { search: { type: "string", description: "Search query" }, type: { type: "string", enum: ["CS", "ADRC", "ADRP", "ADRR", "UNIT", "RIGHT", "PFD", "FUND", "SP", "WARRANT", "INDEX", "ETF", "ETN", "OS", "GDR", "OTHER", "NYRS", "AGEN", "EQLK", "BOND", "ADRW", "BASKET"], description: "Security type" }, market: { type: "string", enum: ["stocks", "crypto", "fx", "otc", "indices"], description: "Market type" }, limit: { type: "number", description: "Number of results (default: 100)" } } } }, { name: "get_snapshot", description: "Get snapshot of ticker(s)", inputSchema: { type: "object", properties: { tickers: { type: "string", description: "Comma-separated list of tickers (e.g., AAPL,MSFT,GOOGL)" } }, required: ["tickers"] } } ] }; }); // Handle tool calls server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; if (name in toolHandlers) { return await (toolHandlers as any)[name](args || {}); } throw new Error(`Unknown tool: ${name}`); }); // Start the server async function main() { const transport = new StdioServerTransport(); await server.connect(transport); console.error('Polygon MCP server running on stdio'); } main().catch((error) => { console.error("Server error:", error); process.exit(1); });

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/jwaresolutions/polygon-mcp-server'

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