ragalgo-mcp-server 1.0.5 → 1.0.7

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.
@@ -4,30 +4,33 @@
4
4
  import { z } from 'zod';
5
5
  export declare const ChartStockParamsSchema: z.ZodObject<{
6
6
  ticker: z.ZodOptional<z.ZodString>;
7
- market: z.ZodOptional<z.ZodEnum<{
8
- KOSPI: "KOSPI";
9
- KOSDAQ: "KOSDAQ";
10
- }>>;
11
- zone: z.ZodOptional<z.ZodEnum<{
12
- STRONG_UP: "STRONG_UP";
13
- UP_ZONE: "UP_ZONE";
14
- NEUTRAL: "NEUTRAL";
15
- DOWN_ZONE: "DOWN_ZONE";
16
- STRONG_DOWN: "STRONG_DOWN";
17
- }>>;
7
+ market: z.ZodOptional<z.ZodEnum<["KOSPI", "KOSDAQ", "US", "JP", "UK"]>>;
8
+ zone: z.ZodOptional<z.ZodEnum<["STRONG_UP", "UP_ZONE", "NEUTRAL", "DOWN_ZONE", "STRONG_DOWN"]>>;
18
9
  limit: z.ZodDefault<z.ZodNumber>;
19
- }, z.core.$strip>;
10
+ }, "strip", z.ZodTypeAny, {
11
+ limit: number;
12
+ market?: "KOSPI" | "KOSDAQ" | "US" | "JP" | "UK" | undefined;
13
+ ticker?: string | undefined;
14
+ zone?: "STRONG_UP" | "UP_ZONE" | "NEUTRAL" | "DOWN_ZONE" | "STRONG_DOWN" | undefined;
15
+ }, {
16
+ limit?: number | undefined;
17
+ market?: "KOSPI" | "KOSDAQ" | "US" | "JP" | "UK" | undefined;
18
+ ticker?: string | undefined;
19
+ zone?: "STRONG_UP" | "UP_ZONE" | "NEUTRAL" | "DOWN_ZONE" | "STRONG_DOWN" | undefined;
20
+ }>;
20
21
  export declare const ChartCoinParamsSchema: z.ZodObject<{
21
22
  ticker: z.ZodOptional<z.ZodString>;
22
- zone: z.ZodOptional<z.ZodEnum<{
23
- STRONG_UP: "STRONG_UP";
24
- UP_ZONE: "UP_ZONE";
25
- NEUTRAL: "NEUTRAL";
26
- DOWN_ZONE: "DOWN_ZONE";
27
- STRONG_DOWN: "STRONG_DOWN";
28
- }>>;
23
+ zone: z.ZodOptional<z.ZodEnum<["STRONG_UP", "UP_ZONE", "NEUTRAL", "DOWN_ZONE", "STRONG_DOWN"]>>;
29
24
  limit: z.ZodDefault<z.ZodNumber>;
30
- }, z.core.$strip>;
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
+ }>;
31
34
  export type ChartStockParams = z.infer<typeof ChartStockParamsSchema>;
32
35
  export type ChartCoinParams = z.infer<typeof ChartCoinParamsSchema>;
33
36
  export declare function getChartStock(params: ChartStockParams): Promise<{
@@ -39,6 +42,13 @@ export declare function getChartStock(params: ChartStockParams): Promise<{
39
42
  scores: number[];
40
43
  zone: string;
41
44
  oscillator_state: string;
45
+ analysis?: {
46
+ weekly_zone: string;
47
+ daily_momentum: string;
48
+ daily_signal: string;
49
+ };
50
+ outlook?: string;
51
+ chart_history?: any;
42
52
  last_price: number;
43
53
  updated_at: string;
44
54
  } | Array<{
@@ -57,6 +67,13 @@ export declare function getChartCoin(params: ChartCoinParams): Promise<{
57
67
  scores: number[];
58
68
  zone: string;
59
69
  oscillator_state: string;
70
+ analysis?: {
71
+ weekly_zone: string;
72
+ daily_momentum: string;
73
+ daily_signal: string;
74
+ };
75
+ outlook?: string;
76
+ chart_history?: any;
60
77
  last_price: number;
61
78
  updated_at: string;
62
79
  } | Array<{
@@ -6,7 +6,7 @@ import { callApi } from '../utils/api.js';
6
6
  // 주식 차트 파라미터 스키마
7
7
  export const ChartStockParamsSchema = z.object({
8
8
  ticker: z.string().optional().describe('종목 코드 (예: 005930)'),
9
- market: z.enum(['KOSPI', 'KOSDAQ']).optional().describe('시장 구분'),
9
+ market: z.enum(['KOSPI', 'KOSDAQ', 'US', 'JP', 'UK']).optional().describe('시장 구분 (KOSPI/KOSDAQ/US/JP/UK)'),
10
10
  zone: z.enum(['STRONG_UP', 'UP_ZONE', 'NEUTRAL', 'DOWN_ZONE', 'STRONG_DOWN']).optional().describe('차트 구간'),
11
11
  limit: z.number().min(1).max(100).default(20).describe('결과 수'),
12
12
  });
@@ -18,15 +18,14 @@ export const ChartCoinParamsSchema = z.object({
18
18
  });
19
19
  // 주식 차트 조회
20
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);
21
+ const endpoint = 'chart-stock';
22
+ // params passes through directly as query params
23
+ const result = await callApi(endpoint, params);
24
24
  return result;
25
25
  }
26
26
  // 코인 차트 조회
27
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);
28
+ const endpoint = 'chart-coin';
29
+ const result = await callApi(endpoint, params);
31
30
  return result;
32
31
  }
@@ -5,14 +5,25 @@ import { z } from 'zod';
5
5
  export declare const FinancialsParamsSchema: z.ZodObject<{
6
6
  ticker: z.ZodOptional<z.ZodString>;
7
7
  period: z.ZodOptional<z.ZodString>;
8
- market: z.ZodOptional<z.ZodEnum<{
9
- KOSPI: "KOSPI";
10
- KOSDAQ: "KOSDAQ";
11
- }>>;
8
+ market: z.ZodOptional<z.ZodEnum<["KOSPI", "KOSDAQ", "US", "JP", "UK"]>>;
12
9
  periods: z.ZodDefault<z.ZodNumber>;
13
10
  limit: z.ZodDefault<z.ZodNumber>;
14
11
  offset: z.ZodDefault<z.ZodNumber>;
15
- }, z.core.$strip>;
12
+ }, "strip", z.ZodTypeAny, {
13
+ limit: number;
14
+ offset: number;
15
+ periods: number;
16
+ market?: "KOSPI" | "KOSDAQ" | "US" | "JP" | "UK" | undefined;
17
+ ticker?: string | undefined;
18
+ period?: string | undefined;
19
+ }, {
20
+ limit?: number | undefined;
21
+ offset?: number | undefined;
22
+ market?: "KOSPI" | "KOSDAQ" | "US" | "JP" | "UK" | undefined;
23
+ ticker?: string | undefined;
24
+ period?: string | undefined;
25
+ periods?: number | undefined;
26
+ }>;
16
27
  export type FinancialsParams = z.infer<typeof FinancialsParamsSchema>;
17
28
  export declare function getFinancials(params: FinancialsParams): Promise<{
18
29
  success: boolean;
@@ -7,7 +7,7 @@ import { callApi } from '../utils/api.js';
7
7
  export const FinancialsParamsSchema = z.object({
8
8
  ticker: z.string().optional().describe('종목 코드 (예: 005930)'),
9
9
  period: z.string().optional().describe('분기 (예: 2024Q3)'),
10
- market: z.enum(['KOSPI', 'KOSDAQ']).optional().describe('시장 구분'),
10
+ market: z.enum(['KOSPI', 'KOSDAQ', 'US', 'JP', 'UK']).optional().describe('시장 구분 (KOSPI/KOSDAQ/US/JP/UK)'),
11
11
  periods: z.number().min(1).max(8).default(4).describe('최근 N분기 (기본: 4)'),
12
12
  limit: z.number().min(1).max(200).default(50).describe('결과 수'),
13
13
  offset: z.number().min(0).default(0).describe('페이지네이션 오프셋'),
@@ -8,30 +8,75 @@ export declare const NewsParamsSchema: z.ZodObject<{
8
8
  search: z.ZodOptional<z.ZodString>;
9
9
  from_date: z.ZodOptional<z.ZodString>;
10
10
  to_date: z.ZodOptional<z.ZodString>;
11
- limit: z.ZodDefault<z.ZodNumber>;
12
- offset: z.ZodDefault<z.ZodNumber>;
13
11
  start_date: z.ZodOptional<z.ZodString>;
14
12
  end_date: z.ZodOptional<z.ZodString>;
15
- }, z.core.$strip>;
13
+ limit: z.ZodDefault<z.ZodNumber>;
14
+ offset: z.ZodDefault<z.ZodNumber>;
15
+ }, "strip", z.ZodTypeAny, {
16
+ limit: number;
17
+ offset: number;
18
+ tag_code?: string | undefined;
19
+ source?: string | undefined;
20
+ search?: string | undefined;
21
+ from_date?: string | undefined;
22
+ to_date?: string | undefined;
23
+ start_date?: string | undefined;
24
+ end_date?: string | undefined;
25
+ }, {
26
+ tag_code?: string | undefined;
27
+ source?: string | undefined;
28
+ search?: string | undefined;
29
+ from_date?: string | undefined;
30
+ to_date?: string | undefined;
31
+ start_date?: string | undefined;
32
+ end_date?: string | undefined;
33
+ limit?: number | undefined;
34
+ offset?: number | undefined;
35
+ }>;
16
36
  export declare const NewsScoredParamsSchema: z.ZodObject<{
17
37
  tag_code: z.ZodOptional<z.ZodString>;
18
38
  source: z.ZodOptional<z.ZodString>;
19
39
  search: z.ZodOptional<z.ZodString>;
20
40
  from_date: z.ZodOptional<z.ZodString>;
21
41
  to_date: z.ZodOptional<z.ZodString>;
22
- limit: z.ZodDefault<z.ZodNumber>;
23
- offset: z.ZodDefault<z.ZodNumber>;
24
42
  start_date: z.ZodOptional<z.ZodString>;
25
43
  end_date: z.ZodOptional<z.ZodString>;
44
+ limit: z.ZodDefault<z.ZodNumber>;
45
+ offset: z.ZodDefault<z.ZodNumber>;
46
+ } & {
26
47
  min_score: z.ZodOptional<z.ZodNumber>;
27
48
  max_score: z.ZodOptional<z.ZodNumber>;
28
- verdict: z.ZodOptional<z.ZodEnum<{
29
- bullish: "bullish";
30
- bearish: "bearish";
31
- neutral: "neutral";
32
- }>>;
49
+ verdict: z.ZodOptional<z.ZodEnum<["bullish", "bearish", "neutral"]>>;
33
50
  market: z.ZodOptional<z.ZodString>;
34
- }, z.core.$strip>;
51
+ }, "strip", z.ZodTypeAny, {
52
+ limit: number;
53
+ offset: number;
54
+ tag_code?: string | undefined;
55
+ source?: string | undefined;
56
+ search?: string | undefined;
57
+ from_date?: string | undefined;
58
+ to_date?: string | undefined;
59
+ start_date?: string | undefined;
60
+ end_date?: string | undefined;
61
+ min_score?: number | undefined;
62
+ max_score?: number | undefined;
63
+ verdict?: "bullish" | "bearish" | "neutral" | undefined;
64
+ market?: string | undefined;
65
+ }, {
66
+ tag_code?: string | undefined;
67
+ source?: string | undefined;
68
+ search?: string | undefined;
69
+ from_date?: string | undefined;
70
+ to_date?: string | undefined;
71
+ start_date?: string | undefined;
72
+ end_date?: string | undefined;
73
+ limit?: number | undefined;
74
+ offset?: number | undefined;
75
+ min_score?: number | undefined;
76
+ max_score?: number | undefined;
77
+ verdict?: "bullish" | "bearish" | "neutral" | undefined;
78
+ market?: string | undefined;
79
+ }>;
35
80
  export type NewsParams = z.infer<typeof NewsParamsSchema>;
36
81
  export type NewsScoredParams = z.infer<typeof NewsScoredParamsSchema>;
37
82
  export declare function getNews(params: NewsParams): Promise<{
@@ -6,25 +6,27 @@ import { callApi } from '../utils/api.js';
6
6
  // 뉴스 파라미터 스키마
7
7
  export const NewsParamsSchema = z.object({
8
8
  tag_code: z.string().optional().describe('태그 코드 (search_tags 결과값, 예: STK005930, THM001)'),
9
- source: z.string().optional().describe('소스 필터 (예: 한경, 매경)'),
9
+ source: z.string().optional().describe('소스 필터 (예: 한경, 매경, WSJ, Bloomberg)'),
10
10
  search: z.string().optional().describe('제목 검색어'),
11
11
  from_date: z.string().optional().describe('시작일 (YYYY-MM-DD)'),
12
12
  to_date: z.string().optional().describe('종료일 (YYYY-MM-DD)'),
13
+ start_date: z.string().optional().describe('시작일 (from_date의 별칭)'), // [FIX] LLM Alias support
14
+ end_date: z.string().optional().describe('종료일 (to_date의 별칭)'), // [FIX] LLM Alias support
13
15
  limit: z.number().min(1).max(100).default(20).describe('결과 수 (기본: 20, 최대: 100)'),
14
16
  offset: z.number().min(0).default(0).describe('페이지네이션 오프셋'),
15
- start_date: z.string().optional().describe('시작일 alias'),
16
- end_date: z.string().optional().describe('종료일 alias'),
17
17
  }); // [MOD] Removed .strict()
18
18
  // 점수 포함 뉴스 파라미터 스키마
19
19
  export const NewsScoredParamsSchema = NewsParamsSchema.extend({
20
20
  min_score: z.number().min(-10).max(10).optional().describe('최소 감정 점수 (-10~10)'),
21
21
  max_score: z.number().min(-10).max(10).optional().describe('최대 감정 점수 (-10~10)'),
22
22
  verdict: z.enum(['bullish', 'bearish', 'neutral']).optional().describe('판정 필터'),
23
- market: z.string().optional().describe('시장 필터 (KR, US, JP, UK)'),
23
+ market: z.string().optional().describe('시장 필터 (KR, US 등) - 호환성 유지용'), // [FIX] LLM Compatibility
24
24
  }); // [MOD] Removed .strict()
25
25
  // 뉴스 조회 (점수 제외)
26
26
  export async function getNews(params) {
27
+ console.error(`[getNews] Params: ${JSON.stringify(params)}`); // [DEBUG]
27
28
  const { tag_code, start_date, end_date, ...rest } = params;
29
+ // [FIX] Handle Aliases
28
30
  const apiParams = { ...rest, tag: tag_code };
29
31
  if (start_date && !apiParams.from_date)
30
32
  apiParams.from_date = start_date;
@@ -35,29 +37,14 @@ export async function getNews(params) {
35
37
  }
36
38
  // 뉴스 조회 (점수 포함)
37
39
  export async function getNewsScored(params) {
38
- const { tag_code, start_date, end_date, ...rest } = params;
40
+ console.error(`[getNewsScored] Params: ${JSON.stringify(params)}`); // [DEBUG]
41
+ const { tag_code, start_date, end_date, ...rest } = params; // [FIXED] Include 'market' in API call by not destructuring it from rest (it's inside rest now or handled by type)
42
+ // [FIX] Handle Aliases
39
43
  const apiParams = { ...rest, tag: tag_code };
40
44
  if (start_date && !apiParams.from_date)
41
45
  apiParams.from_date = start_date;
42
46
  if (end_date && !apiParams.to_date)
43
47
  apiParams.to_date = end_date;
44
- // [FIX] JP/UK Fallback: 'news-scored' endpoint only supports scored news (news_final).
45
- // Raw markets (JP/UK) are in raw tables accessed via 'news' endpoint.
46
- // We hijack the call to 'news' and polyfill the score fields.
47
- const market = apiParams.market?.toUpperCase();
48
- if (market === 'JP' || market === 'UK') {
49
- const result = await callApi('news', apiParams);
50
- return {
51
- ...result,
52
- data: (result.data || []).map(item => ({
53
- ...item,
54
- sentiment_score: 0,
55
- verdict: 'neutral',
56
- tag_codes: item.tags || [] // 'news' endpoint returns tags as strings or codes? check 'news' return type.
57
- // Actually 'news' endpoint handles mapping too.
58
- }))
59
- };
60
- }
61
48
  const result = await callApi('news-scored', apiParams);
62
49
  return result;
63
50
  }
@@ -1,26 +1,39 @@
1
1
  /**
2
- * 컨설팅 보고서 관련 MCP Tools
2
+ * Research (보고서) 관련 MCP Tools
3
3
  */
4
4
  import { z } from 'zod';
5
5
  export declare const ResearchParamsSchema: z.ZodObject<{
6
- tag_code: z.ZodString;
7
- limit: z.ZodDefault<z.ZodNumber>;
6
+ tag_code: z.ZodOptional<z.ZodString>;
8
7
  source: z.ZodOptional<z.ZodString>;
9
- }, z.core.$strip>;
8
+ limit: z.ZodDefault<z.ZodNumber>;
9
+ offset: z.ZodDefault<z.ZodNumber>;
10
+ }, "strip", z.ZodTypeAny, {
11
+ limit: number;
12
+ offset: number;
13
+ tag_code?: string | undefined;
14
+ source?: string | undefined;
15
+ }, {
16
+ tag_code?: string | undefined;
17
+ source?: string | undefined;
18
+ limit?: number | undefined;
19
+ offset?: number | undefined;
20
+ }>;
10
21
  export type ResearchParams = z.infer<typeof ResearchParamsSchema>;
11
22
  export declare function getResearch(params: ResearchParams): Promise<{
12
- tag_code: string;
13
- tag_name: string | null;
14
- research_count: number;
15
- research: Array<{
23
+ success: boolean;
24
+ data: Array<{
16
25
  id: number;
17
26
  title: string;
27
+ summary: string;
28
+ tag_codes: string[];
29
+ created_at: string;
30
+ processed_at: string;
18
31
  source: string;
19
- content_type: string;
20
- published_at: string | null;
21
- chunks: Array<{
22
- section: string;
23
- content: string;
24
- }>;
32
+ market_outlook?: string;
25
33
  }>;
34
+ meta: {
35
+ count: number;
36
+ limit: number;
37
+ offset: number;
38
+ };
26
39
  }>;
@@ -1,18 +1,18 @@
1
1
  /**
2
- * 컨설팅 보고서 관련 MCP Tools
2
+ * Research (보고서) 관련 MCP Tools
3
3
  */
4
4
  import { z } from 'zod';
5
5
  import { callApi } from '../utils/api.js';
6
- const API_BASE = 'https://ragalgo-research-production.up.railway.app'; // 혹시 몰라 남겨룸, 하지만 callApi 사용시 Supabase Edge Function 호출
7
- // 보고서 조회 파라미터 스키마
6
+ // Research 파라미터 스키마
8
7
  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 등'),
8
+ tag_code: z.string().optional().describe('Tag code filter (e.g., STK005930, USTK_AAPL)'),
9
+ source: z.string().optional().describe('Source filter (e.g., mckinsey, bcg, ls)'),
10
+ limit: z.number().min(1).max(50).default(10).describe('Result count (default: 10)'),
11
+ offset: z.number().min(0).default(0).describe('Pagination offset'),
12
12
  });
13
- // 보고서 조회
13
+ // Research 보고서 조회
14
14
  export async function getResearch(params) {
15
- // Supabase Edge Function 호출
16
- const result = await callApi('research', params); // 'research' function 호출
15
+ const endpoint = 'research';
16
+ const result = await callApi(endpoint, params);
17
17
  return result;
18
18
  }
@@ -0,0 +1,33 @@
1
+ import { z } from 'zod';
2
+ export declare const RoomsParamsSchema: z.ZodObject<{
3
+ search: z.ZodOptional<z.ZodString>;
4
+ type: z.ZodOptional<z.ZodEnum<["tag", "ticker", "keyword"]>>;
5
+ limit: z.ZodDefault<z.ZodNumber>;
6
+ }, "strip", z.ZodTypeAny, {
7
+ limit: number;
8
+ type?: "ticker" | "tag" | "keyword" | undefined;
9
+ search?: string | undefined;
10
+ }, {
11
+ type?: "ticker" | "tag" | "keyword" | undefined;
12
+ search?: string | undefined;
13
+ limit?: number | undefined;
14
+ }>;
15
+ export type RoomsParams = z.infer<typeof RoomsParamsSchema>;
16
+ export declare const GetAvailableRoomsSchema: z.ZodObject<{
17
+ search: z.ZodOptional<z.ZodString>;
18
+ type: z.ZodOptional<z.ZodEnum<["tag", "ticker", "keyword"]>>;
19
+ limit: z.ZodDefault<z.ZodNumber>;
20
+ }, "strip", z.ZodTypeAny, {
21
+ limit: number;
22
+ type?: "ticker" | "tag" | "keyword" | undefined;
23
+ search?: string | undefined;
24
+ }, {
25
+ type?: "ticker" | "tag" | "keyword" | undefined;
26
+ search?: string | undefined;
27
+ limit?: number | undefined;
28
+ }>;
29
+ export declare function getAvailableRooms(params: RoomsParams): Promise<{
30
+ rooms: any;
31
+ count: any;
32
+ help: string;
33
+ }>;
@@ -0,0 +1,43 @@
1
+ import { z } from 'zod';
2
+ const SUPABASE_PROJECT_URL = 'https://xunrsikkybgxkybjzrgz.supabase.co';
3
+ const SUPABASE_REST_URL = `${SUPABASE_PROJECT_URL}/rest/v1`;
4
+ const SUPABASE_ANON_KEY = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Inh1bnJzaWtreWJneGt5Ymp6cmd6Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3NjQ0NTExNTgsImV4cCI6MjA4MDAyNzE1OH0.SsXri828-Rf0gHlu4Bls-pewhfMNNII4mbiuLnc9ACs';
5
+ export const RoomsParamsSchema = z.object({
6
+ search: z.string().optional().describe('Search term for rooms (e.g., "Samsung", "Semiconductor")'),
7
+ type: z.enum(['tag', 'ticker', 'keyword']).optional().describe('Filter by room type'),
8
+ limit: z.number().min(1).max(100).default(20).describe('Result count'),
9
+ });
10
+ export const GetAvailableRoomsSchema = RoomsParamsSchema;
11
+ export async function getAvailableRooms(params) {
12
+ const url = new URL(`${SUPABASE_REST_URL}/available_websocket_rooms`);
13
+ // Select specific columns
14
+ url.searchParams.append('select', 'room_id,type,description');
15
+ // Add filters
16
+ if (params.search) {
17
+ // Search in both description and room_id
18
+ url.searchParams.append('or', `(description.ilike.*${params.search}*,room_id.ilike.*${params.search}*)`);
19
+ }
20
+ if (params.type) {
21
+ url.searchParams.append('type', `eq.${params.type}`);
22
+ }
23
+ // Limit
24
+ url.searchParams.append('limit', String(params.limit));
25
+ const response = await fetch(url.toString(), {
26
+ method: 'GET',
27
+ headers: {
28
+ 'Authorization': `Bearer ${SUPABASE_ANON_KEY}`,
29
+ 'apikey': SUPABASE_ANON_KEY,
30
+ 'Content-Type': 'application/json',
31
+ },
32
+ });
33
+ if (!response.ok) {
34
+ const error = await response.text();
35
+ throw new Error(`Failed to fetch rooms: ${response.status} - ${error}`);
36
+ }
37
+ const data = await response.json();
38
+ return {
39
+ rooms: data,
40
+ count: data.length,
41
+ help: "Use these room_ids to subscribe via WebSocket. Example: socket.emit('subscribe', 'tag:STK005930')"
42
+ };
43
+ }
@@ -4,11 +4,26 @@
4
4
  import { z } from 'zod';
5
5
  export declare const SnapshotsParamsSchema: z.ZodObject<{
6
6
  tag_code: z.ZodOptional<z.ZodString>;
7
+ market: z.ZodOptional<z.ZodEnum<["KR", "US", "JP", "UK", "UNIFIED", "CRY", "FUTURES"]>>;
7
8
  date: z.ZodOptional<z.ZodString>;
8
9
  days: z.ZodDefault<z.ZodNumber>;
9
10
  limit: z.ZodDefault<z.ZodNumber>;
10
11
  offset: z.ZodDefault<z.ZodNumber>;
11
- }, z.core.$strip>;
12
+ }, "strip", z.ZodTypeAny, {
13
+ limit: number;
14
+ offset: number;
15
+ days: number;
16
+ tag_code?: string | undefined;
17
+ market?: "US" | "JP" | "UK" | "KR" | "UNIFIED" | "CRY" | "FUTURES" | undefined;
18
+ date?: string | undefined;
19
+ }, {
20
+ tag_code?: string | undefined;
21
+ limit?: number | undefined;
22
+ offset?: number | undefined;
23
+ market?: "US" | "JP" | "UK" | "KR" | "UNIFIED" | "CRY" | "FUTURES" | undefined;
24
+ date?: string | undefined;
25
+ days?: number | undefined;
26
+ }>;
12
27
  export type SnapshotsParams = z.infer<typeof SnapshotsParamsSchema>;
13
28
  export declare function getSnapshots(params: SnapshotsParams): Promise<{
14
29
  success: boolean;
@@ -6,15 +6,28 @@ import { callApi } from '../utils/api.js';
6
6
  // 스냅샷 파라미터 스키마
7
7
  export const SnapshotsParamsSchema = z.object({
8
8
  tag_code: z.string().optional().describe('태그 코드 (예: STK005930)'),
9
+ market: z.enum(['KR', 'US', 'JP', 'UK', 'UNIFIED', 'CRY', 'FUTURES']).optional().describe('시장 구분 (KR/US/JP/UK/UNIFIED/CRY/FUTURES)'),
9
10
  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('결과 수'),
11
+ days: z.number().min(1).default(7).describe('최근 N일 (기본: 7, 무제한)'),
12
+ limit: z.number().min(1).default(50).describe('결과 수 (기본: 50, 무제한)'),
12
13
  offset: z.number().min(0).default(0).describe('페이지네이션 오프셋'),
13
14
  });
14
15
  // 스냅샷 조회
16
+ // [IMPORTANT] Snapshots are generated daily at 17:00 KST (market close).
17
+ // If you request 'today' and get no results (because it's morning in KST),
18
+ // you MUST:
19
+ // 1. Fetch 'yesterday's snapshot for context.
20
+ // 2. Call 'get_news_scored' to get REAL-TIME news for the current day.
15
21
  export async function getSnapshots(params) {
16
- const endpoint = params.tag_code ? `snapshots/${params.tag_code}` : 'snapshots';
22
+ const endpoint = 'snapshots';
17
23
  const { tag_code, ...queryParams } = params;
24
+ // 태그 코드가 있으면 쿼리 파라미터에 추가
25
+ if (tag_code) {
26
+ queryParams.tag_code = tag_code;
27
+ }
28
+ if (params.market) {
29
+ queryParams.market = params.market;
30
+ }
18
31
  const result = await callApi(endpoint, queryParams);
19
32
  return result;
20
33
  }
@@ -3,28 +3,68 @@
3
3
  */
4
4
  import { z } from 'zod';
5
5
  export declare const TagsSearchParamsSchema: z.ZodObject<{
6
- q: z.ZodString;
7
- type: z.ZodOptional<z.ZodEnum<{
8
- STOCK: "STOCK";
9
- SECTOR: "SECTOR";
10
- THEME: "THEME";
11
- CRYPTO: "CRYPTO";
12
- }>>;
6
+ q: z.ZodOptional<z.ZodString>;
7
+ query: z.ZodOptional<z.ZodString>;
8
+ type: z.ZodOptional<z.ZodEnum<["STOCK", "SECTOR", "THEME", "CRYPTO"]>>;
13
9
  limit: z.ZodDefault<z.ZodNumber>;
14
- }, z.core.$strip>;
10
+ }, "strip", z.ZodTypeAny, {
11
+ limit: number;
12
+ type?: "STOCK" | "SECTOR" | "THEME" | "CRYPTO" | undefined;
13
+ q?: string | undefined;
14
+ query?: string | undefined;
15
+ }, {
16
+ type?: "STOCK" | "SECTOR" | "THEME" | "CRYPTO" | undefined;
17
+ limit?: number | undefined;
18
+ q?: string | undefined;
19
+ query?: string | undefined;
20
+ }>;
15
21
  export declare const TagsMatchParamsSchema: z.ZodObject<{
16
22
  text: z.ZodString;
17
- types: z.ZodOptional<z.ZodArray<z.ZodEnum<{
18
- STOCK: "STOCK";
19
- SECTOR: "SECTOR";
20
- THEME: "THEME";
21
- CRYPTO: "CRYPTO";
22
- }>>>;
23
+ types: z.ZodOptional<z.ZodArray<z.ZodEnum<["STOCK", "SECTOR", "THEME", "CRYPTO"]>, "many">>;
23
24
  limit: z.ZodDefault<z.ZodNumber>;
24
- }, z.core.$strip>;
25
+ }, "strip", z.ZodTypeAny, {
26
+ text: string;
27
+ limit: number;
28
+ types?: ("STOCK" | "SECTOR" | "THEME" | "CRYPTO")[] | undefined;
29
+ }, {
30
+ text: string;
31
+ limit?: number | undefined;
32
+ types?: ("STOCK" | "SECTOR" | "THEME" | "CRYPTO")[] | undefined;
33
+ }>;
25
34
  export type TagsSearchParams = z.infer<typeof TagsSearchParamsSchema>;
26
35
  export type TagsMatchParams = z.infer<typeof TagsMatchParamsSchema>;
27
- export declare function searchTags(params: TagsSearchParams): Promise<{
36
+ export declare const SearchTagsParamsSchema: z.ZodObject<{
37
+ q: z.ZodOptional<z.ZodString>;
38
+ query: z.ZodOptional<z.ZodString>;
39
+ type: z.ZodOptional<z.ZodEnum<["STOCK", "SECTOR", "THEME", "CRYPTO"]>>;
40
+ limit: z.ZodDefault<z.ZodNumber>;
41
+ }, "strip", z.ZodTypeAny, {
42
+ limit: number;
43
+ type?: "STOCK" | "SECTOR" | "THEME" | "CRYPTO" | undefined;
44
+ q?: string | undefined;
45
+ query?: string | undefined;
46
+ }, {
47
+ type?: "STOCK" | "SECTOR" | "THEME" | "CRYPTO" | undefined;
48
+ limit?: number | undefined;
49
+ q?: string | undefined;
50
+ query?: string | undefined;
51
+ }>;
52
+ export declare const MatchTagsParamsSchema: z.ZodObject<{
53
+ text: z.ZodString;
54
+ types: z.ZodOptional<z.ZodArray<z.ZodEnum<["STOCK", "SECTOR", "THEME", "CRYPTO"]>, "many">>;
55
+ limit: z.ZodDefault<z.ZodNumber>;
56
+ }, "strip", z.ZodTypeAny, {
57
+ text: string;
58
+ limit: number;
59
+ types?: ("STOCK" | "SECTOR" | "THEME" | "CRYPTO")[] | undefined;
60
+ }, {
61
+ text: string;
62
+ limit?: number | undefined;
63
+ types?: ("STOCK" | "SECTOR" | "THEME" | "CRYPTO")[] | undefined;
64
+ }>;
65
+ export declare function searchTags(params: TagsSearchParams & {
66
+ query?: string;
67
+ }): Promise<{
28
68
  success: boolean;
29
69
  data: Array<{
30
70
  tag_code: string;
@@ -5,7 +5,8 @@ import { z } from 'zod';
5
5
  import { callApi, callApiPost } from '../utils/api.js';
6
6
  // 태그 검색 파라미터 스키마
7
7
  export const TagsSearchParamsSchema = z.object({
8
- q: z.string().describe('검색어 (예: 삼성, 반도체)'),
8
+ q: z.string().describe('검색어 (예: 삼성, 반도체)').optional(),
9
+ query: z.string().optional().describe('검색어 alias'), // [FIX] LLM often sends 'query'
9
10
  type: z.enum(['STOCK', 'SECTOR', 'THEME', 'CRYPTO']).optional().describe('태그 타입'),
10
11
  limit: z.number().min(1).max(50).default(20).describe('결과 수'),
11
12
  });
@@ -15,9 +16,19 @@ export const TagsMatchParamsSchema = z.object({
15
16
  types: z.array(z.enum(['STOCK', 'SECTOR', 'THEME', 'CRYPTO'])).optional().describe('태그 타입 필터'),
16
17
  limit: z.number().min(1).max(20).default(10).describe('결과 수'),
17
18
  });
19
+ export const SearchTagsParamsSchema = TagsSearchParamsSchema;
20
+ export const MatchTagsParamsSchema = TagsMatchParamsSchema;
18
21
  // 태그 검색
19
22
  export async function searchTags(params) {
20
- const result = await callApi('tags/search', params);
23
+ // [FIX] Alias mapping: query -> q
24
+ if (!params.q && params.query) {
25
+ params.q = params.query;
26
+ }
27
+ if (!params.q) {
28
+ throw new Error("검색어(q 또는 query)가 필요합니다.");
29
+ }
30
+ const { query, ...apiParams } = params; // Remove 'query' alias from API call
31
+ const result = await callApi('tags/search', apiParams);
21
32
  return result;
22
33
  }
23
34
  // 태그 매칭 (텍스트 → 태그)