stockmatrix-mcp 0.1.1 → 0.1.3
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 +0 -1
- package/dist/fetch-helper.js +62 -22
- package/dist/index.d.ts +2 -1
- package/dist/index.js +14 -9
- package/dist/tools/search-themes.js +1 -0
- package/package.json +1 -9
package/README.md
CHANGED
package/dist/fetch-helper.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const BASE_URL = process.env.STOCKMATRIX_API_URL || 'https://stockmatrix.co.kr';
|
|
2
|
+
const MCP_USER_AGENT = `stockmatrix-mcp/0.1.3`;
|
|
2
3
|
// 시작 시 URL 유효성 검증
|
|
3
4
|
try {
|
|
4
5
|
new URL(BASE_URL);
|
|
@@ -6,6 +7,22 @@ try {
|
|
|
6
7
|
catch {
|
|
7
8
|
throw new Error(`Invalid STOCKMATRIX_API_URL: "${BASE_URL}" is not a valid URL`);
|
|
8
9
|
}
|
|
10
|
+
const FETCH_TIMEOUT_MS = 15_000;
|
|
11
|
+
const MAX_RETRIES = 2;
|
|
12
|
+
const RETRY_BASE_MS = 1_000;
|
|
13
|
+
const RETRYABLE_STATUS = new Set([429, 502, 503, 504]);
|
|
14
|
+
const isRetryable = (error) => {
|
|
15
|
+
if (error instanceof Error) {
|
|
16
|
+
const msg = error.message;
|
|
17
|
+
return (msg.includes('ECONNRESET') ||
|
|
18
|
+
msg.includes('ETIMEDOUT') ||
|
|
19
|
+
msg.includes('UND_ERR_CONNECT_TIMEOUT') ||
|
|
20
|
+
msg.includes('fetch failed') ||
|
|
21
|
+
RETRYABLE_STATUS.has(Number(msg.match(/API request failed: (\d+)/)?.[1])));
|
|
22
|
+
}
|
|
23
|
+
return false;
|
|
24
|
+
};
|
|
25
|
+
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
9
26
|
export const fetchApi = async (path, params) => {
|
|
10
27
|
const url = new URL(path, BASE_URL);
|
|
11
28
|
if (params) {
|
|
@@ -13,30 +30,53 @@ export const fetchApi = async (path, params) => {
|
|
|
13
30
|
url.searchParams.set(key, value);
|
|
14
31
|
}
|
|
15
32
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
let lastError;
|
|
34
|
+
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
35
|
+
if (attempt > 0) {
|
|
36
|
+
await sleep(RETRY_BASE_MS * 2 ** (attempt - 1));
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
const response = await fetch(url.toString(), {
|
|
40
|
+
headers: {
|
|
41
|
+
Accept: 'application/json',
|
|
42
|
+
'User-Agent': MCP_USER_AGENT,
|
|
43
|
+
},
|
|
44
|
+
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),
|
|
45
|
+
});
|
|
46
|
+
if (!response.ok) {
|
|
47
|
+
const errorText = await response.text().catch(() => 'Unknown error');
|
|
48
|
+
throw new Error(`API request failed: ${response.status} ${response.statusText} - ${errorText}`);
|
|
49
|
+
}
|
|
50
|
+
const contentType = response.headers.get('content-type') || '';
|
|
51
|
+
if (!contentType.includes('application/json')) {
|
|
52
|
+
const preview = await response.text().catch(() => '');
|
|
53
|
+
throw new Error(`Expected JSON response but got ${contentType || 'unknown'}: ${preview.slice(0, 200)}`);
|
|
54
|
+
}
|
|
55
|
+
const json = await response.json();
|
|
56
|
+
if (json === null || json === undefined) {
|
|
57
|
+
throw new Error('API returned null or undefined response');
|
|
58
|
+
}
|
|
59
|
+
if (typeof json === 'object' &&
|
|
60
|
+
json !== null &&
|
|
61
|
+
'success' in json &&
|
|
62
|
+
'data' in json) {
|
|
63
|
+
const wrapped = json;
|
|
64
|
+
if (!wrapped.success) {
|
|
65
|
+
throw new Error(wrapped.error?.message || 'API returned unsuccessful response');
|
|
66
|
+
}
|
|
67
|
+
return wrapped.data;
|
|
68
|
+
}
|
|
69
|
+
return json;
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
lastError = error;
|
|
73
|
+
if (attempt < MAX_RETRIES && isRetryable(error)) {
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
throw error;
|
|
36
77
|
}
|
|
37
|
-
return wrapped.data;
|
|
38
78
|
}
|
|
39
|
-
|
|
79
|
+
throw lastError;
|
|
40
80
|
};
|
|
41
81
|
export const formatResult = (data) => JSON.stringify(data, null, 2);
|
|
42
82
|
export const formatError = (error) => {
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -6,15 +6,20 @@ import { registerGetThemeDetail } from './tools/get-theme-detail.js';
|
|
|
6
6
|
import { registerGetThemeHistory } from './tools/get-theme-history.js';
|
|
7
7
|
import { registerSearchThemes } from './tools/search-themes.js';
|
|
8
8
|
import { registerGetStockTheme } from './tools/get-stock-theme.js';
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
9
|
+
const createServer = () => {
|
|
10
|
+
const s = new McpServer({
|
|
11
|
+
name: 'stockmatrix-mcp',
|
|
12
|
+
version: '0.1.3',
|
|
13
|
+
});
|
|
14
|
+
registerGetThemeRanking(s);
|
|
15
|
+
registerGetThemeDetail(s);
|
|
16
|
+
registerGetThemeHistory(s);
|
|
17
|
+
registerSearchThemes(s);
|
|
18
|
+
registerGetStockTheme(s);
|
|
19
|
+
return s;
|
|
20
|
+
};
|
|
21
|
+
export const createSandboxServer = () => createServer();
|
|
22
|
+
const server = createServer();
|
|
18
23
|
const main = async () => {
|
|
19
24
|
const transport = new StdioServerTransport();
|
|
20
25
|
await server.connect(transport);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "stockmatrix-mcp",
|
|
3
3
|
"mcpName": "io.github.MongLong0214/stockmatrix-mcp",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.3",
|
|
5
5
|
"description": "StockMatrix MCP Server - Korean stock market theme lifecycle analysis for AI agents",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "dist/index.js",
|
|
@@ -26,15 +26,7 @@
|
|
|
26
26
|
"kosdaq",
|
|
27
27
|
"ai-agent"
|
|
28
28
|
],
|
|
29
|
-
"repository": {
|
|
30
|
-
"type": "git",
|
|
31
|
-
"url": "https://github.com/MongLong0214/stock-ai-newsletter.git",
|
|
32
|
-
"directory": "mcp"
|
|
33
|
-
},
|
|
34
29
|
"homepage": "https://stockmatrix.co.kr/developers",
|
|
35
|
-
"bugs": {
|
|
36
|
-
"url": "https://github.com/MongLong0214/stock-ai-newsletter/issues"
|
|
37
|
-
},
|
|
38
30
|
"license": "MIT",
|
|
39
31
|
"author": "StockMatrix <aistockmatrix@gmail.com>",
|
|
40
32
|
"engines": {
|