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 +68 -37
- package/dist/fetch-helper.d.ts +2 -1
- package/dist/fetch-helper.js +11 -2
- package/dist/index.js +7 -2
- package/dist/tools/get-methodology.d.ts +2 -0
- package/dist/tools/get-methodology.js +109 -0
- package/dist/tools/get-stock-theme.js +11 -3
- package/dist/tools/get-theme-detail.js +16 -3
- package/dist/tools/get-theme-history.js +14 -3
- package/dist/tools/get-theme-ranking.js +24 -4
- package/dist/tools/search-themes.js +13 -3
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
# stockmatrix-mcp
|
|
2
2
|
|
|
3
|
-
MCP server for Korean stock market theme
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
74
|
+
Get theme rankings by lifecycle stage.
|
|
63
75
|
|
|
64
76
|
| Parameter | Type | Required | Description |
|
|
65
77
|
|-----------|------|----------|-------------|
|
|
66
|
-
| `stage` | string | No |
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
### `
|
|
104
|
+
### `get_stock_theme`
|
|
85
105
|
|
|
86
|
-
|
|
106
|
+
Find themes a specific stock belongs to.
|
|
87
107
|
|
|
88
108
|
| Parameter | Type | Required | Description |
|
|
89
109
|
|-----------|------|----------|-------------|
|
|
90
|
-
| `
|
|
110
|
+
| `symbol` | string | Yes | 6-digit code, e.g. `"005930"` (Samsung), `"000660"` (SK Hynix) |
|
|
91
111
|
|
|
92
|
-
### `
|
|
112
|
+
### `get_methodology`
|
|
93
113
|
|
|
94
|
-
|
|
114
|
+
Get TLI algorithm documentation — scoring, stages, stabilization, comparison, prediction.
|
|
95
115
|
|
|
96
116
|
| Parameter | Type | Required | Description |
|
|
97
117
|
|-----------|------|----------|-------------|
|
|
98
|
-
| `
|
|
118
|
+
| `section` | string | No | `scoring` / `stabilization` / `stages` / `comparison` / `prediction` / `all` |
|
|
99
119
|
|
|
100
|
-
##
|
|
120
|
+
## Scoring Algorithm
|
|
101
121
|
|
|
102
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
112
|
-
→ `search_themes` with `query: "반도체"` → `get_theme_detail` with the returned theme ID
|
|
133
|
+
## Lifecycle Stages
|
|
113
134
|
|
|
114
|
-
|
|
115
|
-
→
|
|
135
|
+
```
|
|
136
|
+
Dormant → Emerging → Growth → Peak → Decline → Dormant
|
|
137
|
+
↓
|
|
138
|
+
Reigniting
|
|
139
|
+
```
|
|
116
140
|
|
|
117
|
-
|
|
141
|
+
Stage transitions require 2 consecutive days of the same candidate (hysteresis) and follow Markov transition constraints.
|
|
118
142
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
-
|
|
122
|
-
-
|
|
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
|
|
package/dist/fetch-helper.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export declare const fetchApi: <T = unknown>(path: string, params?: Record<string, string>) => Promise<T>;
|
|
2
|
-
|
|
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;
|
package/dist/fetch-helper.js
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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
|
|
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(
|
|
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,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
|
|
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
|
|
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',
|
|
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
|
|
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 (
|
|
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
|
|
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.
|
|
5
|
-
"description": "StockMatrix MCP Server
|
|
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": {
|