sometrend-mcp-server
Version:
TM2 기반의 썸트렌드(sometrend) MCP 서버 - 트렌드 분석 및 데이터 처리
289 lines (239 loc) • 7.82 kB
text/typescript
/**
* 썸트렌드 MCP 서버 CLI 진입점
* npx sometrend-mcp-server 로 실행
*/
import { spawn } from 'child_process';
import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
import { join, dirname } from 'path';
import { homedir } from 'os';
import { stdin, stdout } from 'process';
import { fileURLToPath } from 'url';
import readline from 'readline';
// ES Module에서 __dirname 대체
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
// CLI 인수 파싱
const args = process.argv.slice(2);
const isServerMode = args.includes('--server') || args.includes('-s');
const isSetupMode = args.includes('--setup');
const isHelpMode = args.includes('--help') || args.includes('-h');
const portIndex = args.findIndex(arg => arg === '--port' || arg === '-p');
const port = portIndex !== -1 && args[portIndex + 1] ? parseInt(args[portIndex + 1]) : 8000;
// 설정 파일 경로
const configDir = join(homedir(), '.sometrend-mcp');
const configFile = join(configDir, 'config.json');
interface Config {
apiKey?: string;
baseUrl?: string;
timeout?: number;
}
/**
* 도움말 표시
*/
function showHelp() {
console.log(`
🚀 썸트렌드 MCP 서버
사용법:
npx sometrend-mcp-server [옵션]
옵션:
--setup, --config API 키 설정 (최초 1회)
--server, -s 서버 모드로 실행 (SSE)
--port, -p <번호> 서버 포트 (기본값: 8000)
--help, -h 도움말 표시
예시:
npx sometrend-mcp-server --setup # API 키 설정
npx sometrend-mcp-server # STDIO 모드 (Claude Desktop용)
npx sometrend-mcp-server --server # 서버 모드
npx sometrend-mcp-server -s -p 3000 # 포트 3000으로 서버 실행
📋 API 키 발행 방법:
1. 이메일로 API 키 발급 신청: biz@vaiv.kr
2. 회사명, 사용 목적, 연락처 정보 포함하여 문의
3. 승인 후 발급받은 API 키를 --setup 명령으로 설정
📞 문의처:
- 이메일: biz@vaiv.kr
- 전화: 02-565-0531
- 회사: ㈜바이브컴퍼니
설정:
API 키는 ~/.sometrend-mcp/config.json에 저장됩니다.
또는 환경변수 TM2_API_KEY를 사용할 수 있습니다.
`);
}
/**
* 설정 파일 읽기
*/
function loadConfig(): Config {
if (!existsSync(configFile)) {
return {};
}
try {
const content = readFileSync(configFile, 'utf-8');
return JSON.parse(content);
} catch (error) {
console.error('설정 파일 읽기 오류:', error);
return {};
}
}
/**
* 설정 파일 저장
*/
function saveConfig(config: Config) {
if (!existsSync(configDir)) {
mkdirSync(configDir, { recursive: true });
}
try {
writeFileSync(configFile, JSON.stringify(config, null, 2));
console.log('✅ 설정이 저장되었습니다:', configFile);
} catch (error) {
console.error('설정 파일 저장 오류:', error);
process.exit(1);
}
}
/**
* API 키 입력받기 (숨김 처리)
*/
function promptApiKey(): Promise<string> {
return new Promise((resolve) => {
const rl = readline.createInterface({
input: stdin,
output: stdout
});
// API 키 입력 시 숨김 처리
rl.question('썸트렌드 API 키를 입력하세요: ', (apiKey) => {
rl.close();
resolve(apiKey.trim());
});
// 입력 숨김 처리 (별표로 표시)
(rl as any)._writeToOutput = function(stringToWrite: string) {
if (stringToWrite.includes('썸트렌드 API 키')) {
stdout.write(stringToWrite);
} else {
stdout.write('*');
}
};
});
}
/**
* 설정 모드
*/
async function setupMode() {
console.log('🔧 썸트렌드 MCP 서버 설정\n');
const config = loadConfig();
// API 키 입력
const apiKey = await promptApiKey();
if (!apiKey) {
console.error('❌ API 키가 필요합니다.');
process.exit(1);
}
config.apiKey = apiKey;
config.baseUrl = config.baseUrl || 'http://10.1.41.49:9292';
config.timeout = config.timeout || 300000;
saveConfig(config);
console.log('\n✅ 설정 완료! 이제 다음 명령으로 서버를 실행할 수 있습니다:');
console.log(' npx sometrend-mcp-server # STDIO 모드');
console.log(' npx sometrend-mcp-server --server # 서버 모드');
}
/**
* API 키 검증
*/
function validateApiKey(): string {
// 1. 환경변수 확인 (우선순위: TM2_API_KEY > SOMETREND_API_KEY)
let apiKey = process.env.TM2_API_KEY || process.env.SOMETREND_API_KEY;
// 2. 설정 파일 확인
if (!apiKey) {
const config = loadConfig();
apiKey = config.apiKey;
}
if (!apiKey) {
console.error(`
❌ API 키가 설정되지 않았습니다.
다음 중 하나의 방법으로 API 키를 설정하세요:
1. 설정 명령 사용:
npx sometrend-mcp-server --setup
2. 환경변수 설정:
export TM2_API_KEY="your-api-key"
npx sometrend-mcp-server
3. 도움말 확인:
npx sometrend-mcp-server --help
`);
process.exit(1);
}
return apiKey;
}
/**
* 메인 실행 함수
*/
async function main() {
// 도움말 모드
if (isHelpMode) {
showHelp();
return;
}
// 설정 모드
if (isSetupMode) {
await setupMode();
return;
}
// API 키 검증
const apiKey = validateApiKey();
const config = loadConfig();
// 환경변수 설정
process.env.TM2_API_KEY = apiKey;
process.env.SOMETREND_API_KEY = apiKey; // 백워드 호환성
process.env.TM2_BASE_URL = config.baseUrl || 'http://10.1.41.49:9292';
process.env.API_TIMEOUT = String(config.timeout || 300000);
// 서버 모드 vs STDIO 모드
if (isServerMode) {
console.log(`🚀 썸트렌드 MCP 서버 시작 (포트 ${port})`);
console.log(' Ctrl+C로 종료하세요.\n');
process.env.PORT = String(port);
// SSE 서버 실행
const { spawn } = await import('child_process');
const serverProcess = spawn('node', [join(__dirname, 'index-sse.js')], {
stdio: 'inherit',
env: process.env
});
// 프로세스 종료 처리
process.on('SIGINT', () => {
serverProcess.kill('SIGTERM');
process.exit(0);
});
process.on('SIGTERM', () => {
serverProcess.kill('SIGTERM');
process.exit(0);
});
} else {
// STDIO 모드 (Claude Desktop용)
console.error('🔗 썸트렌드 MCP 서버 (STDIO 모드)');
console.error(' Claude Desktop과 연결되었습니다.\n');
// STDIO MCP 서버 실행
const { spawn } = await import('child_process');
const stdioProcess = spawn('node', [join(__dirname, 'index.js')], {
stdio: ['inherit', 'inherit', 'inherit'],
env: process.env
});
// 프로세스 종료 처리
process.on('SIGINT', () => {
stdioProcess.kill('SIGTERM');
process.exit(0);
});
process.on('SIGTERM', () => {
stdioProcess.kill('SIGTERM');
process.exit(0);
});
}
}
// 에러 처리
process.on('uncaughtException', (error) => {
console.error('예상치 못한 오류:', error);
process.exit(1);
});
process.on('unhandledRejection', (error) => {
console.error('처리되지 않은 Promise 거부:', error);
process.exit(1);
});
// 메인 함수 실행
main().catch((error) => {
console.error('CLI 실행 오류:', error);
process.exit(1);
});