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.
@@ -5,7 +5,13 @@ import { z } from 'zod';
5
5
  export declare const TrendsParamsSchema: z.ZodObject<{
6
6
  tag_code: z.ZodString;
7
7
  days: z.ZodDefault<z.ZodNumber>;
8
- }, z.core.$strip>;
8
+ }, "strip", z.ZodTypeAny, {
9
+ tag_code: string;
10
+ days: number;
11
+ }, {
12
+ tag_code: string;
13
+ days?: number | undefined;
14
+ }>;
9
15
  export type TrendsParams = z.infer<typeof TrendsParamsSchema>;
10
16
  export declare function getTrends(params: TrendsParams): Promise<{
11
17
  success: boolean;
@@ -13,6 +19,7 @@ export declare function getTrends(params: TrendsParams): Promise<{
13
19
  code: string;
14
20
  name: string;
15
21
  type: string;
22
+ name_en?: string;
16
23
  };
17
24
  trend: Array<{
18
25
  date: string;
package/dist/utils/api.js CHANGED
@@ -2,20 +2,80 @@
2
2
  * RagAlgo API 유틸리티
3
3
  * Supabase Edge Functions 호출
4
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;
5
+ const CACHE_TTL_MS = 5 * 60 * 1000; // 5분
6
+ const cache = new Map();
7
+ function getCacheKey(endpoint, params) {
8
+ const sortedParams = params
9
+ ? Object.entries(params)
10
+ .filter(([, v]) => v !== undefined)
11
+ .sort(([a], [b]) => a.localeCompare(b))
12
+ .map(([k, v]) => `${k}=${v}`)
13
+ .join('&')
14
+ : '';
15
+ return `${endpoint}?${sortedParams}`;
16
+ }
17
+ function getFromCache(key) {
18
+ const entry = cache.get(key);
19
+ if (!entry)
20
+ return null;
21
+ const now = Date.now();
22
+ if (now - entry.timestamp > CACHE_TTL_MS) {
23
+ cache.delete(key);
24
+ return null;
25
+ }
26
+ return entry.data;
27
+ }
28
+ function setCache(key, data) {
29
+ // 캐시 크기 제한 (최대 100개)
30
+ if (cache.size > 100) {
31
+ const oldestKey = cache.keys().next().value;
32
+ if (oldestKey)
33
+ cache.delete(oldestKey);
34
+ }
35
+ cache.set(key, {
36
+ data,
37
+ timestamp: Date.now()
38
+ });
39
+ }
40
+ // 캐시 통계 (디버그용)
41
+ let cacheHits = 0;
42
+ let cacheMisses = 0;
43
+ // ============================================================================
44
+ // [CHANGED] Dynamic URL Support
45
+ // If SUPABASE_URL is injected (from Desktop .env), use it. Otherwise fallback to hardcoded (Public default).
46
+ const DEFAULT_URL = 'https://xunrsikkybgxkybjzrgz.supabase.co/functions/v1';
47
+ const SUPABASE_URL = (process.env.SUPABASE_URL ? `${process.env.SUPABASE_URL}/functions/v1` : DEFAULT_URL).replace(/\/+$/, ''); // Remove trailing slash if double
48
+ // [DEBUG] Log active configuration
49
+ console.error(`[API Init] Target URL: ${SUPABASE_URL}`);
50
+ console.error(`[API Init] Env Override: ${!!process.env.SUPABASE_URL}`);
51
+ // [CHANGED] Get Keys from Environment (Injected by mcp_manager.py)
52
+ const getKeys = () => {
53
+ const apiKey = process.env.RAGALGO_API_KEY;
54
+ const anonKey = process.env.SUPABASE_ANON_KEY;
55
+ if (!apiKey) {
56
+ throw new Error('RAGALGO_API_KEY environment variable is missing.');
57
+ }
58
+ if (!anonKey) {
59
+ // Fallback for local testing if not injected, but log warning
60
+ console.error('[API] Warning: SUPABASE_ANON_KEY not found in env. Calls may fail.');
61
+ }
62
+ // [FALLBACK] Hardcoded Anon Key for reliability
63
+ const fallbackAnon = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Inh1bnJzaWtreWJneGt5Ymp6cmd6Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3NjQ0NTExNTgsImV4cCI6MjA4MDAyNzE1OH0.SsXri828-Rf0gHlu4Bls-pewhfMNNII4mbiuLnc9ACs";
64
+ return { apiKey, anonKey: anonKey || fallbackAnon };
14
65
  };
15
- // API 호출 기본 함수
66
+ // API 호출 기본 함수 (5분 캐시 적용)
16
67
  export async function callApi(endpoint, params) {
17
- const apiKey = getApiKey();
18
- // 쿼리 파라미터 생성
68
+ // [CACHE] 캐시 확인
69
+ const cacheKey = getCacheKey(endpoint, params);
70
+ const cachedData = getFromCache(cacheKey);
71
+ if (cachedData !== null) {
72
+ cacheHits++;
73
+ console.error(`[CACHE HIT] ${endpoint} (hits: ${cacheHits}, misses: ${cacheMisses})`);
74
+ return cachedData;
75
+ }
76
+ cacheMisses++;
77
+ console.error(`[CACHE MISS] ${endpoint} (hits: ${cacheHits}, misses: ${cacheMisses})`);
78
+ const { apiKey, anonKey } = getKeys();
19
79
  const url = new URL(`${SUPABASE_URL}/${endpoint}`);
20
80
  if (params) {
21
81
  Object.entries(params).forEach(([key, value]) => {
@@ -24,35 +84,49 @@ export async function callApi(endpoint, params) {
24
84
  }
25
85
  });
26
86
  }
87
+ const headers = {
88
+ 'Authorization': `Bearer ${anonKey.trim()}`,
89
+ 'apikey': anonKey.trim(),
90
+ 'x-api-key': apiKey.trim(),
91
+ 'Content-Type': 'application/json',
92
+ };
27
93
  const response = await fetch(url.toString(), {
28
94
  method: 'GET',
29
- headers: {
30
- 'Authorization': `Bearer ${SUPABASE_ANON_KEY}`,
31
- 'x-api-key': apiKey,
32
- 'Content-Type': 'application/json',
33
- },
95
+ headers: headers,
34
96
  });
35
97
  if (!response.ok) {
36
98
  const error = await response.text();
37
- throw new Error(`API 호출 실패: ${response.status} - ${error}`);
99
+ const debugInfo = `[DEBUG] keys_present=${!!anonKey}, URL: ${url.toString()}`;
100
+ if (response.status === 429) {
101
+ throw new Error(`[RATE LIMIT EXCEEDED] API 요청 제한에 도달했습니다. 잠시 후 다시 시도하거나 요청량을 줄여주세요. (Plan Quota Exceeded) | ${debugInfo}`);
102
+ }
103
+ throw new Error(`API 호출 실패: ${response.status} - ${error} | ${debugInfo}`);
38
104
  }
39
- return response.json();
105
+ const data = await response.json();
106
+ // [CACHE] 성공 시 캐시에 저장
107
+ setCache(cacheKey, data);
108
+ return data;
40
109
  }
41
- // POST API 호출
110
+ // POST API 호출 (POST는 캐시하지 않음 - 데이터 변경 가능성)
42
111
  export async function callApiPost(endpoint, body) {
43
- const apiKey = getApiKey();
112
+ const { apiKey, anonKey } = getKeys();
44
113
  const url = `${SUPABASE_URL}/${endpoint}`;
114
+ const headers = {
115
+ 'Authorization': `Bearer ${anonKey.trim()}`,
116
+ 'apikey': anonKey.trim(),
117
+ 'x-api-key': apiKey.trim(), // [FIX] anonKey → apiKey 수정
118
+ 'Content-Type': 'application/json',
119
+ };
45
120
  const response = await fetch(url, {
46
121
  method: 'POST',
47
- headers: {
48
- 'Authorization': `Bearer ${SUPABASE_ANON_KEY}`,
49
- 'x-api-key': apiKey,
50
- 'Content-Type': 'application/json',
51
- },
122
+ headers: headers,
52
123
  body: JSON.stringify(body),
53
124
  });
54
125
  if (!response.ok) {
55
126
  const error = await response.text();
127
+ if (response.status === 429) {
128
+ throw new Error(`[RATE LIMIT EXCEEDED] API 요청 제한에 도달했습니다. 잠시 후 다시 시도하거나 요청량을 줄여주세요. (Plan Quota Exceeded)`);
129
+ }
56
130
  throw new Error(`API 호출 실패: ${response.status} - ${error}`);
57
131
  }
58
132
  return response.json();
package/package.json CHANGED
@@ -1,41 +1,47 @@
1
1
  {
2
- "name": "ragalgo-mcp-server",
3
- "version": "1.0.5",
4
- "files": [
5
- "dist"
6
- ],
7
- "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).",
8
- "author": "",
9
- "main": "dist/index.js",
10
- "bin": {
11
- "ragalgo-mcp-server": "./dist/index.js"
12
- },
13
- "type": "module",
14
- "scripts": {
15
- "build": "npx tsc",
16
- "start": "node dist/index.js",
17
- "dev": "npx tsx src/index.ts"
18
- },
19
- "keywords": [
20
- "mcp",
21
- "ragalgo",
22
- "finance",
23
- "news",
24
- "ai"
25
- ],
26
- "license": "MIT",
27
- "dependencies": {
28
- "@modelcontextprotocol/sdk": "^1.0.0",
29
- "cors": "^2.8.5",
30
- "express": "^5.2.1",
31
- "zod": "^4.3.5",
32
- "zod-to-json-schema": "^3.25.1"
33
- },
34
- "devDependencies": {
35
- "@types/cors": "^2.8.19",
36
- "@types/express": "^5.0.6",
37
- "@types/node": "^20.19.26",
38
- "tsx": "^4.21.0",
39
- "typescript": "^5.9.3"
40
- }
2
+ "name": "ragalgo-mcp-server",
3
+ "version": "1.0.7",
4
+ "mcpName": "io.github.kokogo100/ragalgo",
5
+ "files": [
6
+ "dist",
7
+ "README.md",
8
+ "server.json"
9
+ ],
10
+ "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).",
11
+ "main": "dist/index.js",
12
+ "bin": {
13
+ "ragalgo-mcp-server": "./dist/index.js"
14
+ },
15
+ "type": "module",
16
+ "scripts": {
17
+ "build": "npx tsc",
18
+ "start": "node dist/index.js",
19
+ "dev": "npx tsx src/index.ts"
20
+ },
21
+ "keywords": [
22
+ "mcp",
23
+ "rag",
24
+ "ai-reliability",
25
+ "context-scoring",
26
+ "finance",
27
+ "korea-market"
28
+ ],
29
+ "author": "RagAlgo Team",
30
+ "license": "MIT",
31
+ "dependencies": {
32
+ "@modelcontextprotocol/sdk": "^1.0.0",
33
+ "@types/uuid": "^10.0.0",
34
+ "cors": "^2.8.5",
35
+ "express": "^4.21.2",
36
+ "uuid": "^13.0.0",
37
+ "zod": "^3.25.0",
38
+ "zod-to-json-schema": "^3.25.1"
39
+ },
40
+ "devDependencies": {
41
+ "@types/cors": "^2.8.19",
42
+ "@types/express": "^5.0.6",
43
+ "@types/node": "^20.19.26",
44
+ "tsx": "^4.21.0",
45
+ "typescript": "^5.9.3"
46
+ }
41
47
  }
package/server.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
3
+ "name": "io.github.kokogo100/ragalgo",
4
+ "description": "Dynamic RAG Engine preventing AI hallucinations in Korean Finance and Crypto markets.",
5
+ "status": "active",
6
+ "repository": {
7
+ "url": "https://github.com/kokogo100/ragalgo-mcp-server",
8
+ "source": "github"
9
+ },
10
+ "version": "1.0.7",
11
+ "packages": [
12
+ {
13
+ "registryType": "npm",
14
+ "registry_type": "npm",
15
+ "registry_base_url": "https://registry.npmjs.org",
16
+ "identifier": "ragalgo-mcp-server",
17
+ "version": "1.0.7",
18
+ "transport": {
19
+ "type": "stdio"
20
+ },
21
+ "environment_variables": [
22
+ {
23
+ "description": "Your API key for the RagAlgo service",
24
+ "is_required": true,
25
+ "format": "string",
26
+ "is_secret": true,
27
+ "name": "RAGALGO_API_KEY"
28
+ }
29
+ ]
30
+ }
31
+ ]
32
+ }