stockmatrix-mcp 0.1.3 → 0.2.0

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/README.md CHANGED
@@ -1,14 +1,10 @@
1
1
  # stockmatrix-mcp
2
2
 
3
- MCP server for Korean stock market theme lifecycle analysis. Provides real-time theme scores, lifecycle stages, related stocks, and news for 250+ KOSPI/KOSDAQ investment themes.
3
+ MCP server for Korean stock market theme analysis. Track 250+ KOSPI/KOSDAQ investment themes with lifecycle scores, trend data, related stocks, and news all through natural conversation with AI.
4
4
 
5
- ## Installation
5
+ Scores are computed using **TLI (Theme Lifecycle Index)** — a Bayesian-optimized algorithm combining search interest, news momentum, market volatility, and stock activity into a 0-100 score with lifecycle stage classification.
6
6
 
7
- ```bash
8
- npx -y stockmatrix-mcp
9
- ```
10
-
11
- ## Configuration
7
+ ## Quick Start
12
8
 
13
9
  ### Claude Desktop
14
10
 
@@ -25,9 +21,9 @@ Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
25
21
  }
26
22
  ```
27
23
 
28
- ### Cursor
24
+ ### Cursor / Windsurf
29
25
 
30
- Add to `.cursor/mcp.json`:
26
+ Add to `.cursor/mcp.json` or `.windsurf/mcp.json`:
31
27
 
32
28
  ```json
33
29
  {
@@ -40,7 +36,7 @@ Add to `.cursor/mcp.json`:
40
36
  }
41
37
  ```
42
38
 
43
- ### VS Code
39
+ ### VS Code / Claude Code
44
40
 
45
41
  Add to `.vscode/mcp.json`:
46
42
 
@@ -55,71 +51,106 @@ Add to `.vscode/mcp.json`:
55
51
  }
56
52
  ```
57
53
 
54
+ ## Try Asking
55
+
56
+ After setup, just ask in natural language:
57
+
58
+ | Prompt | What happens |
59
+ |--------|-------------|
60
+ | "요즘 한국 주식시장에서 뜨는 테마 뭐야?" | Top trending themes with scores |
61
+ | "AI 관련 테마 찾아줘" | Search AI-related themes |
62
+ | "반도체 테마 최근 한달 추세 어때?" | 30-day score history |
63
+ | "삼성전자가 속한 테마 알려줘" | Themes linked to Samsung (005930) |
64
+ | "성장 단계인 테마만 보여줘" | Growth-stage themes only |
65
+ | "방산 테마 상세 정보" | Score, stocks, news for defense theme |
66
+ | "TLI 점수는 어떻게 계산돼?" | Algorithm methodology |
67
+ | "What are the hottest stock themes in Korea?" | Works in English too |
68
+ | "Which themes is SK Hynix (000660) part of?" | Stock-to-theme lookup |
69
+
58
70
  ## Available Tools
59
71
 
60
72
  ### `get_theme_ranking`
61
73
 
62
- 한국 주식시장 테마 생명주기 랭킹을 조회합니다. Retrieves theme lifecycle rankings by stage.
74
+ Get theme rankings by lifecycle stage.
63
75
 
64
76
  | Parameter | Type | Required | Description |
65
77
  |-----------|------|----------|-------------|
66
- | `stage` | string | No | Filter by stage: `emerging`, `growth`, `peak`, `decline`, `reigniting` |
78
+ | `stage` | string | No | `emerging` / `growth` / `peak` / `decline` / `reigniting` |
79
+
80
+ ### `search_themes`
81
+
82
+ Search themes by keyword (Korean or English).
83
+
84
+ | Parameter | Type | Required | Description |
85
+ |-----------|------|----------|-------------|
86
+ | `query` | string | Yes | e.g. `"AI"`, `"반도체"`, `"2차전지"`, `"삼성전자"` |
67
87
 
68
88
  ### `get_theme_detail`
69
89
 
70
- 특정 테마의 상세 정보를 조회합니다. Gets detailed theme info including score, stage, related stocks, and news.
90
+ Get detailed info: score breakdown (4 components), stage, prediction, stocks, news, comparisons.
71
91
 
72
92
  | Parameter | Type | Required | Description |
73
93
  |-----------|------|----------|-------------|
74
- | `theme_id` | string (UUID) | Yes | Theme UUID |
94
+ | `theme_id` | string (UUID) | Yes | Theme UUID from ranking or search |
75
95
 
76
96
  ### `get_theme_history`
77
97
 
78
- 테마의 최근 30일 점수 이력을 조회합니다. Returns 30-day score history for a theme.
98
+ Get 30-day score history for trend analysis.
79
99
 
80
100
  | Parameter | Type | Required | Description |
81
101
  |-----------|------|----------|-------------|
82
102
  | `theme_id` | string (UUID) | Yes | Theme UUID |
83
103
 
84
- ### `search_themes`
104
+ ### `get_stock_theme`
85
105
 
86
- 테마를 검색합니다. Searches themes by name in Korean or English.
106
+ Find themes a specific stock belongs to.
87
107
 
88
108
  | Parameter | Type | Required | Description |
89
109
  |-----------|------|----------|-------------|
90
- | `query` | string | Yes | Search query (e.g. `"AI"`, `"반도체"`, `"삼성전자"`) |
110
+ | `symbol` | string | Yes | 6-digit code, e.g. `"005930"` (Samsung), `"000660"` (SK Hynix) |
91
111
 
92
- ### `get_stock_theme`
112
+ ### `get_methodology`
93
113
 
94
- 특정 종목이 속한 테마를 조회합니다. Finds themes related to a specific stock code.
114
+ Get TLI algorithm documentation scoring, stages, stabilization, comparison, prediction.
95
115
 
96
116
  | Parameter | Type | Required | Description |
97
117
  |-----------|------|----------|-------------|
98
- | `symbol` | string | Yes | 6-digit Korean stock code (e.g. `"005930"` for Samsung) |
118
+ | `section` | string | No | `scoring` / `stabilization` / `stages` / `comparison` / `prediction` / `all` |
99
119
 
100
- ## Environment Variables
120
+ ## Scoring Algorithm
101
121
 
102
- | Variable | Default | Description |
103
- |----------|---------|-------------|
104
- | `STOCKMATRIX_API_URL` | `https://stockmatrix.co.kr` | API base URL |
122
+ TLI scores (0-100) are a weighted sum of 4 components, optimized via Bayesian Optimization:
105
123
 
106
- ## Examples
124
+ | Component | Weight | Source |
125
+ |-----------|--------|--------|
126
+ | Search Interest | 30.4% | Naver DataLab |
127
+ | News Momentum | 36.6% | Naver News |
128
+ | Volatility | 10.4% | Interest time-series |
129
+ | Stock Activity | 22.6% | Naver Finance |
107
130
 
108
- **"What are the hottest stock themes in Korea right now?"**
109
- → `get_theme_ranking` with `stage: "growth"`
131
+ Scores are stabilized through **Cautious Decay** (3-signal majority vote prevents false drops), **Bollinger Band Clamp** (limits daily change), and **Age-adaptive EMA** (newer themes react faster).
110
132
 
111
- **"Tell me about the semiconductor theme"**
112
- → `search_themes` with `query: "반도체"` → `get_theme_detail` with the returned theme ID
133
+ ## Lifecycle Stages
113
134
 
114
- **"What themes is Samsung Electronics part of?"**
115
- `get_stock_theme` with `symbol: "005930"`
135
+ ```
136
+ Dormant Emerging Growth → Peak → Decline → Dormant
137
+
138
+ Reigniting
139
+ ```
116
140
 
117
- ## Data Sources
141
+ Stage transitions require 2 consecutive days of the same candidate (hysteresis) and follow Markov transition constraints.
118
142
 
119
- - Naver DataLab search interest trends
120
- - Naver Finance theme stock data
121
- - Naver News article collection
122
- - KRX (Korea Exchange) market data
143
+ ## Data Coverage
144
+
145
+ - **250+ themes** across KOSPI & KOSDAQ
146
+ - **Daily updates** scores, news, stock mappings
147
+ - **Sources**: Naver DataLab, Naver Finance, Naver News
148
+
149
+ ## Configuration
150
+
151
+ | Variable | Default | Description |
152
+ |----------|---------|-------------|
153
+ | `STOCKMATRIX_API_URL` | `https://stockmatrix.co.kr` | Override API base URL |
123
154
 
124
155
  ## License
125
156
 
@@ -1,3 +1,4 @@
1
1
  export declare const fetchApi: <T = unknown>(path: string, params?: Record<string, string>) => Promise<T>;
2
- export declare const formatResult: (data: unknown) => string;
2
+ /** JSON 직렬화 with optional context header for AI agents */
3
+ export declare const formatResult: (data: unknown, context?: string) => string;
3
4
  export declare const formatError: (error: unknown) => string;
@@ -1,5 +1,8 @@
1
+ import { createRequire } from 'node:module';
2
+ const require = createRequire(import.meta.url);
3
+ const { version } = require('../package.json');
1
4
  const BASE_URL = process.env.STOCKMATRIX_API_URL || 'https://stockmatrix.co.kr';
2
- const MCP_USER_AGENT = `stockmatrix-mcp/0.1.3`;
5
+ const MCP_USER_AGENT = `stockmatrix-mcp/${version}`;
3
6
  // 시작 시 URL 유효성 검증
4
7
  try {
5
8
  new URL(BASE_URL);
@@ -78,7 +81,13 @@ export const fetchApi = async (path, params) => {
78
81
  }
79
82
  throw lastError;
80
83
  };
81
- export const formatResult = (data) => JSON.stringify(data, null, 2);
84
+ /** JSON 직렬화 with optional context header for AI agents */
85
+ export const formatResult = (data, context) => {
86
+ if (context) {
87
+ return `${context}\n\n${JSON.stringify(data, null, 2)}`;
88
+ }
89
+ return JSON.stringify(data, null, 2);
90
+ };
82
91
  export const formatError = (error) => {
83
92
  const message = error instanceof Error ? error.message : String(error);
84
93
  return `Error: ${message}`;
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ import { createRequire } from 'node:module';
2
3
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
4
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
5
  import { registerGetThemeRanking } from './tools/get-theme-ranking.js';
@@ -6,16 +7,20 @@ import { registerGetThemeDetail } from './tools/get-theme-detail.js';
6
7
  import { registerGetThemeHistory } from './tools/get-theme-history.js';
7
8
  import { registerSearchThemes } from './tools/search-themes.js';
8
9
  import { registerGetStockTheme } from './tools/get-stock-theme.js';
10
+ import { registerGetMethodology } from './tools/get-methodology.js';
11
+ const require = createRequire(import.meta.url);
12
+ const { version } = require('../package.json');
9
13
  const createServer = () => {
10
14
  const s = new McpServer({
11
15
  name: 'stockmatrix-mcp',
12
- version: '0.1.3',
16
+ version,
13
17
  });
14
18
  registerGetThemeRanking(s);
15
19
  registerGetThemeDetail(s);
16
20
  registerGetThemeHistory(s);
17
21
  registerSearchThemes(s);
18
22
  registerGetStockTheme(s);
23
+ registerGetMethodology(s);
19
24
  return s;
20
25
  };
21
26
  export const createSandboxServer = () => createServer();
@@ -23,7 +28,7 @@ const server = createServer();
23
28
  const main = async () => {
24
29
  const transport = new StdioServerTransport();
25
30
  await server.connect(transport);
26
- console.error('StockMatrix MCP server running on stdio');
31
+ console.error(`StockMatrix MCP server v${version} running on stdio`);
27
32
  };
28
33
  main().catch((error) => {
29
34
  console.error('Fatal error in main():', error);
@@ -0,0 +1,2 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare const registerGetMethodology: (server: McpServer) => void;
@@ -0,0 +1,109 @@
1
+ import { z } from 'zod';
2
+ const METHODOLOGY = {
3
+ name: 'TLI (Theme Lifecycle Index)',
4
+ version: '2.0 — Bayesian Optimized',
5
+ description: 'Quantitative index tracking Korean stock market theme lifecycles using public data sources.',
6
+ scoring: {
7
+ range: '0-100',
8
+ components: [
9
+ { name: 'interest', weight: '30.4%', source: 'Naver DataLab', method: '7-day search volume average vs 30-day baseline, sigmoid-normalized. Batch self-normalization applied (DataLab 5-keyword batch limit).' },
10
+ { name: 'newsMomentum', weight: '36.6%', source: 'Naver News', method: 'Log-scale news volume + weekly article count change rate.' },
11
+ { name: 'volatility', weight: '10.4%', source: 'Interest time-series', method: 'Standard deviation of interest values, sigmoid-normalized.' },
12
+ { name: 'activity', weight: '22.6%', source: 'Naver Finance', method: 'Related stock price change rates, trading volume intensity, and data coverage cross-signal.' },
13
+ ],
14
+ optimization: 'Weights derived via Bayesian Optimization (Optuna TPE sampler, 2-stage hierarchical search: 80 trials core params + 120 trials fine-tune). Validated with walk-forward train/val split with 7-day gap to prevent data leakage.',
15
+ accuracy: 'Growth/Decline Directional Accuracy (GDDA): ~66% on validation set.',
16
+ },
17
+ stabilization: {
18
+ pipeline: 'Cautious Decay → Bollinger Band Clamp → EMA Smoothing (applied in this fixed order)',
19
+ cautiousDecay: {
20
+ description: 'Prevents false score drops from data gaps or temporary noise.',
21
+ mechanism: '3 independent binary signals checked on score decline: (1) interest slope < 0, (2) this week news < last week news, (3) directional volatility index < 0.4. Decline confirmed only if 2+ signals agree (majority vote). Otherwise, previous score × 0.947 used as floor.',
22
+ },
23
+ bollingerClamp: {
24
+ description: 'Limits daily score change to prevent spikes.',
25
+ mechanism: 'Max daily change = max(min_daily_change, 2 × σ of recent smoothed scores).',
26
+ },
27
+ emaScheduling: {
28
+ description: 'Theme age-adaptive smoothing.',
29
+ mechanism: 'EMA alpha linearly interpolated: new themes (0 days) α=0.6 (reactive) → mature themes (30+ days) α=0.3 (stable). Null first_spike_date uses default α=0.417.',
30
+ },
31
+ },
32
+ stages: {
33
+ order: 'Dormant → Emerging → Growth → Peak → Decline (→ Dormant or Reigniting)',
34
+ thresholds: {
35
+ dormant: { score: '< 10', condition: 'AND trend ≠ rising' },
36
+ emerging: { score: 'default', condition: 'Does not match other stage criteria' },
37
+ growth: { score: '≥ 40', condition: 'AND stable/rising trend' },
38
+ peak: { score: '≥ 71', condition: 'OR (≥ 50 AND stable/rising AND news > 30 articles)' },
39
+ decline: { condition: 'Falling trend AND score < 86% of level score AND news declining' },
40
+ reigniting: { condition: 'Transition from Decline to Emerging/Growth' },
41
+ },
42
+ hysteresis: '2 consecutive days of same candidate stage required for transition (prevents 1-day noise).',
43
+ markov: 'Only allowed transitions: Dormant→Emerging, Emerging→Growth/Dormant, Growth→Peak/Decline, Peak→Decline/Growth, Decline→Dormant/Emerging/Growth. Data gap ≥ 3 days relaxes constraints.',
44
+ },
45
+ comparison: {
46
+ method: '3-Pillar similarity analysis',
47
+ pillars: [
48
+ { name: 'Feature Similarity', weight: 'dynamic (0.40-1.00)', method: 'Mutual Rank (sqrt of bidirectional rank product) with z-score and cosine fallbacks.' },
49
+ { name: 'Curve Similarity', weight: 'dynamic (0.00-0.60)', method: 'Shape RMSE (35%) + Derivative Pearson correlation (30%) + DTW distance (35%). Minimum 14 days data required.' },
50
+ { name: 'Keyword Similarity', weight: 'display only', method: 'Jaccard coefficient of theme keywords.' },
51
+ ],
52
+ threshold: '≥ 0.40 to qualify as meaningful comparison. Auto-tuned via comparison_calibration feedback loop.',
53
+ },
54
+ prediction: {
55
+ horizon: '7-day directional outlook',
56
+ phases: 'Rising (Emerging + Growth), Hot (Peak), Cooling (Decline + Dormant)',
57
+ reliability: 'Rising signals are most accurate. Cooling signals are reference-level only.',
58
+ },
59
+ dataSources: [
60
+ { name: 'Naver DataLab', provides: 'Search interest trends (relative values, 30-day window)' },
61
+ { name: 'Naver News', provides: 'Article counts and headlines' },
62
+ { name: 'Naver Finance', provides: 'Theme stock listings, prices, trading volumes' },
63
+ ],
64
+ updateSchedule: {
65
+ themeDiscovery: 'Sunday and Wednesday',
66
+ scores: 'Daily (full pipeline after market close)',
67
+ news: 'Daily (morning + evening)',
68
+ stocks: 'Weekdays (full)',
69
+ },
70
+ limitations: [
71
+ 'Naver DataLab 5-keyword batch limit requires self-normalization across batches — precision is limited.',
72
+ 'News momentum is article-count-based; sentiment analysis is not included (removed due to low accuracy).',
73
+ 'Data collection intervals mean latest market changes may not be immediately reflected.',
74
+ ],
75
+ disclaimer: 'This algorithm and its results are for informational purposes only, not investment advice. High scores indicate strong theme momentum, not necessarily investment opportunity — they may signal overheating.',
76
+ };
77
+ const SECTIONS = ['scoring', 'stabilization', 'stages', 'comparison', 'prediction', 'all'];
78
+ export const registerGetMethodology = (server) => {
79
+ server.tool('get_methodology', `Get the TLI (Theme Lifecycle Index) algorithm methodology — how scores, stages, and predictions work.
80
+
81
+ Use when the user asks:
82
+ - How are theme scores calculated?
83
+ - What do the lifecycle stages mean?
84
+ - How does the prediction work?
85
+ - TLI 알고리즘 설명, 점수 산출 방식, 단계 판정 기준
86
+ - What data sources are used?
87
+
88
+ Returns structured documentation of the scoring algorithm, stage determination, stabilization techniques, comparison analysis, and prediction methodology.`, {
89
+ section: z
90
+ .enum(SECTIONS)
91
+ .optional()
92
+ .describe('Specific section: scoring, stabilization, stages, comparison, prediction, or all (default: all)'),
93
+ }, async ({ section }) => {
94
+ const selected = section || 'all';
95
+ if (selected === 'all') {
96
+ return {
97
+ content: [{ type: 'text', text: JSON.stringify(METHODOLOGY, null, 2) }],
98
+ };
99
+ }
100
+ const sectionData = METHODOLOGY[selected];
101
+ const result = {
102
+ section: selected,
103
+ ...(typeof sectionData === 'object' ? sectionData : { value: sectionData }),
104
+ };
105
+ return {
106
+ content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
107
+ };
108
+ });
109
+ };
@@ -1,16 +1,24 @@
1
1
  import { z } from 'zod';
2
2
  import { fetchApi, formatResult, formatError } from '../fetch-helper.js';
3
+ const CONTEXT = `[StockMatrix Stock-to-Theme Lookup]
4
+ Shows all investment themes a specific Korean stock belongs to, with each theme's TLI score and lifecycle stage.
5
+ A stock can belong to multiple themes simultaneously. Use the returned theme_id with get_theme_detail for full analysis.
6
+ Common codes: 005930 (삼성전자), 000660 (SK하이닉스), 373220 (LG에너지솔루션), 035420 (NAVER), 035720 (카카오).`;
3
7
  export const registerGetStockTheme = (server) => {
4
- server.tool('get_stock_theme', '특정 종목이 속한 테마를 조회합니다. 종목 코드로 관련 테마 정보를 확인할 수 있습니다.', {
8
+ server.tool('get_stock_theme', `Find which investment themes a Korean stock belongs to.
9
+
10
+ Use when the user asks about a specific stock by its 6-digit code. Returns all associated themes with TLI scores and lifecycle stages.
11
+
12
+ Answers: "삼성전자 무슨 테마야?", "what themes is this stock part of?", "이 종목 관련 테마", "005930 테마 알려줘".`, {
5
13
  symbol: z
6
14
  .string()
7
15
  .regex(/^\d{6}$/, 'Korean stock code must be 6 digits')
8
- .describe('Korean stock code (e.g. "005930" for Samsung Electronics, "000660" for SK Hynix)'),
16
+ .describe('6-digit Korean stock code (e.g. "005930" for Samsung, "000660" for SK Hynix)'),
9
17
  }, async ({ symbol }) => {
10
18
  try {
11
19
  const data = await fetchApi(`/api/tli/stocks/${symbol}/theme`);
12
20
  return {
13
- content: [{ type: 'text', text: formatResult(data) }],
21
+ content: [{ type: 'text', text: formatResult(data, CONTEXT) }],
14
22
  };
15
23
  }
16
24
  catch (error) {
@@ -1,16 +1,29 @@
1
1
  import { z } from 'zod';
2
2
  import { fetchApi, formatResult, formatError } from '../fetch-helper.js';
3
+ const CONTEXT = `[StockMatrix Theme Detail]
4
+ Score components (Bayesian-optimized weights):
5
+ - interest (30.4%): Naver DataLab search volume — 7-day avg vs 30-day baseline
6
+ - newsMomentum (36.6%): Naver News article count — weekly change rate
7
+ - volatility (10.4%): Interest time-series standard deviation
8
+ - activity (22.6%): Related stock price changes, volume intensity, data coverage
9
+ Score stabilization: Cautious Decay (3-signal majority vote prevents false drops) → Bollinger Clamp → Age-adaptive EMA smoothing.
10
+ Stage transitions use Markov constraints + 2-day hysteresis.
11
+ Comparisons: 3-Pillar similarity (feature + curve + keyword) with Mutual Rank, threshold ≥ 0.40.`;
3
12
  export const registerGetThemeDetail = (server) => {
4
- server.tool('get_theme_detail', '특정 테마의 상세 정보를 조회합니다. 테마 점수, 생명주기 단계, 관련 종목, 뉴스 등을 포함합니다.', {
13
+ server.tool('get_theme_detail', `Get detailed analysis for a specific Korean stock theme.
14
+
15
+ Returns: TLI score breakdown (4 components with weights), lifecycle stage, 24h/7d score changes, prediction outlook, top related stocks with price changes, latest news headlines, and similar theme comparisons.
16
+
17
+ Use after get_theme_ranking or search_themes to drill into a specific theme. Answers: "tell me more about this theme", "what stocks are in this theme", "테마 상세 정보", "관련 종목 알려줘", "이 테마 전망".`, {
5
18
  theme_id: z
6
19
  .string()
7
20
  .uuid('Theme ID must be a valid UUID')
8
- .describe('Theme UUID (e.g. "a1b2c3d4-e5f6-7890-abcd-ef1234567890")'),
21
+ .describe('Theme UUID from ranking or search results'),
9
22
  }, async ({ theme_id }) => {
10
23
  try {
11
24
  const data = await fetchApi(`/api/tli/themes/${theme_id}`);
12
25
  return {
13
- content: [{ type: 'text', text: formatResult(data) }],
26
+ content: [{ type: 'text', text: formatResult(data, CONTEXT) }],
14
27
  };
15
28
  }
16
29
  catch (error) {
@@ -1,16 +1,27 @@
1
1
  import { z } from 'zod';
2
2
  import { fetchApi, formatResult, formatError } from '../fetch-helper.js';
3
+ const CONTEXT = `[StockMatrix Theme History — 30-day]
4
+ Daily TLI scores with stage transitions. Use to identify:
5
+ - Trend direction: rising scores = growing interest, falling = declining
6
+ - Stage transitions: stage changes require 2 consecutive days (hysteresis)
7
+ - Score stability: Cautious Decay prevents false drops from data gaps
8
+ - Momentum: EMA smoothing adapts to theme age (newer themes react faster)
9
+ Scores are 0-100, computed from interest + news + volatility + activity.`;
3
10
  export const registerGetThemeHistory = (server) => {
4
- server.tool('get_theme_history', '테마의 최근 30 점수 이력을 조회합니다. 생명주기 추이를 파악할 수 있습니다.', {
11
+ server.tool('get_theme_history', `Get 30-day score history for a Korean stock theme.
12
+
13
+ Returns daily TLI scores and stage transitions for trend analysis. Use when the user asks about theme momentum over time, whether a theme is gaining or losing interest, or wants to see historical trajectory.
14
+
15
+ Answers: "이 테마 추세가 어때?", "최근 한달 흐름", "is this theme gaining or losing momentum?", "show me the trend".`, {
5
16
  theme_id: z
6
17
  .string()
7
18
  .uuid('Theme ID must be a valid UUID')
8
- .describe('Theme UUID (e.g. "a1b2c3d4-e5f6-7890-abcd-ef1234567890")'),
19
+ .describe('Theme UUID from ranking or search results'),
9
20
  }, async ({ theme_id }) => {
10
21
  try {
11
22
  const data = await fetchApi(`/api/tli/themes/${theme_id}/history`);
12
23
  return {
13
- content: [{ type: 'text', text: formatResult(data) }],
24
+ content: [{ type: 'text', text: formatResult(data, CONTEXT) }],
14
25
  };
15
26
  }
16
27
  catch (error) {
@@ -7,29 +7,49 @@ const VALID_STAGES = [
7
7
  'decline',
8
8
  'reigniting',
9
9
  ];
10
+ const STAGE_DESCRIPTIONS = {
11
+ emerging: 'score < growth threshold, early interest signal',
12
+ growth: 'score ≥ 40 with stable/rising trend — expanding interest',
13
+ peak: 'score ≥ 71 or high score + news surge — maximum attention',
14
+ decline: 'falling trend + score drop + declining news coverage',
15
+ reigniting: 'previously declined theme showing renewed growth',
16
+ };
17
+ const CONTEXT = `[StockMatrix TLI Ranking]
18
+ Scores: 0-100 (Bayesian-optimized weighted sum of 4 components: interest 30%, news momentum 37%, volatility 10%, activity 23%).
19
+ Stages: Emerging → Growth → Peak → Decline → Dormant (with possible Reigniting). Stage transitions require 2 consecutive days of same candidate (hysteresis).
20
+ Higher score = stronger theme momentum. Stage indicates lifecycle position.`;
10
21
  export const registerGetThemeRanking = (server) => {
11
- server.tool('get_theme_ranking', '한국 주식시장 테마 생명주기 랭킹을 조회합니다. 단계별(초기/성장/정점/쇠퇴/재점화) 테마 목록과 점수를 반환합니다.', {
22
+ server.tool('get_theme_ranking', `Get Korean stock market theme rankings with lifecycle scores (TLI: Theme Lifecycle Index).
23
+
24
+ Use when the user asks about:
25
+ - Trending stock themes, hot investment sectors, market momentum
26
+ - What themes are rising/falling in Korea
27
+ - 한국 주식 테마 랭킹, 요즘 뜨는 테마, 상승/하락 테마
28
+ - KOSPI/KOSDAQ theme trends
29
+
30
+ Returns themes ranked by score (0-100) with lifecycle stage and related stocks. Scores are computed from search interest (Naver DataLab), news momentum, market volatility, and stock activity — all optimized via Bayesian optimization.`, {
12
31
  stage: z
13
32
  .enum(VALID_STAGES)
14
33
  .optional()
15
- .describe('Filter by lifecycle stage: emerging (초기), growth (성장), peak (정점), decline (쇠퇴), reigniting (재점화)'),
34
+ .describe('Filter by lifecycle stage: emerging (초기 — early interest), growth (성장 — expanding), peak (정점 — maximum attention), decline (하락 — fading), reigniting (재점화 — comeback)'),
16
35
  }, async ({ stage }) => {
17
36
  try {
18
37
  const data = await fetchApi('/api/tli/scores/ranking');
19
38
  if (stage) {
20
39
  const stageData = data[stage];
21
40
  const summary = data.summary;
41
+ const stageContext = `${CONTEXT}\nFiltered: ${stage} — ${STAGE_DESCRIPTIONS[stage]}`;
22
42
  return {
23
43
  content: [
24
44
  {
25
45
  type: 'text',
26
- text: formatResult({ stage, themes: stageData, summary }),
46
+ text: formatResult({ stage, themes: stageData, summary }, stageContext),
27
47
  },
28
48
  ],
29
49
  };
30
50
  }
31
51
  return {
32
- content: [{ type: 'text', text: formatResult(data) }],
52
+ content: [{ type: 'text', text: formatResult(data, CONTEXT) }],
33
53
  };
34
54
  }
35
55
  catch (error) {
@@ -1,17 +1,27 @@
1
1
  import { z } from 'zod';
2
2
  import { fetchApi, formatResult, formatError } from '../fetch-helper.js';
3
+ const CONTEXT = `[StockMatrix Theme Search]
4
+ Results include TLI score (0-100), lifecycle stage, and theme ID for drill-down.
5
+ Use theme_id with get_theme_detail for full analysis or get_theme_history for 30-day trend.
6
+ Stages: Emerging (초기) → Growth (성장) → Peak (정점) → Decline (하락), with Reigniting (재점화) for comeback themes.`;
3
7
  export const registerSearchThemes = (server) => {
4
- server.tool('search_themes', '테마를 검색합니다. 이름(한국어/영문)으로 필터링하여 일치하는 테마의 점수, 단계 정보를 반환합니다.', {
8
+ server.tool('search_themes', `Search Korean stock market themes by keyword (Korean or English).
9
+
10
+ Use when the user asks about a specific sector, industry, or investment theme. Searches theme names and related stock names.
11
+
12
+ Examples: "AI", "반도체" (semiconductor), "2차전지" (EV battery), "방산" (defense), "로봇" (robotics), "원자력" (nuclear), "삼성전자" (Samsung).
13
+
14
+ Returns matching themes with TLI scores and lifecycle stages. Use the returned theme_id with get_theme_detail or get_theme_history for deeper analysis.`, {
5
15
  query: z
6
16
  .string()
7
17
  .min(1)
8
18
  .max(200)
9
- .describe('Search query (theme name or related stock name, e.g. "AI", "반도체", "삼성전자")'),
19
+ .describe('Search query theme name, sector keyword, or stock name (Korean or English)'),
10
20
  }, async ({ query }) => {
11
21
  try {
12
22
  const data = await fetchApi('/api/tli/themes', { q: query });
13
23
  return {
14
- content: [{ type: 'text', text: formatResult(data) }],
24
+ content: [{ type: 'text', text: formatResult(data, CONTEXT) }],
15
25
  };
16
26
  }
17
27
  catch (error) {
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "stockmatrix-mcp",
3
3
  "mcpName": "io.github.MongLong0214/stockmatrix-mcp",
4
- "version": "0.1.3",
5
- "description": "StockMatrix MCP Server - Korean stock market theme lifecycle analysis for AI agents",
4
+ "version": "0.2.0",
5
+ "description": "StockMatrix MCP Server Korean stock market theme lifecycle analysis (TLI) with Bayesian-optimized scoring for AI agents",
6
6
  "type": "module",
7
7
  "main": "dist/index.js",
8
8
  "bin": {