sometrend-mcp-server
Version:
TM2 기반의 썸트렌드(sometrend) MCP 서버 - 트렌드 분석 및 데이터 처리
779 lines (756 loc) • 29.3 kB
text/typescript
/**
* 썸트렌드(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
);
}
}