ragalgo-mcp-server 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.dockerignore ADDED
@@ -0,0 +1,4 @@
1
+ node_modules
2
+ dist
3
+ .git
4
+ .env
@@ -0,0 +1 @@
1
+ ghu_Safy78H3Zvt7BUuP8NfXi5r2gCVRjy1qBA0C
@@ -0,0 +1 @@
1
+ {"token":"eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJtY3AtcmVnaXN0cnkiLCJleHAiOjE3NjYyMTQ0MTAsIm5iZiI6MTc2NjIxNDExMCwiaWF0IjoxNzY2MjE0MTEwLCJhdXRoX21ldGhvZCI6ImdpdGh1Yi1hdCIsImF1dGhfbWV0aG9kX3N1YiI6Imtva29nbzEwMCIsInBlcm1pc3Npb25zIjpbeyJhY3Rpb24iOiJwdWJsaXNoIiwicmVzb3VyY2UiOiJpby5naXRodWIua29rb2dvMTAwLyoifV19.hflQzpb2k9_IJXL0_60d2yIiTkn-279aMAwLU601Zrw2sD76mOukJ6iY4psRv3RR2IygAwaMhYqezwoZZECoDw","expires_at":1766214410}
package/Dockerfile ADDED
@@ -0,0 +1,23 @@
1
+ # Build stage
2
+ FROM node:18-alpine AS builder
3
+
4
+ WORKDIR /app
5
+ COPY package*.json ./
6
+ RUN npm install
7
+ COPY . .
8
+ RUN npm run build
9
+
10
+ # Production stage
11
+ FROM node:18-alpine
12
+
13
+ WORKDIR /app
14
+ COPY package*.json ./
15
+ # Install only production dependencies
16
+ RUN npm install --only=production
17
+
18
+ COPY --from=builder /app/dist ./dist
19
+
20
+ ENV PORT=8080
21
+ EXPOSE 8080
22
+
23
+ CMD ["npm", "start"]
package/README.md ADDED
@@ -0,0 +1,73 @@
1
+ # RagAlgo: Dynamic RAG Engine for AI Reliability
2
+
3
+ > **AI 신뢰성을 위한 다이내믹 RAG 엔진**
4
+
5
+ RagAlgo는 변동성이 큰 한국 금융(주식/코인) 데이터를 **'태그(Tag)'**와 **'점수(Score)'**로 표준화하여 제공하는 **AI 전용 MCP 서버**입니다.
6
+ 여러분의 AI 에이전트가 인터넷을 헤매지 않고, 가장 효율적으로 시장의 "진실(State-of-Truth)"을 파악할 수 있도록 돕습니다.
7
+
8
+ - **핵심 기능:** KOSPI/KOSDAQ 및 업비트(Upbit) 기반의 실시간 차트 점수, 뉴스 감정 분석
9
+ - **무료 테스트:** 지금 바로 설치하여 **1,000회 무료 호출**로 충분히 테스트해보세요.
10
+ - **상세 문서:** 웹소켓 연동 및 비즈니스 플랜 등 자세한 내용은 [공식 웹사이트(ragalgo.com)](https://www.ragalgo.com)에서 확인하실 수 있습니다.
11
+
12
+ ---
13
+
14
+ ## 🚀 설치 및 실행
15
+
16
+ ### 1. 직접 실행 (npx)
17
+
18
+ ```bash
19
+ # 별도 설치 없이 바로 실행 (API Key 필요)
20
+ npx -y @ragalgo/server
21
+ ```
22
+
23
+ ### 2. Claude Desktop 설정
24
+
25
+ `%APPDATA%\Claude\claude_desktop_config.json` (Windows) 또는 `~/Library/Application Support/Claude/claude_desktop_config.json` (Mac) 파일에 추가하세요.
26
+
27
+ ```json
28
+ {
29
+ "mcpServers": {
30
+ "ragalgo": {
31
+ "command": "npx",
32
+ "args": ["-y", "@ragalgo/server", "--stdio"],
33
+ "env": {
34
+ "RAGALGO_API_KEY": "비즈니스_또는_테스트_키_입력"
35
+ }
36
+ }
37
+ }
38
+ }
39
+ ```
40
+
41
+ > **Tip:** 테스트용 API Key는 [RagAlgo 대시보드](https://www.ragalgo.com/dashboard)에서 즉시 발급 가능합니다.
42
+
43
+ ---
44
+
45
+
46
+
47
+ ## 🛠️ 제공 도구 (Tools)
48
+
49
+ | 도구 | 설명 |
50
+ |------|------|
51
+ | `get_news_scored` | **[핵심]** 감정 점수(Sentiment Score)가 포함된 금융 뉴스 조회 |
52
+ | `get_chart_stock` | **[핵심]** 한국 주식(KOSPI/KOSDAQ) 기술적 분석 점수 조회 |
53
+ | `get_chart_coin` | **[핵심]** 한국 가상화폐(Upbit) 기술적 분석 점수 조회 |
54
+ | `get_snapshots` | 시장 전체 요약 스냅샷 (뉴스 + 차트 + 트렌드) |
55
+ | `get_financials` | 기업 재무제표 (분기/연간 실적) |
56
+ | `search_tags` | 텍스트(종목명)를 RagAlgo 고유 태그로 변환 |
57
+
58
+ ---
59
+
60
+ ## 📡 Real-time WebSocket (Business Only)
61
+
62
+ 실시간 주가/코인 점수 데이터를 웹소켓으로 수신할 수 있습니다.
63
+
64
+ - **대상:** Business Plan 사용자 (월 30개 연결 포함)
65
+ - **주소:** `wss://ragalgo-relay-server-1-production.up.railway.app`
66
+ - **구현 방법:** `socket.io-client` 라이브러리 사용 (자세한 코드는 [공식 문서](https://www.ragalgo.com/docs) 참조)
67
+
68
+ ---
69
+
70
+ ## 💬 Community & Support
71
+
72
+ - **Website:** [ragalgo.com](https://www.ragalgo.com)
73
+ - **Email:** support@ragalgo.com
Binary file
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * RagAlgo MCP Server v1.0.2
4
+ * Financial news and data API via MCP protocol
5
+ *
6
+ * 🇰🇷 KOREAN MARKET SPECIALIST - Primary tool for Korean stocks & crypto
7
+ * 🌐 Works best WITH web_search for comprehensive analysis
8
+ */
9
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,440 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * RagAlgo MCP Server v1.0.2
4
+ * Financial news and data API via MCP protocol
5
+ *
6
+ * 🇰🇷 KOREAN MARKET SPECIALIST - Primary tool for Korean stocks & crypto
7
+ * 🌐 Works best WITH web_search for comprehensive analysis
8
+ */
9
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
10
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
11
+ import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
12
+ import express from 'express';
13
+ import cors from 'cors';
14
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
15
+ // Tools
16
+ import { getNews, getNewsScored, NewsParamsSchema, NewsScoredParamsSchema } from './tools/news.js';
17
+ import { getChartStock, getChartCoin, ChartStockParamsSchema, ChartCoinParamsSchema } from './tools/chart.js';
18
+ import { getFinancials, FinancialsParamsSchema } from './tools/financials.js';
19
+ import { getSnapshots, SnapshotsParamsSchema } from './tools/snapshots.js';
20
+ import { searchTags, matchTags, TagsSearchParamsSchema, TagsMatchParamsSchema } from './tools/tags.js';
21
+ import { getTrends, TrendsParamsSchema } from './tools/trends.js';
22
+ import { getResearch, ResearchParamsSchema } from './tools/research.js';
23
+ // MCP Server
24
+ const server = new Server({
25
+ name: 'RagAlgo',
26
+ version: '1.0.2',
27
+ }, {
28
+ capabilities: {
29
+ tools: {},
30
+ },
31
+ });
32
+ // Tool definitions with improved descriptions for better AI routing
33
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
34
+ return {
35
+ tools: [
36
+ // ============================================================
37
+ // 🏷️ TAG TOOLS - MUST USE FIRST!
38
+ // ============================================================
39
+ {
40
+ name: 'search_tags',
41
+ description: `🔍 [TAG LOOKUP - USE FIRST] ALWAYS use this BEFORE other RagAlgo tools when user mentions any Korean stock, coin, or theme by NAME.
42
+
43
+ PRIMARY TOOL for converting names to tag_codes. Without correct tag_code, other tools will return inaccurate or empty results.
44
+
45
+ ALWAYS use when you see:
46
+ - Korean stock names: 삼성전자, SK하이닉스, 네이버, 카카오, LG에너지솔루션
47
+ - Crypto names: 비트코인, 이더리움, 리플, 솔라나
48
+ - Theme/sector names: 반도체, AI, 2차전지, 바이오
49
+
50
+ Examples: "삼성전자" → STK005930, "비트코인" → CRY_BTC, "반도체" → THM_반도체
51
+
52
+ CRITICAL: Call this first, then use the returned tag_code in other tools.`,
53
+ inputSchema: {
54
+ type: 'object',
55
+ properties: {
56
+ q: { type: 'string', description: 'Search query (e.g., 삼성, Samsung, 반도체, AI, Bitcoin)' },
57
+ type: { type: 'string', enum: ['STOCK', 'SECTOR', 'THEME', 'CRYPTO'], description: 'Tag type filter (optional)' },
58
+ limit: { type: 'number', description: 'Result count (default: 20)' },
59
+ },
60
+ required: ['q'],
61
+ },
62
+ },
63
+ // ============================================================
64
+ // 📊 SUMMARY TOOL - MOST EFFICIENT!
65
+ // ============================================================
66
+ {
67
+ name: 'get_snapshots',
68
+ description: `📊 [DAILY SUMMARY - MOST EFFICIENT] PRIMARY TOOL for Korean market overview. ALWAYS use this FIRST for general market questions.
69
+
70
+ This is the ONLY tool that returns news + chart + sentiment COMBINED in one call.
71
+ Prefer this over calling get_news + get_chart separately - much more efficient!
72
+
73
+ ALWAYS use when user asks:
74
+ - "오늘 시장 어때?" / "how's the market today?"
75
+ - "시장 요약해줘" / "market summary"
76
+ - "오늘 뉴스 좋은 거 뭐 있어?" / "what's hot today?"
77
+ - "전체적인 분위기 어때?" / "market sentiment"
78
+
79
+ [IMPORTANT] Snapshots are generated daily at 17:00 KST (market close).
80
+ If you request 'today' and get no results (because it's morning in KST), you MUST:
81
+ 1. Fetch 'yesterday's snapshot for context.
82
+ 2. Call 'get_news_scored' to get REAL-TIME news for the current day.
83
+
84
+ Returns per asset: news_count, avg_sentiment, bullish/bearish counts, chart_score, zone, price.
85
+
86
+ 🔗 BEST PRACTICE - Combine with web_search:
87
+ 1. Use get_snapshots FIRST for Korean market sentiment & chart data
88
+ 2. Then use web_search for latest breaking news or global context
89
+ Example: get_snapshots → "시장 하락세" → web_search "한국 증시 하락 원인" → 종합 분석`,
90
+ inputSchema: {
91
+ type: 'object',
92
+ properties: {
93
+ tag_code: { type: 'string', description: 'Tag code for specific asset (e.g., STK005930, CRY_BTC). Leave empty for market-wide overview.' },
94
+ date: { type: 'string', description: 'Date (YYYY-MM-DD). Default: today' },
95
+ days: { type: 'number', description: 'Recent N days for time-series (default: 7)' },
96
+ limit: { type: 'number', description: 'Result count' },
97
+ },
98
+ },
99
+ },
100
+ // ============================================================
101
+ // 📰 NEWS TOOLS
102
+ // ============================================================
103
+ {
104
+ name: 'get_news_scored',
105
+ description: `📰 [KOREAN NEWS WITH SENTIMENT] PRIMARY news tool for Korean market. Returns news WITH AI sentiment scores (-10 to +10).
106
+
107
+ Use for Korean stock/crypto news with sentiment analysis.
108
+
109
+ [NOTE] This tool AUTOMATICALLY filters out 0-score (Neutral/Noise) news to provide clear signals.
110
+ If you need raw/neutral news, use 'get_news' instead.
111
+
112
+ Use when user asks:
113
+ - "삼성전자 뉴스" / "Samsung news"
114
+ - "호재 뉴스 보여줘" / "show me bullish news"
115
+ - "비트코인 악재 있어?" / "any bearish news on Bitcoin?"
116
+ - "오늘 좋은 뉴스" / "today's positive news"
117
+
118
+ Filter by: tag, verdict (bullish/bearish/neutral), score range
119
+ Returns: title, summary, sentiment_score, verdict, tags
120
+
121
+ 🔗 BEST PRACTICE - Combine with web_search:
122
+ - RagAlgo: Sentiment-analyzed Korean market news (structured data)
123
+ - web_search: Real-time breaking news, global context, additional sources
124
+ Example workflow:
125
+ 1. get_news_scored(tag="삼성전자") → 감정 분석된 뉴스 목록
126
+ 2. web_search("삼성전자 최신 뉴스") → 실시간 속보
127
+ 3. Combine both for comprehensive analysis!
128
+
129
+ TIP: For market overview, use get_snapshots instead (more efficient).
130
+ TIP: Use search_tags first to get exact tag name.`,
131
+ inputSchema: {
132
+ type: 'object',
133
+ properties: {
134
+ tag: { type: 'string', description: 'Tag CODE (e.g., STK005930). Use search_tags first to get this code!' },
135
+ source: { type: 'string', description: 'Source filter' },
136
+ search: { type: 'string', description: 'Title search keyword' },
137
+ min_score: { type: 'number', description: 'Min sentiment score (-10 to 10)' },
138
+ max_score: { type: 'number', description: 'Max sentiment score (-10 to 10)' },
139
+ verdict: { type: 'string', enum: ['bullish', 'bearish', 'neutral'], description: 'Sentiment verdict filter' },
140
+ limit: { type: 'number', description: 'Result count (default: 20)' },
141
+ },
142
+ },
143
+ },
144
+ {
145
+ name: 'get_news',
146
+ description: `📰 [KOREAN NEWS - NO SCORES] Basic news without sentiment analysis. Use only when sentiment scores are not needed or for non-scored tier users.
147
+
148
+ Prefer get_news_scored over this for most use cases unless you want raw data including 0-score items.
149
+
150
+ Filter by: tag, source, date range
151
+ Returns: title, summary, url, tags, source`,
152
+ inputSchema: {
153
+ type: 'object',
154
+ properties: {
155
+ tag: { type: 'string', description: 'Tag filter (e.g., 삼성전자, 비트코인, 반도체)' },
156
+ source: { type: 'string', description: 'Source filter (e.g., 한경, 매경)' },
157
+ search: { type: 'string', description: 'Title search keyword' },
158
+ from_date: { type: 'string', description: 'Start date (YYYY-MM-DD)' },
159
+ to_date: { type: 'string', description: 'End date (YYYY-MM-DD)' },
160
+ limit: { type: 'number', description: 'Result count (default: 20, max: 100)' },
161
+ },
162
+ },
163
+ },
164
+ // ============================================================
165
+ // 📈 CHART/TECHNICAL ANALYSIS TOOLS
166
+ // ============================================================
167
+ {
168
+ name: 'get_chart_stock',
169
+ description: `📈 [KOREAN STOCK CHARTS] PRIMARY tool for Korean stock technical analysis. Returns momentum scores and trend zones.
170
+
171
+ ALWAYS use for Korean stock chart/technical questions.
172
+
173
+ [IMPORTANT] You MUST use 'search_tags' first to get the correct ticker (e.g., STK005930).
174
+
175
+ Use when user asks:
176
+ - "차트 강한 종목" / "stocks with strong momentum"
177
+ - "상승 추세 종목" / "uptrending stocks"
178
+ - "삼성전자 차트 어때?" / "how's Samsung's chart?"
179
+ - "기술적 분석" / "technical analysis"
180
+
181
+ Filter by: zone (STRONG_UP/UP_ZONE/NEUTRAL/DOWN_ZONE/STRONG_DOWN), market (KOSPI/KOSDAQ)
182
+ Returns: ticker, name, zone, oscillator_state, 5-day scores (d0-d4), last_price
183
+
184
+ 🔗 COMBINE with web_search for deeper analysis:
185
+ 1. get_chart_stock → "삼성전자 DOWN_ZONE"
186
+ 2. web_search "삼성전자 주가 하락 이유" → 하락 원인 파악
187
+ 3. Provide comprehensive technical + fundamental analysis!
188
+
189
+ TIP: Use search_tags first to get ticker from stock name.`,
190
+ inputSchema: {
191
+ type: 'object',
192
+ properties: {
193
+ ticker: { type: 'string', description: 'Stock ticker (e.g., 005930 for Samsung)' },
194
+ market: { type: 'string', enum: ['KOSPI', 'KOSDAQ'], description: 'Market type' },
195
+ zone: { type: 'string', enum: ['STRONG_UP', 'UP_ZONE', 'NEUTRAL', 'DOWN_ZONE', 'STRONG_DOWN'], description: 'Chart zone filter - use this to find strong/weak stocks' },
196
+ limit: { type: 'number', description: 'Result count' },
197
+ },
198
+ },
199
+ },
200
+ {
201
+ name: 'get_chart_coin',
202
+ description: `🪙 [CRYPTO CHARTS] PRIMARY tool for Korean crypto (Upbit) technical analysis. Returns momentum scores and trend zones.
203
+
204
+ ALWAYS use for Korean crypto chart questions.
205
+
206
+ [IMPORTANT] You MUST use 'search_tags' first to get the correct ticker (e.g., CRY_BTC).
207
+
208
+ Use when user asks:
209
+ - "비트코인 차트" / "Bitcoin chart"
210
+ - "상승 중인 코인" / "pumping coins"
211
+ - "코인 기술적 분석" / "crypto technical analysis"
212
+
213
+ Filter by: zone (STRONG_UP/UP_ZONE/NEUTRAL/DOWN_ZONE/STRONG_DOWN)
214
+ Returns: ticker, name, zone, oscillator_state, 10-candle scores (c0-c9, 12h intervals), last_price
215
+
216
+ 🔗 COMBINE with web_search for context:
217
+ 1. get_chart_coin → "비트코인 UP_ZONE"
218
+ 2. web_search "비트코인 상승 이유" → 상승 배경 파악`,
219
+ inputSchema: {
220
+ type: 'object',
221
+ properties: {
222
+ ticker: { type: 'string', description: 'Coin ticker (e.g., KRW-BTC for Bitcoin)' },
223
+ zone: { type: 'string', enum: ['STRONG_UP', 'UP_ZONE', 'NEUTRAL', 'DOWN_ZONE', 'STRONG_DOWN'], description: 'Chart zone filter' },
224
+ limit: { type: 'number', description: 'Result count' },
225
+ },
226
+ },
227
+ },
228
+ // ============================================================
229
+ // 6. 컨설팅 보고서 (신규!)
230
+ // ============================================================
231
+ {
232
+ name: 'get_research',
233
+ description: `📑 [RESEARCH] Get consulting firm reports (McKinsey, BCG, etc.)
234
+
235
+ Use for: "long-term trends", "sector outlook", "industry analysis"
236
+ Filter by: source, tag_code, market_outlook
237
+
238
+ Returns: AI summary in Korean, investment insights
239
+ Includes tag_codes for cross-referencing with news/charts.
240
+
241
+ ⚠️ This tool returns FULL chunked text. Analyze it to answer user questions.`,
242
+ inputSchema: {
243
+ type: 'object',
244
+ properties: {
245
+ tag_code: { type: 'string', description: 'Tag code (required). Use search_tags first.' },
246
+ limit: { type: 'number', description: 'Result count (default: 5)' },
247
+ source: { type: 'string', description: 'Source filter (mckinsey, goldman, etc.)' },
248
+ },
249
+ required: ['tag_code'],
250
+ },
251
+ },
252
+ // ============================================================
253
+ // 💰 FINANCIAL DATA TOOLS
254
+ // ============================================================
255
+ {
256
+ name: 'get_financials',
257
+ description: `💰 [KOREAN STOCK FUNDAMENTALS] PRIMARY tool for Korean stock financial data. Returns quarterly financial statements.
258
+
259
+ ALWAYS use for Korean stock fundamental analysis.
260
+
261
+ Use when user asks:
262
+ - "삼성전자 재무제표" / "Samsung financials"
263
+ - "PER 낮은 종목" / "low PER stocks"
264
+ - "ROE 높은 기업" / "high ROE companies"
265
+ - "저평가 종목" / "undervalued stocks"
266
+
267
+ Returns: PER, PBR, ROE, ROA, revenue, operating_income, net_income, debt_ratio, dividend_yield
268
+
269
+ 🔗 COMBINE with web_search:
270
+ 1. get_financials → "PER 5.2, ROE 15%"
271
+ 2. web_search "삼성전자 실적 전망" → 미래 실적 예측`,
272
+ inputSchema: {
273
+ type: 'object',
274
+ properties: {
275
+ ticker: { type: 'string', description: 'Stock ticker (e.g., 005930)' },
276
+ period: { type: 'string', description: 'Quarter (e.g., 2024Q3)' },
277
+ market: { type: 'string', enum: ['KOSPI', 'KOSDAQ'], description: 'Market type' },
278
+ periods: { type: 'number', description: 'Recent N quarters (default: 4)' },
279
+ limit: { type: 'number', description: 'Result count' },
280
+ },
281
+ },
282
+ },
283
+ // ============================================================
284
+ // 📉 TREND TOOLS
285
+ // ============================================================
286
+ {
287
+ name: 'get_trends',
288
+ description: `📉 [SENTIMENT TRENDS] Get historical sentiment trend for a specific asset over time.
289
+
290
+ Use when user asks:
291
+ - "삼성전자 지난주 분위기" / "Samsung sentiment last week"
292
+ - "비트코인 추세" / "Bitcoin trend"
293
+ - "최근 7일간 뉴스 동향" / "news trend over 7 days"
294
+
295
+ REQUIRES tag_code - use search_tags first!
296
+ Returns: daily news_count and avg_sentiment_score over N days
297
+
298
+ 🔗 COMBINE with web_search:
299
+ 1. get_trends → "지난주 감정 -2.5로 하락"
300
+ 2. web_search "삼성전자 지난주 이슈" → 하락 원인 파악`,
301
+ inputSchema: {
302
+ type: 'object',
303
+ properties: {
304
+ tag_code: { type: 'string', description: 'Tag code (e.g., STK005930, CRY_BTC) - REQUIRED. Use search_tags to find this first!' },
305
+ days: { type: 'number', description: 'Recent N days (default: 7, max: 30)' },
306
+ },
307
+ required: ['tag_code'],
308
+ },
309
+ },
310
+ // ============================================================
311
+ // 🏷️ AUTO-TAGGING TOOL
312
+ // ============================================================
313
+ {
314
+ name: 'match_tags',
315
+ description: `🏷️ [AUTO-TAG EXTRACTION] Extract stock/crypto/theme tags from any text. Useful for categorizing news or analyzing what topics a text mentions.
316
+
317
+ Use when:
318
+ - Analyzing what stocks/themes a news title mentions
319
+ - Auto-categorizing text content
320
+ - Finding related tags from a sentence
321
+
322
+ Input: any text (e.g., "삼성전자 HBM 대박 소식")
323
+ Returns: matched tags with confidence scores`,
324
+ inputSchema: {
325
+ type: 'object',
326
+ properties: {
327
+ text: { type: 'string', description: 'Text to analyze (e.g., "삼성전자 HBM 대박 소식")' },
328
+ types: { type: 'array', items: { type: 'string' }, description: 'Tag type filter (optional)' },
329
+ limit: { type: 'number', description: 'Result count (default: 10)' },
330
+ },
331
+ required: ['text'],
332
+ },
333
+ },
334
+ ],
335
+ };
336
+ });
337
+ // Tool call handler
338
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
339
+ const { name, arguments: args } = request.params;
340
+ try {
341
+ let result;
342
+ switch (name) {
343
+ case 'get_news':
344
+ result = await getNews(NewsParamsSchema.parse(args));
345
+ break;
346
+ case 'get_news_scored':
347
+ result = await getNewsScored(NewsScoredParamsSchema.parse(args));
348
+ break;
349
+ case 'get_chart_stock':
350
+ result = await getChartStock(ChartStockParamsSchema.parse(args));
351
+ break;
352
+ case 'get_chart_coin':
353
+ result = await getChartCoin(ChartCoinParamsSchema.parse(args));
354
+ break;
355
+ case 'get_research':
356
+ result = await getResearch(ResearchParamsSchema.parse(args));
357
+ break;
358
+ case 'get_financials':
359
+ result = await getFinancials(FinancialsParamsSchema.parse(args));
360
+ break;
361
+ case 'get_snapshots':
362
+ result = await getSnapshots(SnapshotsParamsSchema.parse(args));
363
+ break;
364
+ case 'search_tags':
365
+ result = await searchTags(TagsSearchParamsSchema.parse(args));
366
+ break;
367
+ case 'match_tags':
368
+ result = await matchTags(TagsMatchParamsSchema.parse(args));
369
+ break;
370
+ case 'get_trends':
371
+ result = await getTrends(TrendsParamsSchema.parse(args));
372
+ break;
373
+ default:
374
+ throw new Error(`Unknown tool: ${name}`);
375
+ }
376
+ return {
377
+ content: [
378
+ {
379
+ type: 'text',
380
+ text: JSON.stringify(result, null, 2),
381
+ },
382
+ ],
383
+ };
384
+ }
385
+ catch (error) {
386
+ const errorMessage = error instanceof Error ? error.message : String(error);
387
+ return {
388
+ content: [
389
+ {
390
+ type: 'text',
391
+ text: `Error: ${errorMessage}`,
392
+ },
393
+ ],
394
+ isError: true,
395
+ };
396
+ }
397
+ });
398
+ // Start server
399
+ async function main() {
400
+ // Check if running in stdio mode (command line argument or specific env var)
401
+ const isStdio = process.argv.includes('--stdio');
402
+ if (isStdio) {
403
+ const transport = new StdioServerTransport();
404
+ await server.connect(transport);
405
+ console.error('RagAlgo MCP Server started (Stdio Mode)');
406
+ }
407
+ else {
408
+ // SSE / HTTP Mode (Default for deployment)
409
+ const app = express();
410
+ const port = process.env.PORT || 8080;
411
+ app.use(cors());
412
+ app.use(express.json());
413
+ let transport = null;
414
+ app.get('/sse', async (req, res) => {
415
+ console.log('New SSE connection established');
416
+ transport = new SSEServerTransport('/messages', res);
417
+ await server.connect(transport);
418
+ });
419
+ app.post('/messages', async (req, res) => {
420
+ if (transport) {
421
+ await transport.handlePostMessage(req, res);
422
+ }
423
+ else {
424
+ res.status(404).json({ error: 'Session not found or connection not established' });
425
+ }
426
+ });
427
+ app.get('/health', (req, res) => {
428
+ res.status(200).json({ status: 'ok', version: '1.0.2' });
429
+ });
430
+ app.listen(port, () => {
431
+ console.log(`RagAlgo MCP Server listening on port ${port} (SSE Mode)`);
432
+ console.log(`- SSE Endpoint: http://localhost:${port}/sse`);
433
+ console.log(`- Health Check: http://localhost:${port}/health`);
434
+ });
435
+ }
436
+ }
437
+ main().catch((error) => {
438
+ console.error('Fatal error:', error);
439
+ process.exit(1);
440
+ });
@@ -0,0 +1,83 @@
1
+ /**
2
+ * 차트 관련 MCP Tools
3
+ */
4
+ import { z } from 'zod';
5
+ export declare const ChartStockParamsSchema: z.ZodObject<{
6
+ ticker: z.ZodOptional<z.ZodString>;
7
+ market: z.ZodOptional<z.ZodEnum<["KOSPI", "KOSDAQ"]>>;
8
+ zone: z.ZodOptional<z.ZodEnum<["STRONG_UP", "UP_ZONE", "NEUTRAL", "DOWN_ZONE", "STRONG_DOWN"]>>;
9
+ limit: z.ZodDefault<z.ZodNumber>;
10
+ }, "strip", z.ZodTypeAny, {
11
+ limit: number;
12
+ ticker?: string | undefined;
13
+ market?: "KOSPI" | "KOSDAQ" | undefined;
14
+ zone?: "STRONG_UP" | "UP_ZONE" | "NEUTRAL" | "DOWN_ZONE" | "STRONG_DOWN" | undefined;
15
+ }, {
16
+ limit?: number | undefined;
17
+ ticker?: string | undefined;
18
+ market?: "KOSPI" | "KOSDAQ" | undefined;
19
+ zone?: "STRONG_UP" | "UP_ZONE" | "NEUTRAL" | "DOWN_ZONE" | "STRONG_DOWN" | undefined;
20
+ }>;
21
+ export declare const ChartCoinParamsSchema: z.ZodObject<{
22
+ ticker: z.ZodOptional<z.ZodString>;
23
+ zone: z.ZodOptional<z.ZodEnum<["STRONG_UP", "UP_ZONE", "NEUTRAL", "DOWN_ZONE", "STRONG_DOWN"]>>;
24
+ limit: z.ZodDefault<z.ZodNumber>;
25
+ }, "strip", z.ZodTypeAny, {
26
+ limit: number;
27
+ ticker?: string | undefined;
28
+ zone?: "STRONG_UP" | "UP_ZONE" | "NEUTRAL" | "DOWN_ZONE" | "STRONG_DOWN" | undefined;
29
+ }, {
30
+ limit?: number | undefined;
31
+ ticker?: string | undefined;
32
+ zone?: "STRONG_UP" | "UP_ZONE" | "NEUTRAL" | "DOWN_ZONE" | "STRONG_DOWN" | undefined;
33
+ }>;
34
+ export type ChartStockParams = z.infer<typeof ChartStockParamsSchema>;
35
+ export type ChartCoinParams = z.infer<typeof ChartCoinParamsSchema>;
36
+ export declare function getChartStock(params: ChartStockParams): Promise<{
37
+ success: boolean;
38
+ data: {
39
+ ticker: string;
40
+ name: string;
41
+ market: string;
42
+ scores: number[];
43
+ zone: string;
44
+ oscillator_state: string;
45
+ analysis?: {
46
+ weekly_zone: string;
47
+ daily_momentum: string;
48
+ daily_signal: string;
49
+ };
50
+ outlook?: string;
51
+ last_price: number;
52
+ updated_at: string;
53
+ } | Array<{
54
+ ticker: string;
55
+ name: string;
56
+ market: string;
57
+ zone: string;
58
+ last_price: number;
59
+ }>;
60
+ }>;
61
+ export declare function getChartCoin(params: ChartCoinParams): Promise<{
62
+ success: boolean;
63
+ data: {
64
+ ticker: string;
65
+ name: string;
66
+ scores: number[];
67
+ zone: string;
68
+ oscillator_state: string;
69
+ analysis?: {
70
+ weekly_zone: string;
71
+ daily_momentum: string;
72
+ daily_signal: string;
73
+ };
74
+ outlook?: string;
75
+ last_price: number;
76
+ updated_at: string;
77
+ } | Array<{
78
+ ticker: string;
79
+ name: string;
80
+ zone: string;
81
+ last_price: number;
82
+ }>;
83
+ }>;