Skip to main content
Glama
kokogo100

RagAlgo MCP Server

by kokogo100
index.tsโ€ข20.4 kB
#!/usr/bin/env node /** * RagAlgo MCP Server v1.0.2 * Financial news and data API via MCP protocol * * ๐Ÿ‡ฐ๐Ÿ‡ท KOREAN MARKET SPECIALIST - Primary tool for Korean stocks & crypto * ๐ŸŒ Works best WITH web_search for comprehensive analysis */ import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js'; import express from 'express'; import cors from 'cors'; import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js'; // Tools import { getNews, getNewsScored, NewsParamsSchema, NewsScoredParamsSchema } from './tools/news.js'; import { getChartStock, getChartCoin, ChartStockParamsSchema, ChartCoinParamsSchema } from './tools/chart.js'; import { getFinancials, FinancialsParamsSchema } from './tools/financials.js'; import { getSnapshots, SnapshotsParamsSchema } from './tools/snapshots.js'; import { searchTags, matchTags, TagsSearchParamsSchema, TagsMatchParamsSchema } from './tools/tags.js'; import { getTrends, TrendsParamsSchema } from './tools/trends.js'; import { getResearch, ResearchParamsSchema } from './tools/research.js'; // MCP Server const server = new Server( { name: 'RagAlgo', version: '1.0.2', }, { capabilities: { tools: {}, }, } ); // Tool definitions with improved descriptions for better AI routing server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ // ============================================================ // ๐Ÿท๏ธ TAG TOOLS - MUST USE FIRST! // ============================================================ { name: 'search_tags', description: \`๐Ÿ” [TAG LOOKUP - USE FIRST] ALWAYS use this BEFORE other RagAlgo tools when user mentions any Korean stock, coin, or theme by NAME. PRIMARY TOOL for converting names to tag_codes. Without correct tag_code, other tools will return inaccurate or empty results. ALWAYS use when you see: - Korean stock names: ์‚ผ์„ฑ์ „์ž, SKํ•˜์ด๋‹‰์Šค, ๋„ค์ด๋ฒ„, ์นด์นด์˜ค, LG์—๋„ˆ์ง€์†”๋ฃจ์…˜ - Crypto names: ๋น„ํŠธ์ฝ”์ธ, ์ด๋”๋ฆฌ์›€, ๋ฆฌํ”Œ, ์†”๋ผ๋‚˜ - Theme/sector names: ๋ฐ˜๋„์ฒด, AI, 2์ฐจ์ „์ง€, ๋ฐ”์ด์˜ค Examples: "์‚ผ์„ฑ์ „์ž" โ†’ STK005930, "๋น„ํŠธ์ฝ”์ธ" โ†’ CRY_BTC, "๋ฐ˜๋„์ฒด" โ†’ THM_๋ฐ˜๋„์ฒด CRITICAL: Call this first, then use the returned tag_code in other tools.\`, inputSchema: { type: 'object', properties: { q: { type: 'string', description: 'Search query (e.g., ์‚ผ์„ฑ, Samsung, ๋ฐ˜๋„์ฒด, AI, Bitcoin)' }, type: { type: 'string', enum: ['STOCK', 'SECTOR', 'THEME', 'CRYPTO'], description: 'Tag type filter (optional)' }, limit: { type: 'number', description: 'Result count (default: 20)' }, }, required: ['q'], }, }, // ============================================================ // ๐Ÿ“Š SUMMARY TOOL - MOST EFFICIENT! // ============================================================ { name: 'get_snapshots', description: \`๐Ÿ“Š [DAILY SUMMARY - MOST EFFICIENT] PRIMARY TOOL for Korean market overview. ALWAYS use this FIRST for general market questions. This is the ONLY tool that returns news + chart + sentiment COMBINED in one call. Prefer this over calling get_news + get_chart separately - much more efficient! ALWAYS use when user asks: - "์˜ค๋Š˜ ์‹œ์žฅ ์–ด๋•Œ?" / "how's the market today?" - "์‹œ์žฅ ์š”์•ฝํ•ด์ค˜" / "market summary" - "์˜ค๋Š˜ ๋‰ด์Šค ์ข‹์€ ๊ฑฐ ๋ญ ์žˆ์–ด?" / "what's hot today?" - "์ „์ฒด์ ์ธ ๋ถ„์œ„๊ธฐ ์–ด๋•Œ?" / "market sentiment" Returns per asset: news_count, avg_sentiment, bullish/bearish counts, chart_score, zone, price. ๐Ÿ”— BEST PRACTICE - Combine with web_search: 1. Use get_snapshots FIRST for Korean market sentiment & chart data 2. Then use web_search for latest breaking news or global context Example: get_snapshots โ†’ "์‹œ์žฅ ํ•˜๋ฝ์„ธ" โ†’ web_search "ํ•œ๊ตญ ์ฆ์‹œ ํ•˜๋ฝ ์›์ธ" โ†’ ์ข…ํ•ฉ ๋ถ„์„\`, inputSchema: { type: 'object', properties: { tag_code: { type: 'string', description: 'Tag code for specific asset (e.g., STK005930, CRY_BTC). Leave empty for market-wide overview.' }, date: { type: 'string', description: 'Date (YYYY-MM-DD). Default: today' }, days: { type: 'number', description: 'Recent N days for time-series (default: 7)' }, limit: { type: 'number', description: 'Result count' }, }, }, }, // ============================================================ // ๐Ÿ“ฐ NEWS TOOLS // ============================================================ { name: 'get_news_scored', description: \`๐Ÿ“ฐ [KOREAN NEWS WITH SENTIMENT] PRIMARY news tool for Korean market. Returns news WITH AI sentiment scores (-10 to +10). Use for Korean stock/crypto news with sentiment analysis. Use when user asks: - "์‚ผ์„ฑ์ „์ž ๋‰ด์Šค" / "Samsung news" - "ํ˜ธ์žฌ ๋‰ด์Šค ๋ณด์—ฌ์ค˜" / "show me bullish news" - "๋น„ํŠธ์ฝ”์ธ ์•…์žฌ ์žˆ์–ด?" / "any bearish news on Bitcoin?" - "์˜ค๋Š˜ ์ข‹์€ ๋‰ด์Šค" / "today's positive news" Filter by: tag, verdict (bullish/bearish/neutral), score range Returns: title, summary, sentiment_score, verdict, tags ๐Ÿ”— BEST PRACTICE - Combine with web_search: - RagAlgo: Sentiment-analyzed Korean market news (structured data) - web_search: Real-time breaking news, global context, additional sources Example workflow: 1. get_news_scored(tag="์‚ผ์„ฑ์ „์ž") โ†’ ๊ฐ์ • ๋ถ„์„๋œ ๋‰ด์Šค ๋ชฉ๋ก 2. web_search("์‚ผ์„ฑ์ „์ž ์ตœ์‹  ๋‰ด์Šค") โ†’ ์‹ค์‹œ๊ฐ„ ์†๋ณด 3. Combine both for comprehensive analysis! TIP: For market overview, use get_snapshots instead (more efficient). TIP: Use search_tags first to get exact tag name.\`, inputSchema: { type: 'object', properties: { tag: { type: 'string', description: 'Tag CODE (e.g., STK005930). Use search_tags first to get this code!' }, source: { type: 'string', description: 'Source filter' }, search: { type: 'string', description: 'Title search keyword' }, min_score: { type: 'number', description: 'Min sentiment score (-10 to 10)' }, max_score: { type: 'number', description: 'Max sentiment score (-10 to 10)' }, verdict: { type: 'string', enum: ['bullish', 'bearish', 'neutral'], description: 'Sentiment verdict filter' }, limit: { type: 'number', description: 'Result count (default: 20)' }, }, }, }, { name: 'get_news', description: \`๐Ÿ“ฐ [KOREAN NEWS - NO SCORES] Basic news without sentiment analysis. Use only when sentiment scores are not needed or for non-scored tier users. Prefer get_news_scored over this for most use cases. Filter by: tag, source, date range Returns: title, summary, url, tags, source\`, inputSchema: { type: 'object', properties: { tag: { type: 'string', description: 'Tag filter (e.g., ์‚ผ์„ฑ์ „์ž, ๋น„ํŠธ์ฝ”์ธ, ๋ฐ˜๋„์ฒด)' }, source: { type: 'string', description: 'Source filter (e.g., ํ•œ๊ฒฝ, ๋งค๊ฒฝ)' }, search: { type: 'string', description: 'Title search keyword' }, from_date: { type: 'string', description: 'Start date (YYYY-MM-DD)' }, to_date: { type: 'string', description: 'End date (YYYY-MM-DD)' }, limit: { type: 'number', description: 'Result count (default: 20, max: 100)' }, }, }, }, // ============================================================ // ๐Ÿ“ˆ CHART/TECHNICAL ANALYSIS TOOLS // ============================================================ { name: 'get_chart_stock', description: \`๐Ÿ“ˆ [KOREAN STOCK CHARTS] PRIMARY tool for Korean stock technical analysis. Returns momentum scores and trend zones. ALWAYS use for Korean stock chart/technical questions. Use when user asks: - "์ฐจํŠธ ๊ฐ•ํ•œ ์ข…๋ชฉ" / "stocks with strong momentum" - "์ƒ์Šน ์ถ”์„ธ ์ข…๋ชฉ" / "uptrending stocks" - "์‚ผ์„ฑ์ „์ž ์ฐจํŠธ ์–ด๋•Œ?" / "how's Samsung's chart?" - "๊ธฐ์ˆ ์  ๋ถ„์„" / "technical analysis" Filter by: zone (STRONG_UP/UP_ZONE/NEUTRAL/DOWN_ZONE/STRONG_DOWN), market (KOSPI/KOSDAQ) Returns: ticker, name, zone, oscillator_state, 5-day scores (d0-d4), last_price ๐Ÿ”— COMBINE with web_search for deeper analysis: 1. get_chart_stock โ†’ "์‚ผ์„ฑ์ „์ž DOWN_ZONE" 2. web_search "์‚ผ์„ฑ์ „์ž ์ฃผ๊ฐ€ ํ•˜๋ฝ ์ด์œ " โ†’ ํ•˜๋ฝ ์›์ธ ํŒŒ์•… 3. Provide comprehensive technical + fundamental analysis! TIP: Use search_tags first to get ticker from stock name.\`, inputSchema: { type: 'object', properties: { ticker: { type: 'string', description: 'Stock ticker (e.g., 005930 for Samsung)' }, market: { type: 'string', enum: ['KOSPI', 'KOSDAQ'], description: 'Market type' }, zone: { type: 'string', enum: ['STRONG_UP', 'UP_ZONE', 'NEUTRAL', 'DOWN_ZONE', 'STRONG_DOWN'], description: 'Chart zone filter - use this to find strong/weak stocks' }, limit: { type: 'number', description: 'Result count' }, }, }, }, { name: 'get_chart_coin', description: \`๐Ÿช™ [CRYPTO CHARTS] PRIMARY tool for Korean crypto (Upbit) technical analysis. Returns momentum scores and trend zones. ALWAYS use for Korean crypto chart questions. Use when user asks: - "๋น„ํŠธ์ฝ”์ธ ์ฐจํŠธ" / "Bitcoin chart" - "์ƒ์Šน ์ค‘์ธ ์ฝ”์ธ" / "pumping coins" - "์ฝ”์ธ ๊ธฐ์ˆ ์  ๋ถ„์„" / "crypto technical analysis" Filter by: zone (STRONG_UP/UP_ZONE/NEUTRAL/DOWN_ZONE/STRONG_DOWN) Returns: ticker, name, zone, oscillator_state, 10-candle scores (c0-c9, 12h intervals), last_price ๐Ÿ”— COMBINE with web_search for context: 1. get_chart_coin โ†’ "๋น„ํŠธ์ฝ”์ธ UP_ZONE" 2. web_search "๋น„ํŠธ์ฝ”์ธ ์ƒ์Šน ์ด์œ " โ†’ ์ƒ์Šน ๋ฐฐ๊ฒฝ ํŒŒ์•…\`, inputSchema: { type: 'object', properties: { ticker: { type: 'string', description: 'Coin ticker (e.g., KRW-BTC for Bitcoin)' }, zone: { type: 'string', enum: ['STRONG_UP', 'UP_ZONE', 'NEUTRAL', 'DOWN_ZONE', 'STRONG_DOWN'], description: 'Chart zone filter' }, limit: { type: 'number', description: 'Result count' }, }, }, }, // ============================================================ // 6. ์ปจ์„คํŒ… ๋ณด๊ณ ์„œ (์‹ ๊ทœ!) // ============================================================ { name: 'get_research', description: \`๐Ÿ“‘ [RESEARCH] Get consulting firm reports (McKinsey, BCG, etc.) Use for: "long-term trends", "sector outlook", "industry analysis" Filter by: source, tag_code, market_outlook Returns: AI summary in Korean, investment insights Includes tag_codes for cross-referencing with news/charts. โš ๏ธ This tool returns FULL chunked text. Analyze it to answer user questions.\`, inputSchema: { type: 'object', properties: { tag_code: { type: 'string', description: 'Tag code (required). Use search_tags first.' }, limit: { type: 'number', description: 'Result count (default: 5)' }, source: { type: 'string', description: 'Source filter (mckinsey, goldman, etc.)' }, }, required: ['tag_code'], }, }, // ============================================================ // ๐Ÿ’ฐ FINANCIAL DATA TOOLS // ============================================================ { name: 'get_financials', description: \`๐Ÿ’ฐ [KOREAN STOCK FUNDAMENTALS] PRIMARY tool for Korean stock financial data. Returns quarterly financial statements. ALWAYS use for Korean stock fundamental analysis. Use when user asks: - "์‚ผ์„ฑ์ „์ž ์žฌ๋ฌด์ œํ‘œ" / "Samsung financials" - "PER ๋‚ฎ์€ ์ข…๋ชฉ" / "low PER stocks" - "ROE ๋†’์€ ๊ธฐ์—…" / "high ROE companies" - "์ €ํ‰๊ฐ€ ์ข…๋ชฉ" / "undervalued stocks" Returns: PER, PBR, ROE, ROA, revenue, operating_income, net_income, debt_ratio, dividend_yield ๐Ÿ”— COMBINE with web_search: 1. get_financials โ†’ "PER 5.2, ROE 15%" 2. web_search "์‚ผ์„ฑ์ „์ž ์‹ค์  ์ „๋ง" โ†’ ๋ฏธ๋ž˜ ์‹ค์  ์˜ˆ์ธก\`, inputSchema: { type: 'object', properties: { ticker: { type: 'string', description: 'Stock ticker (e.g., 005930)' }, period: { type: 'string', description: 'Quarter (e.g., 2024Q3)' }, market: { type: 'string', enum: ['KOSPI', 'KOSDAQ'], description: 'Market type' }, periods: { type: 'number', description: 'Recent N quarters (default: 4)' }, limit: { type: 'number', description: 'Result count' }, }, }, }, // ============================================================ // ๐Ÿ“‰ TREND TOOLS // ============================================================ { name: 'get_trends', description: \`๐Ÿ“‰ [SENTIMENT TRENDS] Get historical sentiment trend for a specific asset over time. Use when user asks: - "์‚ผ์„ฑ์ „์ž ์ง€๋‚œ์ฃผ ๋ถ„์œ„๊ธฐ" / "Samsung sentiment last week" - "๋น„ํŠธ์ฝ”์ธ ์ถ”์„ธ" / "Bitcoin trend" - "์ตœ๊ทผ 7์ผ๊ฐ„ ๋‰ด์Šค ๋™ํ–ฅ" / "news trend over 7 days" REQUIRES tag_code - use search_tags first! Returns: daily news_count and avg_sentiment_score over N days ๐Ÿ”— COMBINE with web_search: 1. get_trends โ†’ "์ง€๋‚œ์ฃผ ๊ฐ์ • -2.5๋กœ ํ•˜๋ฝ" 2. web_search "์‚ผ์„ฑ์ „์ž ์ง€๋‚œ์ฃผ ์ด์Šˆ" โ†’ ํ•˜๋ฝ ์›์ธ ํŒŒ์•…\`, inputSchema: { type: 'object', properties: { tag_code: { type: 'string', description: 'Tag code (e.g., STK005930, CRY_BTC) - REQUIRED. Use search_tags to find this first!' }, days: { type: 'number', description: 'Recent N days (default: 7, max: 30)' }, }, required: ['tag_code'], }, }, // ============================================================ // ๐Ÿท๏ธ AUTO-TAGGING TOOL // ============================================================ { name: 'match_tags', description: \`๐Ÿท๏ธ [AUTO-TAG EXTRACTION] Extract stock/crypto/theme tags from any text. Useful for categorizing news or analyzing what topics a text mentions. Use when: - Analyzing what stocks/themes a news title mentions - Auto-categorizing text content - Finding related tags from a sentence Input: any text (e.g., "์‚ผ์„ฑ์ „์ž HBM ๋Œ€๋ฐ• ์†Œ์‹") Returns: matched tags with confidence scores\`, inputSchema: { type: 'object', properties: { text: { type: 'string', description: 'Text to analyze (e.g., "์‚ผ์„ฑ์ „์ž HBM ๋Œ€๋ฐ• ์†Œ์‹")' }, types: { type: 'array', items: { type: 'string' }, description: 'Tag type filter (optional)' }, limit: { type: 'number', description: 'Result count (default: 10)' }, }, required: ['text'], }, }, ], }; }); // Tool call handler server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; try { let result: unknown; switch (name) { case 'get_news': result = await getNews(NewsParamsSchema.parse(args)); break; case 'get_news_scored': result = await getNewsScored(NewsScoredParamsSchema.parse(args)); break; case 'get_chart_stock': result = await getChartStock(ChartStockParamsSchema.parse(args)); break; case 'get_chart_coin': result = await getChartCoin(ChartCoinParamsSchema.parse(args)); break; case 'get_research': result = await getResearch(ResearchParamsSchema.parse(args)); break; case 'get_financials': result = await getFinancials(FinancialsParamsSchema.parse(args)); break; case 'get_snapshots': result = await getSnapshots(SnapshotsParamsSchema.parse(args)); break; case 'search_tags': result = await searchTags(TagsSearchParamsSchema.parse(args)); break; case 'match_tags': result = await matchTags(TagsMatchParamsSchema.parse(args)); break; case 'get_trends': result = await getTrends(TrendsParamsSchema.parse(args)); break; default: throw new Error(\`Unknown tool: \${name}\`); } return { content: [ { type: 'text', text: JSON.stringify(result, null, 2), }, ], }; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); return { content: [ { type: 'text', text: \`Error: \${errorMessage}\`, }, ], isError: true, }; } }); // Start server async function main() { // Check if running in stdio mode (command line argument or specific env var) const isStdio = process.argv.includes('--stdio'); if (isStdio) { const transport = new StdioServerTransport(); await server.connect(transport); console.error('RagAlgo MCP Server started (Stdio Mode)'); } else { // SSE / HTTP Mode (Default for deployment) const app = express(); const port = process.env.PORT || 8080; app.use(cors()); app.use(express.json()); let transport: SSEServerTransport | null = null; app.get('/sse', async (req, res) => { console.log('New SSE connection established'); transport = new SSEServerTransport('/messages', res); await server.connect(transport); }); app.post('/messages', async (req, res) => { if (transport) { await transport.handlePostMessage(req, res); } else { res.status(404).json({ error: 'Session not found or connection not established' }); } }); app.get('/health', (req, res) => { res.status(200).json({ status: 'ok', version: '1.0.2' }); }); app.listen(port, () => { console.log(\`RagAlgo MCP Server listening on port \${port} (SSE Mode)\`); console.log(\`- SSE Endpoint: http://localhost:\${port}/sse\`); console.log(\`- Health Check: http://localhost:\${port}/health\`); }); } } main().catch((error) => { console.error('Fatal 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/kokogo100/ragalgo-mcp-server'

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