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 +4 -0
- package/.mcpregistry_github_token +1 -0
- package/.mcpregistry_registry_token +1 -0
- package/Dockerfile +23 -0
- package/README.md +73 -0
- package/android-chrome-192x192.png +0 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +440 -0
- package/dist/tools/chart.d.ts +83 -0
- package/dist/tools/chart.js +32 -0
- package/dist/tools/financials.d.ts +67 -0
- package/dist/tools/financials.js +21 -0
- package/dist/tools/news.d.ts +100 -0
- package/dist/tools/news.js +31 -0
- package/dist/tools/research.d.ts +34 -0
- package/dist/tools/research.js +18 -0
- package/dist/tools/snapshots.d.ts +48 -0
- package/dist/tools/snapshots.js +29 -0
- package/dist/tools/tags.d.ts +64 -0
- package/dist/tools/tags.js +27 -0
- package/dist/tools/trends.d.ts +33 -0
- package/dist/tools/trends.js +15 -0
- package/dist/utils/api.d.ts +6 -0
- package/dist/utils/api.js +59 -0
- package/mcp-publisher.exe +0 -0
- package/package.json +39 -0
- package/server.json +35 -0
- package/smithery.yaml +7 -0
- package/src/index.ts +477 -0
- package/src/tools/chart.ts +90 -0
- package/src/tools/financials.ts +67 -0
- package/src/tools/news.ts +67 -0
- package/src/tools/research.ts +40 -0
- package/src/tools/snapshots.ts +55 -0
- package/src/tools/tags.ts +61 -0
- package/src/tools/trends.ts +35 -0
- package/src/utils/api.ts +76 -0
- package/tsconfig.json +21 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 차트 관련 MCP Tools
|
|
3
|
+
*/
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { callApi } from '../utils/api.js';
|
|
6
|
+
// 주식 차트 파라미터 스키마
|
|
7
|
+
export const ChartStockParamsSchema = z.object({
|
|
8
|
+
ticker: z.string().optional().describe('종목 코드 (예: 005930)'),
|
|
9
|
+
market: z.enum(['KOSPI', 'KOSDAQ']).optional().describe('시장 구분'),
|
|
10
|
+
zone: z.enum(['STRONG_UP', 'UP_ZONE', 'NEUTRAL', 'DOWN_ZONE', 'STRONG_DOWN']).optional().describe('차트 구간'),
|
|
11
|
+
limit: z.number().min(1).max(100).default(20).describe('결과 수'),
|
|
12
|
+
});
|
|
13
|
+
// 코인 차트 파라미터 스키마
|
|
14
|
+
export const ChartCoinParamsSchema = z.object({
|
|
15
|
+
ticker: z.string().optional().describe('코인 코드 (예: KRW-BTC)'),
|
|
16
|
+
zone: z.enum(['STRONG_UP', 'UP_ZONE', 'NEUTRAL', 'DOWN_ZONE', 'STRONG_DOWN']).optional().describe('차트 구간'),
|
|
17
|
+
limit: z.number().min(1).max(100).default(20).describe('결과 수'),
|
|
18
|
+
});
|
|
19
|
+
// 주식 차트 조회
|
|
20
|
+
export async function getChartStock(params) {
|
|
21
|
+
const endpoint = params.ticker ? `chart-stock/${params.ticker}` : 'chart-stock';
|
|
22
|
+
const { ticker, ...queryParams } = params;
|
|
23
|
+
const result = await callApi(endpoint, queryParams);
|
|
24
|
+
return result;
|
|
25
|
+
}
|
|
26
|
+
// 코인 차트 조회
|
|
27
|
+
export async function getChartCoin(params) {
|
|
28
|
+
const endpoint = params.ticker ? `chart-coin/${params.ticker}` : 'chart-coin';
|
|
29
|
+
const { ticker, ...queryParams } = params;
|
|
30
|
+
const result = await callApi(endpoint, queryParams);
|
|
31
|
+
return result;
|
|
32
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 재무제표 관련 MCP Tools
|
|
3
|
+
*/
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
export declare const FinancialsParamsSchema: z.ZodObject<{
|
|
6
|
+
ticker: z.ZodOptional<z.ZodString>;
|
|
7
|
+
period: z.ZodOptional<z.ZodString>;
|
|
8
|
+
market: z.ZodOptional<z.ZodEnum<["KOSPI", "KOSDAQ"]>>;
|
|
9
|
+
periods: z.ZodDefault<z.ZodNumber>;
|
|
10
|
+
limit: z.ZodDefault<z.ZodNumber>;
|
|
11
|
+
offset: z.ZodDefault<z.ZodNumber>;
|
|
12
|
+
}, "strip", z.ZodTypeAny, {
|
|
13
|
+
limit: number;
|
|
14
|
+
offset: number;
|
|
15
|
+
periods: number;
|
|
16
|
+
ticker?: string | undefined;
|
|
17
|
+
market?: "KOSPI" | "KOSDAQ" | undefined;
|
|
18
|
+
period?: string | undefined;
|
|
19
|
+
}, {
|
|
20
|
+
limit?: number | undefined;
|
|
21
|
+
offset?: number | undefined;
|
|
22
|
+
ticker?: string | undefined;
|
|
23
|
+
market?: "KOSPI" | "KOSDAQ" | undefined;
|
|
24
|
+
period?: string | undefined;
|
|
25
|
+
periods?: number | undefined;
|
|
26
|
+
}>;
|
|
27
|
+
export type FinancialsParams = z.infer<typeof FinancialsParamsSchema>;
|
|
28
|
+
export declare function getFinancials(params: FinancialsParams): Promise<{
|
|
29
|
+
success: boolean;
|
|
30
|
+
data: {
|
|
31
|
+
ticker: string;
|
|
32
|
+
name: string;
|
|
33
|
+
market: string;
|
|
34
|
+
quarters: Array<{
|
|
35
|
+
period: string;
|
|
36
|
+
investment_metrics: {
|
|
37
|
+
per: number;
|
|
38
|
+
pbr: number;
|
|
39
|
+
eps: number;
|
|
40
|
+
bps: number;
|
|
41
|
+
div_yield: number;
|
|
42
|
+
};
|
|
43
|
+
income_statement: {
|
|
44
|
+
revenue: number;
|
|
45
|
+
operating_income: number;
|
|
46
|
+
net_income: number;
|
|
47
|
+
};
|
|
48
|
+
balance_sheet: {
|
|
49
|
+
total_assets: number;
|
|
50
|
+
total_liabilities: number;
|
|
51
|
+
total_equity: number;
|
|
52
|
+
};
|
|
53
|
+
ratios: {
|
|
54
|
+
debt_ratio: number;
|
|
55
|
+
roe: number;
|
|
56
|
+
roa: number;
|
|
57
|
+
};
|
|
58
|
+
}>;
|
|
59
|
+
} | Array<{
|
|
60
|
+
ticker: string;
|
|
61
|
+
name: string;
|
|
62
|
+
period: string;
|
|
63
|
+
per: number;
|
|
64
|
+
pbr: number;
|
|
65
|
+
roe: number;
|
|
66
|
+
}>;
|
|
67
|
+
}>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 재무제표 관련 MCP Tools
|
|
3
|
+
*/
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { callApi } from '../utils/api.js';
|
|
6
|
+
// 재무제표 파라미터 스키마
|
|
7
|
+
export const FinancialsParamsSchema = z.object({
|
|
8
|
+
ticker: z.string().optional().describe('종목 코드 (예: 005930)'),
|
|
9
|
+
period: z.string().optional().describe('분기 (예: 2024Q3)'),
|
|
10
|
+
market: z.enum(['KOSPI', 'KOSDAQ']).optional().describe('시장 구분'),
|
|
11
|
+
periods: z.number().min(1).max(8).default(4).describe('최근 N분기 (기본: 4)'),
|
|
12
|
+
limit: z.number().min(1).max(200).default(50).describe('결과 수'),
|
|
13
|
+
offset: z.number().min(0).default(0).describe('페이지네이션 오프셋'),
|
|
14
|
+
});
|
|
15
|
+
// 재무제표 조회
|
|
16
|
+
export async function getFinancials(params) {
|
|
17
|
+
const endpoint = params.ticker ? `financials/${params.ticker}` : 'financials';
|
|
18
|
+
const { ticker, ...queryParams } = params;
|
|
19
|
+
const result = await callApi(endpoint, queryParams);
|
|
20
|
+
return result;
|
|
21
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 뉴스 관련 MCP Tools
|
|
3
|
+
*/
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
export declare const NewsParamsSchema: z.ZodObject<{
|
|
6
|
+
tag: z.ZodOptional<z.ZodString>;
|
|
7
|
+
source: z.ZodOptional<z.ZodString>;
|
|
8
|
+
search: z.ZodOptional<z.ZodString>;
|
|
9
|
+
from_date: z.ZodOptional<z.ZodString>;
|
|
10
|
+
to_date: z.ZodOptional<z.ZodString>;
|
|
11
|
+
limit: z.ZodDefault<z.ZodNumber>;
|
|
12
|
+
offset: z.ZodDefault<z.ZodNumber>;
|
|
13
|
+
}, "strip", z.ZodTypeAny, {
|
|
14
|
+
limit: number;
|
|
15
|
+
offset: number;
|
|
16
|
+
tag?: string | undefined;
|
|
17
|
+
source?: string | undefined;
|
|
18
|
+
search?: string | undefined;
|
|
19
|
+
from_date?: string | undefined;
|
|
20
|
+
to_date?: string | undefined;
|
|
21
|
+
}, {
|
|
22
|
+
tag?: string | undefined;
|
|
23
|
+
source?: string | undefined;
|
|
24
|
+
search?: string | undefined;
|
|
25
|
+
from_date?: string | undefined;
|
|
26
|
+
to_date?: string | undefined;
|
|
27
|
+
limit?: number | undefined;
|
|
28
|
+
offset?: number | undefined;
|
|
29
|
+
}>;
|
|
30
|
+
export declare const NewsScoredParamsSchema: z.ZodObject<{
|
|
31
|
+
tag: z.ZodOptional<z.ZodString>;
|
|
32
|
+
source: z.ZodOptional<z.ZodString>;
|
|
33
|
+
search: z.ZodOptional<z.ZodString>;
|
|
34
|
+
from_date: z.ZodOptional<z.ZodString>;
|
|
35
|
+
to_date: z.ZodOptional<z.ZodString>;
|
|
36
|
+
limit: z.ZodDefault<z.ZodNumber>;
|
|
37
|
+
offset: z.ZodDefault<z.ZodNumber>;
|
|
38
|
+
} & {
|
|
39
|
+
min_score: z.ZodOptional<z.ZodNumber>;
|
|
40
|
+
max_score: z.ZodOptional<z.ZodNumber>;
|
|
41
|
+
verdict: z.ZodOptional<z.ZodEnum<["bullish", "bearish", "neutral"]>>;
|
|
42
|
+
}, "strip", z.ZodTypeAny, {
|
|
43
|
+
limit: number;
|
|
44
|
+
offset: number;
|
|
45
|
+
tag?: string | undefined;
|
|
46
|
+
source?: string | undefined;
|
|
47
|
+
search?: string | undefined;
|
|
48
|
+
from_date?: string | undefined;
|
|
49
|
+
to_date?: string | undefined;
|
|
50
|
+
min_score?: number | undefined;
|
|
51
|
+
max_score?: number | undefined;
|
|
52
|
+
verdict?: "bullish" | "bearish" | "neutral" | undefined;
|
|
53
|
+
}, {
|
|
54
|
+
tag?: string | undefined;
|
|
55
|
+
source?: string | undefined;
|
|
56
|
+
search?: string | undefined;
|
|
57
|
+
from_date?: string | undefined;
|
|
58
|
+
to_date?: string | undefined;
|
|
59
|
+
limit?: number | undefined;
|
|
60
|
+
offset?: number | undefined;
|
|
61
|
+
min_score?: number | undefined;
|
|
62
|
+
max_score?: number | undefined;
|
|
63
|
+
verdict?: "bullish" | "bearish" | "neutral" | undefined;
|
|
64
|
+
}>;
|
|
65
|
+
export type NewsParams = z.infer<typeof NewsParamsSchema>;
|
|
66
|
+
export type NewsScoredParams = z.infer<typeof NewsScoredParamsSchema>;
|
|
67
|
+
export declare function getNews(params: NewsParams): Promise<{
|
|
68
|
+
success: boolean;
|
|
69
|
+
data: Array<{
|
|
70
|
+
id: number;
|
|
71
|
+
title: string;
|
|
72
|
+
summary: string;
|
|
73
|
+
tags: string[];
|
|
74
|
+
url: string;
|
|
75
|
+
source: string;
|
|
76
|
+
created_at: string;
|
|
77
|
+
}>;
|
|
78
|
+
meta: {
|
|
79
|
+
count: number;
|
|
80
|
+
tier: string;
|
|
81
|
+
};
|
|
82
|
+
}>;
|
|
83
|
+
export declare function getNewsScored(params: NewsScoredParams): Promise<{
|
|
84
|
+
success: boolean;
|
|
85
|
+
data: Array<{
|
|
86
|
+
id: number;
|
|
87
|
+
title: string;
|
|
88
|
+
summary: string;
|
|
89
|
+
tags: string[];
|
|
90
|
+
sentiment_score: number;
|
|
91
|
+
verdict: string;
|
|
92
|
+
url: string;
|
|
93
|
+
source: string;
|
|
94
|
+
created_at: string;
|
|
95
|
+
}>;
|
|
96
|
+
meta: {
|
|
97
|
+
count: number;
|
|
98
|
+
tier: string;
|
|
99
|
+
};
|
|
100
|
+
}>;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 뉴스 관련 MCP Tools
|
|
3
|
+
*/
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { callApi } from '../utils/api.js';
|
|
6
|
+
// 뉴스 파라미터 스키마
|
|
7
|
+
export const NewsParamsSchema = z.object({
|
|
8
|
+
tag: z.string().optional().describe('태그 코드 (search_tags 결과값, 예: STK005930, THM001)'),
|
|
9
|
+
source: z.string().optional().describe('소스 필터 (예: 한경, 매경)'),
|
|
10
|
+
search: z.string().optional().describe('제목 검색어'),
|
|
11
|
+
from_date: z.string().optional().describe('시작일 (YYYY-MM-DD)'),
|
|
12
|
+
to_date: z.string().optional().describe('종료일 (YYYY-MM-DD)'),
|
|
13
|
+
limit: z.number().min(1).max(100).default(20).describe('결과 수 (기본: 20, 최대: 100)'),
|
|
14
|
+
offset: z.number().min(0).default(0).describe('페이지네이션 오프셋'),
|
|
15
|
+
});
|
|
16
|
+
// 점수 포함 뉴스 파라미터 스키마
|
|
17
|
+
export const NewsScoredParamsSchema = NewsParamsSchema.extend({
|
|
18
|
+
min_score: z.number().min(-10).max(10).optional().describe('최소 감정 점수 (-10~10)'),
|
|
19
|
+
max_score: z.number().min(-10).max(10).optional().describe('최대 감정 점수 (-10~10)'),
|
|
20
|
+
verdict: z.enum(['bullish', 'bearish', 'neutral']).optional().describe('판정 필터'),
|
|
21
|
+
});
|
|
22
|
+
// 뉴스 조회 (점수 제외)
|
|
23
|
+
export async function getNews(params) {
|
|
24
|
+
const result = await callApi('news', params);
|
|
25
|
+
return result;
|
|
26
|
+
}
|
|
27
|
+
// 뉴스 조회 (점수 포함)
|
|
28
|
+
export async function getNewsScored(params) {
|
|
29
|
+
const result = await callApi('news-scored', params);
|
|
30
|
+
return result;
|
|
31
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 컨설팅 보고서 관련 MCP Tools
|
|
3
|
+
*/
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
export declare const ResearchParamsSchema: z.ZodObject<{
|
|
6
|
+
tag_code: z.ZodString;
|
|
7
|
+
limit: z.ZodDefault<z.ZodNumber>;
|
|
8
|
+
source: z.ZodOptional<z.ZodString>;
|
|
9
|
+
}, "strip", z.ZodTypeAny, {
|
|
10
|
+
limit: number;
|
|
11
|
+
tag_code: string;
|
|
12
|
+
source?: string | undefined;
|
|
13
|
+
}, {
|
|
14
|
+
tag_code: string;
|
|
15
|
+
source?: string | undefined;
|
|
16
|
+
limit?: number | undefined;
|
|
17
|
+
}>;
|
|
18
|
+
export type ResearchParams = z.infer<typeof ResearchParamsSchema>;
|
|
19
|
+
export declare function getResearch(params: ResearchParams): Promise<{
|
|
20
|
+
tag_code: string;
|
|
21
|
+
tag_name: string | null;
|
|
22
|
+
research_count: number;
|
|
23
|
+
research: Array<{
|
|
24
|
+
id: number;
|
|
25
|
+
title: string;
|
|
26
|
+
source: string;
|
|
27
|
+
content_type: string;
|
|
28
|
+
published_at: string | null;
|
|
29
|
+
chunks: Array<{
|
|
30
|
+
section: string;
|
|
31
|
+
content: string;
|
|
32
|
+
}>;
|
|
33
|
+
}>;
|
|
34
|
+
}>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 컨설팅 보고서 관련 MCP Tools
|
|
3
|
+
*/
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { callApi } from '../utils/api.js';
|
|
6
|
+
const API_BASE = 'https://ragalgo-research-production.up.railway.app'; // 혹시 몰라 남겨룸, 하지만 callApi 사용시 Supabase Edge Function 호출
|
|
7
|
+
// 보고서 조회 파라미터 스키마
|
|
8
|
+
export const ResearchParamsSchema = z.object({
|
|
9
|
+
tag_code: z.string().describe('태그 코드 (필수). search_tags로 먼저 조회하세요.'),
|
|
10
|
+
limit: z.number().min(1).max(10).default(5).describe('보고서 수 (기본 5, 최대 10)'),
|
|
11
|
+
source: z.string().optional().describe('출처 필터 (선택): mckinsey, goldman, bcg, lg_research 등'),
|
|
12
|
+
});
|
|
13
|
+
// 보고서 조회
|
|
14
|
+
export async function getResearch(params) {
|
|
15
|
+
// Supabase Edge Function 호출
|
|
16
|
+
const result = await callApi('research', params); // 'research' function 호출
|
|
17
|
+
return result;
|
|
18
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 스냅샷 관련 MCP Tools
|
|
3
|
+
*/
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
export declare const SnapshotsParamsSchema: z.ZodObject<{
|
|
6
|
+
tag_code: z.ZodOptional<z.ZodString>;
|
|
7
|
+
date: z.ZodOptional<z.ZodString>;
|
|
8
|
+
days: z.ZodDefault<z.ZodNumber>;
|
|
9
|
+
limit: z.ZodDefault<z.ZodNumber>;
|
|
10
|
+
offset: z.ZodDefault<z.ZodNumber>;
|
|
11
|
+
}, "strip", z.ZodTypeAny, {
|
|
12
|
+
limit: number;
|
|
13
|
+
offset: number;
|
|
14
|
+
days: number;
|
|
15
|
+
tag_code?: string | undefined;
|
|
16
|
+
date?: string | undefined;
|
|
17
|
+
}, {
|
|
18
|
+
limit?: number | undefined;
|
|
19
|
+
offset?: number | undefined;
|
|
20
|
+
tag_code?: string | undefined;
|
|
21
|
+
date?: string | undefined;
|
|
22
|
+
days?: number | undefined;
|
|
23
|
+
}>;
|
|
24
|
+
export type SnapshotsParams = z.infer<typeof SnapshotsParamsSchema>;
|
|
25
|
+
export declare function getSnapshots(params: SnapshotsParams): Promise<{
|
|
26
|
+
success: boolean;
|
|
27
|
+
data: Array<{
|
|
28
|
+
tag_code: string;
|
|
29
|
+
snapshot_date: string;
|
|
30
|
+
news_count: number;
|
|
31
|
+
news_avg_score: number;
|
|
32
|
+
news_max_score: number;
|
|
33
|
+
news_min_score: number;
|
|
34
|
+
news_bullish_count: number;
|
|
35
|
+
news_bearish_count: number;
|
|
36
|
+
news_neutral_count: number;
|
|
37
|
+
research_count?: number;
|
|
38
|
+
research_outlook?: string;
|
|
39
|
+
chart_score: number;
|
|
40
|
+
chart_zone: string;
|
|
41
|
+
last_price: number;
|
|
42
|
+
}>;
|
|
43
|
+
meta: {
|
|
44
|
+
count: number;
|
|
45
|
+
date?: string;
|
|
46
|
+
days?: number;
|
|
47
|
+
};
|
|
48
|
+
}>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 스냅샷 관련 MCP Tools
|
|
3
|
+
*/
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { callApi } from '../utils/api.js';
|
|
6
|
+
// 스냅샷 파라미터 스키마
|
|
7
|
+
export const SnapshotsParamsSchema = z.object({
|
|
8
|
+
tag_code: z.string().optional().describe('태그 코드 (예: STK005930)'),
|
|
9
|
+
date: z.string().optional().describe('날짜 (YYYY-MM-DD)'),
|
|
10
|
+
days: z.number().min(1).max(30).default(7).describe('최근 N일 (기본: 7)'),
|
|
11
|
+
limit: z.number().min(1).max(100).default(50).describe('결과 수'),
|
|
12
|
+
offset: z.number().min(0).default(0).describe('페이지네이션 오프셋'),
|
|
13
|
+
});
|
|
14
|
+
// 스냅샷 조회
|
|
15
|
+
// [IMPORTANT] Snapshots are generated daily at 17:00 KST (market close).
|
|
16
|
+
// If you request 'today' and get no results (because it's morning in KST),
|
|
17
|
+
// you MUST:
|
|
18
|
+
// 1. Fetch 'yesterday's snapshot for context.
|
|
19
|
+
// 2. Call 'get_news_scored' to get REAL-TIME news for the current day.
|
|
20
|
+
export async function getSnapshots(params) {
|
|
21
|
+
const endpoint = 'snapshots';
|
|
22
|
+
const { tag_code, ...queryParams } = params;
|
|
23
|
+
// 태그 코드가 있으면 쿼리 파라미터에 추가
|
|
24
|
+
if (tag_code) {
|
|
25
|
+
queryParams.tag_code = tag_code;
|
|
26
|
+
}
|
|
27
|
+
const result = await callApi(endpoint, queryParams);
|
|
28
|
+
return result;
|
|
29
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 태그 관련 MCP Tools
|
|
3
|
+
*/
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
export declare const TagsSearchParamsSchema: z.ZodObject<{
|
|
6
|
+
q: z.ZodString;
|
|
7
|
+
type: z.ZodOptional<z.ZodEnum<["STOCK", "SECTOR", "THEME", "CRYPTO"]>>;
|
|
8
|
+
limit: z.ZodDefault<z.ZodNumber>;
|
|
9
|
+
}, "strip", z.ZodTypeAny, {
|
|
10
|
+
limit: number;
|
|
11
|
+
q: string;
|
|
12
|
+
type?: "STOCK" | "SECTOR" | "THEME" | "CRYPTO" | undefined;
|
|
13
|
+
}, {
|
|
14
|
+
q: string;
|
|
15
|
+
limit?: number | undefined;
|
|
16
|
+
type?: "STOCK" | "SECTOR" | "THEME" | "CRYPTO" | undefined;
|
|
17
|
+
}>;
|
|
18
|
+
export declare const TagsMatchParamsSchema: z.ZodObject<{
|
|
19
|
+
text: z.ZodString;
|
|
20
|
+
types: z.ZodOptional<z.ZodArray<z.ZodEnum<["STOCK", "SECTOR", "THEME", "CRYPTO"]>, "many">>;
|
|
21
|
+
limit: z.ZodDefault<z.ZodNumber>;
|
|
22
|
+
}, "strip", z.ZodTypeAny, {
|
|
23
|
+
limit: number;
|
|
24
|
+
text: string;
|
|
25
|
+
types?: ("STOCK" | "SECTOR" | "THEME" | "CRYPTO")[] | undefined;
|
|
26
|
+
}, {
|
|
27
|
+
text: string;
|
|
28
|
+
limit?: number | undefined;
|
|
29
|
+
types?: ("STOCK" | "SECTOR" | "THEME" | "CRYPTO")[] | undefined;
|
|
30
|
+
}>;
|
|
31
|
+
export type TagsSearchParams = z.infer<typeof TagsSearchParamsSchema>;
|
|
32
|
+
export type TagsMatchParams = z.infer<typeof TagsMatchParamsSchema>;
|
|
33
|
+
export declare function searchTags(params: TagsSearchParams): Promise<{
|
|
34
|
+
success: boolean;
|
|
35
|
+
data: Array<{
|
|
36
|
+
tag_code: string;
|
|
37
|
+
tag_type: string;
|
|
38
|
+
name: string;
|
|
39
|
+
name_en?: string;
|
|
40
|
+
match_type: string;
|
|
41
|
+
usage_count: number;
|
|
42
|
+
}>;
|
|
43
|
+
meta: {
|
|
44
|
+
query: string;
|
|
45
|
+
count: number;
|
|
46
|
+
};
|
|
47
|
+
}>;
|
|
48
|
+
export declare function matchTags(params: TagsMatchParams): Promise<{
|
|
49
|
+
success: boolean;
|
|
50
|
+
data: {
|
|
51
|
+
matches: Array<{
|
|
52
|
+
tag_code: string;
|
|
53
|
+
tag_type: string;
|
|
54
|
+
name: string;
|
|
55
|
+
match_type: string;
|
|
56
|
+
}>;
|
|
57
|
+
keywords_extracted: string[];
|
|
58
|
+
keywords_matched: string[];
|
|
59
|
+
};
|
|
60
|
+
meta: {
|
|
61
|
+
input_length: number;
|
|
62
|
+
keywords_count: number;
|
|
63
|
+
};
|
|
64
|
+
}>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 태그 관련 MCP Tools
|
|
3
|
+
*/
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { callApi, callApiPost } from '../utils/api.js';
|
|
6
|
+
// 태그 검색 파라미터 스키마
|
|
7
|
+
export const TagsSearchParamsSchema = z.object({
|
|
8
|
+
q: z.string().describe('검색어 (예: 삼성, 반도체)'),
|
|
9
|
+
type: z.enum(['STOCK', 'SECTOR', 'THEME', 'CRYPTO']).optional().describe('태그 타입'),
|
|
10
|
+
limit: z.number().min(1).max(50).default(20).describe('결과 수'),
|
|
11
|
+
});
|
|
12
|
+
// 태그 매칭 파라미터 스키마
|
|
13
|
+
export const TagsMatchParamsSchema = z.object({
|
|
14
|
+
text: z.string().describe('매칭할 텍스트 (예: 삼성전자 HBM 대박)'),
|
|
15
|
+
types: z.array(z.enum(['STOCK', 'SECTOR', 'THEME', 'CRYPTO'])).optional().describe('태그 타입 필터'),
|
|
16
|
+
limit: z.number().min(1).max(20).default(10).describe('결과 수'),
|
|
17
|
+
});
|
|
18
|
+
// 태그 검색
|
|
19
|
+
export async function searchTags(params) {
|
|
20
|
+
const result = await callApi('tags/search', params);
|
|
21
|
+
return result;
|
|
22
|
+
}
|
|
23
|
+
// 태그 매칭 (텍스트 → 태그)
|
|
24
|
+
export async function matchTags(params) {
|
|
25
|
+
const result = await callApiPost('tags-match', params);
|
|
26
|
+
return result;
|
|
27
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 트렌드 관련 MCP Tools
|
|
3
|
+
*/
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
export declare const TrendsParamsSchema: z.ZodObject<{
|
|
6
|
+
tag_code: z.ZodString;
|
|
7
|
+
days: z.ZodDefault<z.ZodNumber>;
|
|
8
|
+
}, "strip", z.ZodTypeAny, {
|
|
9
|
+
tag_code: string;
|
|
10
|
+
days: number;
|
|
11
|
+
}, {
|
|
12
|
+
tag_code: string;
|
|
13
|
+
days?: number | undefined;
|
|
14
|
+
}>;
|
|
15
|
+
export type TrendsParams = z.infer<typeof TrendsParamsSchema>;
|
|
16
|
+
export declare function getTrends(params: TrendsParams): Promise<{
|
|
17
|
+
success: boolean;
|
|
18
|
+
tag: {
|
|
19
|
+
code: string;
|
|
20
|
+
name: string;
|
|
21
|
+
type: string;
|
|
22
|
+
name_en?: string;
|
|
23
|
+
};
|
|
24
|
+
trend: Array<{
|
|
25
|
+
date: string;
|
|
26
|
+
count: number;
|
|
27
|
+
avg_score: number;
|
|
28
|
+
}>;
|
|
29
|
+
meta: {
|
|
30
|
+
days: number;
|
|
31
|
+
total_news: number;
|
|
32
|
+
};
|
|
33
|
+
}>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 트렌드 관련 MCP Tools
|
|
3
|
+
*/
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { callApi } from '../utils/api.js';
|
|
6
|
+
// 트렌드 파라미터 스키마
|
|
7
|
+
export const TrendsParamsSchema = z.object({
|
|
8
|
+
tag_code: z.string().describe('태그 코드 (예: STK005930)'),
|
|
9
|
+
days: z.number().min(1).max(30).default(7).describe('최근 N일 (기본: 7)'),
|
|
10
|
+
});
|
|
11
|
+
// 트렌드 조회
|
|
12
|
+
export async function getTrends(params) {
|
|
13
|
+
const result = await callApi('trends', params);
|
|
14
|
+
return result;
|
|
15
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RagAlgo API 유틸리티
|
|
3
|
+
* Supabase Edge Functions 호출
|
|
4
|
+
*/
|
|
5
|
+
export declare function callApi<T>(endpoint: string, params?: Record<string, string | number | undefined>): Promise<T>;
|
|
6
|
+
export declare function callApiPost<T>(endpoint: string, body: Record<string, unknown>): Promise<T>;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RagAlgo API 유틸리티
|
|
3
|
+
* Supabase Edge Functions 호출
|
|
4
|
+
*/
|
|
5
|
+
const SUPABASE_URL = 'https://xunrsikkybgxkybjzrgz.supabase.co/functions/v1';
|
|
6
|
+
const SUPABASE_ANON_KEY = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Inh1bnJzaWtreWJneGt5Ymp6cmd6Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3NjQ0NTExNTgsImV4cCI6MjA4MDAyNzE1OH0.SsXri828-Rf0gHlu4Bls-pewhfMNNII4mbiuLnc9ACs';
|
|
7
|
+
// 환경변수에서 API 키 가져오기
|
|
8
|
+
const getApiKey = () => {
|
|
9
|
+
const key = process.env.RAGALGO_API_KEY;
|
|
10
|
+
if (!key) {
|
|
11
|
+
throw new Error('RAGALGO_API_KEY 환경변수가 설정되지 않았습니다.');
|
|
12
|
+
}
|
|
13
|
+
return key;
|
|
14
|
+
};
|
|
15
|
+
// API 호출 기본 함수
|
|
16
|
+
export async function callApi(endpoint, params) {
|
|
17
|
+
const apiKey = getApiKey();
|
|
18
|
+
// 쿼리 파라미터 생성
|
|
19
|
+
const url = new URL(`${SUPABASE_URL}/${endpoint}`);
|
|
20
|
+
if (params) {
|
|
21
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
22
|
+
if (value !== undefined) {
|
|
23
|
+
url.searchParams.append(key, String(value));
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
const response = await fetch(url.toString(), {
|
|
28
|
+
method: 'GET',
|
|
29
|
+
headers: {
|
|
30
|
+
'Authorization': `Bearer ${SUPABASE_ANON_KEY}`,
|
|
31
|
+
'x-api-key': apiKey,
|
|
32
|
+
'Content-Type': 'application/json',
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
if (!response.ok) {
|
|
36
|
+
const error = await response.text();
|
|
37
|
+
throw new Error(`API 호출 실패: ${response.status} - ${error}`);
|
|
38
|
+
}
|
|
39
|
+
return response.json();
|
|
40
|
+
}
|
|
41
|
+
// POST API 호출
|
|
42
|
+
export async function callApiPost(endpoint, body) {
|
|
43
|
+
const apiKey = getApiKey();
|
|
44
|
+
const url = `${SUPABASE_URL}/${endpoint}`;
|
|
45
|
+
const response = await fetch(url, {
|
|
46
|
+
method: 'POST',
|
|
47
|
+
headers: {
|
|
48
|
+
'Authorization': `Bearer ${SUPABASE_ANON_KEY}`,
|
|
49
|
+
'x-api-key': apiKey,
|
|
50
|
+
'Content-Type': 'application/json',
|
|
51
|
+
},
|
|
52
|
+
body: JSON.stringify(body),
|
|
53
|
+
});
|
|
54
|
+
if (!response.ok) {
|
|
55
|
+
const error = await response.text();
|
|
56
|
+
throw new Error(`API 호출 실패: ${response.status} - ${error}`);
|
|
57
|
+
}
|
|
58
|
+
return response.json();
|
|
59
|
+
}
|
|
Binary file
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ragalgo-mcp-server",
|
|
3
|
+
"version": "1.0.4",
|
|
4
|
+
"mcpName": "io.github.kokogo100/ragalgo",
|
|
5
|
+
"description": "Dynamic RAG Engine for AI Reliability. We provide mathematically scored context & sanitized data to prevent hallucinations in both static & volatile domains (starting with Korean Finance).",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"ragalgo-mcp-server": "./dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"type": "module",
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "npx tsc",
|
|
13
|
+
"start": "node dist/index.js",
|
|
14
|
+
"dev": "npx tsx src/index.ts"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"mcp",
|
|
18
|
+
"rag",
|
|
19
|
+
"ai-reliability",
|
|
20
|
+
"context-scoring",
|
|
21
|
+
"finance",
|
|
22
|
+
"korea-market"
|
|
23
|
+
],
|
|
24
|
+
"author": "RagAlgo Team",
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
28
|
+
"cors": "^2.8.5",
|
|
29
|
+
"express": "^5.2.1",
|
|
30
|
+
"zod": "^3.22.0"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@types/cors": "^2.8.19",
|
|
34
|
+
"@types/express": "^5.0.6",
|
|
35
|
+
"@types/node": "^20.19.26",
|
|
36
|
+
"tsx": "^4.21.0",
|
|
37
|
+
"typescript": "^5.9.3"
|
|
38
|
+
}
|
|
39
|
+
}
|
package/server.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://modelcontextprotocol.io/schema/server.schema.json",
|
|
3
|
+
"name": "io.github.kokogo100/ragalgo",
|
|
4
|
+
"displayName": "RagAlgo",
|
|
5
|
+
"description": "Dynamic RAG Engine for AI Reliability. Prevents hallucinations in Korean Finance and Crypto markets with mathematically scored context.",
|
|
6
|
+
"version": "1.0.0",
|
|
7
|
+
"homepage": "https://ragalgo.com",
|
|
8
|
+
"license": "MIT",
|
|
9
|
+
"packages": [
|
|
10
|
+
{
|
|
11
|
+
"registry_type": "npm",
|
|
12
|
+
"identifier": "ragalgo-mcp-server",
|
|
13
|
+
"version": "1.0.4",
|
|
14
|
+
"transport": {
|
|
15
|
+
"type": "stdio"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
],
|
|
19
|
+
"categories": [
|
|
20
|
+
"Finance",
|
|
21
|
+
"Data",
|
|
22
|
+
"Analysis"
|
|
23
|
+
],
|
|
24
|
+
"keywords": [
|
|
25
|
+
"finance",
|
|
26
|
+
"korea",
|
|
27
|
+
"rag",
|
|
28
|
+
"stock",
|
|
29
|
+
"crypto",
|
|
30
|
+
"analysis",
|
|
31
|
+
"sentiment",
|
|
32
|
+
"korean-market"
|
|
33
|
+
],
|
|
34
|
+
"icon": "https://raw.githubusercontent.com/kokogo100/ragalgo-mcp-server/main/android-chrome-192x192.png"
|
|
35
|
+
}
|