UNPKG

sometrend-mcp-server

Version:

TM2 기반의 썸트렌드(sometrend) MCP 서버 - 트렌드 분석 및 데이터 처리

779 lines (756 loc) 29.3 kB
/** * 썸트렌드(sometrend) MCP 도구 정의 * * 썸트렌드(sometrend) API를 통해 제공되는 다양한 분석 도구들을 정의합니다. * - 시스템 정보 도구: 데이터소스, 헬스체크 * - 분류체계 도구: 카테고리 관리 키워드 분류 * - 분석 도구: 문서량, 언급량, 연관어, 감성 분석 */ import type { ToolDefinition, ToolCategory, ToolStatistics, ToolConstants } from '../types/tools.js'; // 공통 설명 상수 - AI 도구 사용성을 위한 핵심 정보 포함 const DATA_SOURCE_DESCRIPTION = "데이터소스 ID - blog(블로그: 리뷰/제품분석 적합), twitter(트위터: 실시간 여론), news(뉴스: 공식 보도), insta(인스타그램: 시각적 트렌드), community(커뮤니티: 깊이있는 토론), youtube(유튜브: 영상 콘텐츠), naver_blog(네이버블로그: 국내 개인 의견)"; const KEYWORD_DESCRIPTION = "분석할 키워드 - 공백 불허, OR 검색: ||, AND 검색: &&, NOT 검색: ~(), 괄호 그룹화 가능. 예: '아이폰||갤럭시', '삼성&&스마트폰'"; const CATEGORY_TYPE_DESCRIPTION = "분류체계 ID - SM(포괄적 분석용), TSN3(트렌드/마케팅 특화)"; // === 시스템 정보 기본 도구 정의 === export const SYSTEM_TOOL_DEFINITIONS: ToolDefinition[] = [ { name: "getAvailableDataSources", description: "썸트렌드 분석에 사용 가능한 모든 데이터 소스 목록을 조회합니다. 블로그, 트위터, 뉴스, 인스타그램, 커뮤니티, 유튜브, 네이버 블로그 등 7개 주요 채널의 정보와 활성화 상태를 확인할 수 있습니다.", inputSchema: { type: "object" as const, properties: { detail: { type: "boolean" as const, description: "상세 정보 포함 여부 (기본값: false)" } }, required: [] as const } }, { name: "getAvailableSnsChannels", description: "소셜미디어 분석을 위한 SNS 채널별 세부 정보를 조회합니다. 각 채널의 데이터 수집 범위, 업데이트 주기, 분석 가능한 콘텐츠 유형 등을 제공하여 채널별 맞춤 분석 전략 수립에 활용됩니다.", inputSchema: { type: "object" as const, properties: { detail: { type: "boolean" as const, description: "상세 정보 포함 여부 (기본값: false)" } }, required: [] as const } }, { name: "availableCategories", description: "분류체계 목록을 조회합니다. SM(Social Metrics), TSN3(Trend Seek 3.0) 등 각 분류체계의 특성과 활용 목적을 확인하여 키워드 분류 분석에 적절한 분류체계를 선택할 수 있습니다.", inputSchema: { type: "object" as const, properties: { detail: { type: "boolean" as const, description: "상세 정보 포함 여부 (기본값: false)" } }, required: [] as const } }, { name: "getCategorySetList", description: "분류체계별 상세 정보와 포함된 카테고리 개수 등을 조회하는 도구입니다. " + "availableCategoryes와 유사하지만 더 구체적인 분류체계 메타데이터를 제공합니다. " + "대규모 키워드 분류 작업이나 체계적인 카테고리 분석을 계획할 때 활용됩니다.\n\n" + "* input parameters: detail (상세정보 포함 여부)\n" + "* output fields: categorySetId, name, description, totalCategories, lastUpdated", inputSchema: { type: "object" as const, properties: { detail: { type: "boolean" as const, description: "상세 정보 포함 여부 (기본값: false)" } }, required: [] as const } } ]; // === 분류체계 관련 도구 정의 === export const CATEGORY_TOOL_DEFINITIONS: ToolDefinition[] = [ { name: "getCategoryList", description: "특정 분류체계 내의 모든 카테고리 목록과 계층 구조를 조회하는 도구입니다. " + "SM 또는 TSN3 분류체계에서 사용 가능한 카테고리들의 상세 정보를 제공합니다. " + "키워드를 특정 카테고리로 분류하거나 카테고리별 분석을 수행하기 전에 전체 분류 구조를 파악할 때 사용됩니다. " + "예를 들어, 'IT 관련 키워드들을 어떤 카테고리로 분류할 수 있는지 알고 싶을 때' 이 도구를 먼저 호출합니다.\n\n" + "* input parameters: source, categorySetId\n" + "* output fields: categoryId, categoryName, parentCategory, level, description", inputSchema: { type: "object" as const, properties: { source: { type: "string" as const, description: DATA_SOURCE_DESCRIPTION }, categorySetId: { type: "string" as const, description: "분류체계 ID" } }, required: ["source", "categorySetId"] as const } }, { name: "getKeywordCategory", description: "키워드를 AI 분류 엔진을 통해 자동으로 카테고리에 분류합니다.", inputSchema: { type: "object" as const, properties: { source: { type: "string" as const, description: DATA_SOURCE_DESCRIPTION }, categorySetId: { type: "string" as const, description: "분류체계 ID" }, keyword: { type: "string" as const, description: "분석할 키워드, 키워드에 공백을 허용하지 않음, 동의어 입력시 \"||\" 로 구분 ex) \"아이폰||갤럭시\")" } }, required: ["source", "categorySetId", "keyword"] as const } }, { name: "getKeywordCategories", description: "여러 키워드의 카테고리 분류를 일괄 처리합니다 (GET 방식).", inputSchema: { type: "object" as const, properties: { source: { type: "string" as const, description: DATA_SOURCE_DESCRIPTION }, categorySetId: { type: "string" as const, description: "분류체계 ID" }, keywords: { type: "array" as const, items: { type: "string" as const }, description: "분석할 키워드, 키워드에 공백을 허용하지 않음, 동의어 입력시 \"||\" 로 구분 ex) \"아이폰||갤럭시\")" } }, required: ["source", "categorySetId", "keywords"] as const } }, { name: "getKeywordCategoriesPost", description: "대규모 키워드 리스트의 카테고리 분류를 효율적으로 처리합니다 (POST 방식).", inputSchema: { type: "object" as const, properties: { source: { type: "string" as const, description: DATA_SOURCE_DESCRIPTION }, categorySetId: { type: "string" as const, description: "분류체계 ID" }, keywords: { type: "array" as const, items: { type: "string" as const }, description: "분류할 키워드 목록 (대량 처리용), 키워드에 공백을 허용하지 않음, 동의어 입력시 \"||\" 로 구분 ex) \"아이폰||갤럭시\")" } }, required: ["source", "categorySetId", "keywords"] as const } } ]; // === 문서 언급량 분석 도구 정의 === export const DOCUMENT_ANALYSIS_TOOL_DEFINITIONS: ToolDefinition[] = [ { name: "documentCounts", description: "데이터소스의 전체 문서 개수를 기간별로 집계합니다.", inputSchema: { type: "object" as const, properties: { source: { type: "string" as const, description: DATA_SOURCE_DESCRIPTION }, startDate: { type: "string" as const, description: "시작 날짜 (YYYYMMDD 형식)" }, endDate: { type: "string" as const, description: "종료 날짜 (YYYYMMDD 형식)" }, period: { type: "string" as const, enum: ["day", "week", "month"] as const, description: "집계 단위 (일/주/월)", default: "day" } }, required: ["source", "startDate", "endDate", "period"] as const } }, { name: "keywordMentions", description: "키워드가 언급된 문서 수의 시간별 추이를 분석합니다 (버즈 분석).", inputSchema: { type: "object" as const, properties: { source: { type: "string" as const, description: DATA_SOURCE_DESCRIPTION }, keyword: { type: "string" as const, description: KEYWORD_DESCRIPTION }, startDate: { type: "string" as const, description: "시작 날짜 (YYYYMMDD 형식)" }, endDate: { type: "string" as const, description: "종료 날짜 (YYYYMMDD 형식)" }, period: { type: "string" as const, enum: ["day", "week", "month"] as const, description: "집계 단위 (일/주/월)", default: "day" } }, required: ["source", "keyword", "startDate", "endDate", "period"] as const } }, { name: "keywordDocuments", description: "키워드가 포함된 실제 문서들의 상세 내용을 조회합니다.", inputSchema: { type: "object" as const, properties: { source: { type: "string" as const, description: DATA_SOURCE_DESCRIPTION }, keyword: { type: "string" as const, description: KEYWORD_DESCRIPTION }, startDate: { type: "string" as const, description: "시작 날짜 (YYYYMMDD 형식)" }, endDate: { type: "string" as const, description: "종료 날짜 (YYYYMMDD 형식)" }, period: { type: "string" as const, enum: ["day", "week", "month"] as const, description: "집계 단위 (일/주/월)", default: "week" }, limit: { type: "integer" as const, description: "결과 개수 제한", default: 10, minimum: 1, maximum: 30 }, offset: { type: "integer" as const, description: "결과 시작 위치", default: 0, minimum: 0 } }, required: ["source", "keyword", "startDate", "endDate"] as const } } ]; // === 연관어 분석 도구 정의 === export const ASSOCIATION_ANALYSIS_TOOL_DEFINITIONS: ToolDefinition[] = [ { name: "keywordAssociations", description: "주제 키워드와 함께 언급되는 연관 키워드의 빈도를 분석합니다.", inputSchema: { type: "object" as const, properties: { source: { type: "string" as const, description: DATA_SOURCE_DESCRIPTION }, keyword: { type: "string" as const, description: KEYWORD_DESCRIPTION }, startDate: { type: "string" as const, description: "시작 날짜 (YYYYMMDD 형식)" }, endDate: { type: "string" as const, description: "종료 날짜 (YYYYMMDD 형식)" }, topN: { type: "integer" as const, description: "연관어 개수 제한", default: 10, minimum: 1, maximum: 50 } }, required: ["source", "keyword", "startDate", "endDate", "topN"] as const } }, { name: "associationTransitionByCategory", description: "카테고리별 연관어들의 날짜별 변화 추이를 분석합니다.", inputSchema: { type: "object" as const, properties: { source: { type: "string" as const, description: DATA_SOURCE_DESCRIPTION }, categorySetId: { type: "string" as const, description: "분류체계 ID" }, keyword: { type: "string" as const, description: KEYWORD_DESCRIPTION }, startDate: { type: "string" as const, description: "시작 날짜 (YYYYMMDD 형식)" }, endDate: { type: "string" as const, description: "종료 날짜 (YYYYMMDD 형식)" }, period: { type: "string" as const, enum: ["day", "week", "month"] as const, description: "집계 단위 (일/주/월)", default: "week" } }, required: ["source", "categorySetId", "keyword", "startDate", "endDate"] as const } }, { name: "topAssociationByPeriod", description: "기간별 상위 연관어 순위 변화를 추적하여 트렌드 전환점을 발견합니다.", inputSchema: { type: "object" as const, properties: { source: { type: "string" as const, description: DATA_SOURCE_DESCRIPTION }, keyword: { type: "string" as const, description: KEYWORD_DESCRIPTION }, startDate: { type: "string" as const, description: "시작 날짜 (YYYYMMDD 형식)" }, endDate: { type: "string" as const, description: "종료 날짜 (YYYYMMDD 형식)" }, period: { type: "string" as const, enum: ["day", "week", "month"] as const, description: "집계 단위 (일/주/월)", default: "week" }, topN: { type: "integer" as const, description: "상위 N개 연관어", default: 15, minimum: 1, maximum: 50 } }, required: ["source", "keyword", "startDate", "endDate", "period", "topN"] as const } } ]; // === 감성 분석 도구 정의 === export const SENTIMENT_ANALYSIS_TOOL_DEFINITIONS: ToolDefinition[] = [ { name: "keywordSentiment", description: "키워드와 관련된 감성 표현의 강도를 분석합니다.", inputSchema: { type: "object" as const, properties: { source: { type: "string" as const, description: DATA_SOURCE_DESCRIPTION }, keyword: { type: "string" as const, description: KEYWORD_DESCRIPTION }, startDate: { type: "string" as const, description: "시작 날짜 (YYYYMMDD 형식)" }, endDate: { type: "string" as const, description: "종료 날짜 (YYYYMMDD 형식)" }, period: { type: "string" as const, enum: ["day", "week", "month"] as const, description: "집계 단위 (일/주/월)", default: "day" } }, required: ["source", "keyword", "startDate", "endDate", "period"] as const } }, { name: "associationTransitionBySentiment", description: "감성 카테고리별 연관어들의 날짜별 변화를 분석합니다.", inputSchema: { type: "object" as const, properties: { source: { type: "string" as const, description: DATA_SOURCE_DESCRIPTION }, keyword: { type: "string" as const, description: KEYWORD_DESCRIPTION }, startDate: { type: "string" as const, description: "시작 날짜 (YYYYMMDD 형식)" }, endDate: { type: "string" as const, description: "종료 날짜 (YYYYMMDD 형식)" }, sentiment: { type: "string" as const, enum: ["positive", "negative", "neutral"] as const, description: "분석할 감성 유형", default: "positive" }, period: { type: "string" as const, enum: ["day", "week", "month"] as const, description: "집계 단위 (일/주/월)", default: "week" } }, required: ["source", "keyword", "startDate", "endDate", "sentiment", "period"] as const } }, { name: "topAssocSentimentByPeriod", description: "기간별 상위 감성 연관어 순위를 비교하여 감성 변화 요인을 파악합니다.", inputSchema: { type: "object" as const, properties: { source: { type: "string" as const, description: DATA_SOURCE_DESCRIPTION }, keyword: { type: "string" as const, description: KEYWORD_DESCRIPTION }, startDate: { type: "string" as const, description: "시작 날짜 (YYYYMMDD 형식)" }, endDate: { type: "string" as const, description: "종료 날짜 (YYYYMMDD 형식)" }, sentiment: { type: "string" as const, enum: ["positive", "negative", "neutral"] as const, description: "분석할 감성 유형", default: "positive" }, period: { type: "string" as const, enum: ["day", "week", "month"] as const, description: "집계 단위 (일/주/월)", default: "week" }, topN: { type: "integer" as const, description: "상위 N개 연관어", default: 15, minimum: 1, maximum: 50 } }, required: ["source", "keyword", "startDate", "endDate", "sentiment", "period", "topN"] as const } } ]; // === SNS 채널 관리 도구 정의 === export const SNS_CHANNEL_TOOL_DEFINITIONS: ToolDefinition[] = [ { name: "searchSnsChannels", description: "데이터 타입과 특성에 따라 SNS 채널을 검색하고 필터링합니다.", inputSchema: { type: "object" as const, properties: { filterByDataType: { type: "array" as const, items: { type: "string" }, description: "데이터 타입으로 필터링 (예: [\"해시태그\", \"댓글\"])" }, filterByFeature: { type: "array" as const, items: { type: "string" }, description: "특성으로 필터링 (예: [\"실시간\", \"분석\"])" } }, required: [] as const } }, { name: "getChannelsByDataType", description: "특정 데이터 타입을 지원하는 SNS 채널들을 조회합니다.", inputSchema: { type: "object" as const, properties: { dataType: { type: "string" as const, description: "조회할 데이터 타입 (예: \"해시태그\", \"댓글\", \"이미지\")" } }, required: ["dataType"] as const } }, { name: "getChannelsByFeature", description: "특정 특성을 가진 SNS 채널들을 조회합니다.", inputSchema: { type: "object" as const, properties: { feature: { type: "string" as const, description: "조회할 특성 (예: \"실시간\", \"분석\", \"해시태그\")" } }, required: ["feature"] as const } }, { name: "getAllSnsDataTypes", description: "시스템에서 지원하는 모든 SNS 데이터 타입 목록을 조회합니다.", inputSchema: { type: "object" as const, properties: {}, required: [] as const } }, { name: "getAllSnsFeatures", description: "시스템에서 지원하는 모든 SNS 특성 목록을 조회합니다.", inputSchema: { type: "object" as const, properties: {}, required: [] as const } }, { name: "getRecommendedSnsChannels", description: "분석 타입에 따른 최적의 SNS 채널 조합을 추천합니다.", inputSchema: { type: "object" as const, properties: { analysisType: { type: "string" as const, enum: ["reputation", "brand", "crisis", "marketing", "trend", "product"] as const, description: "분석 타입" } }, required: ["analysisType"] as const } }, { name: "validateSnsChannelId", description: "SNS 채널 ID의 유효성을 실시간으로 검증합니다.", inputSchema: { type: "object" as const, properties: { channelId: { type: "string" as const, description: "검증할 채널 ID" } }, required: ["channelId"] as const } }, { name: "getSnsChannelHealthCheck", description: "SNS 채널 서비스의 전반적인 상태와 가용성을 모니터링합니다.", inputSchema: { type: "object" as const, properties: {}, required: [] as const } } ]; // === 도구 카테고리 정의 === export const TOOL_CATEGORIES: ToolCategory[] = [ { name: "system", description: "시스템 정보 및 기본 기능 도구", tools: SYSTEM_TOOL_DEFINITIONS }, { name: "sns", description: "SNS 채널 관리 도구", tools: SNS_CHANNEL_TOOL_DEFINITIONS }, { name: "category", description: "분류체계 관련 도구", tools: CATEGORY_TOOL_DEFINITIONS }, { name: "document", description: "문서 및 언급량 분석 도구", tools: DOCUMENT_ANALYSIS_TOOL_DEFINITIONS }, { name: "association", description: "연관어 분석 도구", tools: ASSOCIATION_ANALYSIS_TOOL_DEFINITIONS }, { name: "sentiment", description: "감성 분석 도구", tools: SENTIMENT_ANALYSIS_TOOL_DEFINITIONS } ]; // === 도구 상수 정의 === export const TOOL_CONSTANTS: ToolConstants = { MAX_RESULTS_LIMIT: 1000, DEFAULT_PAGE_SIZE: 100, SUPPORTED_DATE_FORMATS: ['YYYYMMDD', 'YYYYMMDD HH:mm:ss'] as const, SUPPORTED_CHANNELS: ['web', 'news', 'blog', 'sns', 'forum', 'cafe'] as const, ANALYSIS_PERIOD: ['day', 'week', 'month'] as const, SENTIMENT_LEVELS: ['positive', 'negative', 'neutral'] as const }; /** * 모든 도구 정의를 관리하는 클래스 */ export class ToolDefinitions { /** * 모든 도구 정의 목록을 반환 */ static getAllToolDefinitions(): ToolDefinition[] { return TOOL_CATEGORIES.flatMap(category => category.tools); } /** * 카테고리별 도구 정의를 반환 */ static getToolDefinitionsByCategory(): ToolCategory[] { return TOOL_CATEGORIES; } /** * 특정 카테고리의 도구 정의를 반환 */ static getToolDefinitionsByName(categoryName: string): ToolDefinition[] { const category = TOOL_CATEGORIES.find(cat => cat.name === categoryName); return category ? category.tools : []; } /** * 특정 도구 정의를 이름으로 조회 */ static getToolDefinition(toolName: string): ToolDefinition | undefined { const tools = this.getAllToolDefinitions(); return tools.find(tool => tool.name === toolName); } /** * 도구가 존재하는지 확인 */ static hasToolDefinition(toolName: string): boolean { return this.getToolDefinition(toolName) !== undefined; } /** * 도구 통계 정보를 반환 */ static getToolStatistics(): ToolStatistics { const allTools = this.getAllToolDefinitions(); const byCategory = TOOL_CATEGORIES.map(category => ({ name: category.name, count: category.tools.length })); const totalParameters = allTools.reduce((total, tool) => { return total + Object.keys(tool.inputSchema.properties).length; }, 0); const requiredParameters = allTools.reduce((total, tool) => { return total + tool.inputSchema.required.length; }, 0); return { total: allTools.length, byCategory, totalParameters, requiredParameters }; } /** * 도구 상수를 반환 */ static getToolConstants(): ToolConstants { return TOOL_CONSTANTS; } /** * 특정 키워드로 도구를 검색 */ static searchTools(keyword: string): ToolDefinition[] { const searchTerm = keyword.toLowerCase(); return this.getAllToolDefinitions().filter(tool => tool.name.toLowerCase().includes(searchTerm) || tool.description.toLowerCase().includes(searchTerm) ); } /** * 필수 매개변수가 있는 도구만 반환 */ static getToolsWithRequiredParams(): ToolDefinition[] { return this.getAllToolDefinitions().filter(tool => tool.inputSchema.required.length > 0 ); } /** * 매개변수가 없는 도구만 반환 (단순 조회 도구) */ static getSimpleTools(): ToolDefinition[] { return this.getAllToolDefinitions().filter(tool => tool.inputSchema.required.length === 0 ); } }