content-genie-mcp 2.9.0 → 2.9.2
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/Dockerfile +29 -0
- package/README.md +17 -1
- package/dist/index.js +215 -15
- package/package.json +5 -1
- package/railway.json +14 -0
package/Dockerfile
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
FROM node:20-alpine
|
|
2
|
+
|
|
3
|
+
WORKDIR /app
|
|
4
|
+
|
|
5
|
+
# package.json과 tsconfig.json 복사
|
|
6
|
+
COPY package*.json ./
|
|
7
|
+
COPY tsconfig.json ./
|
|
8
|
+
|
|
9
|
+
# 의존성 설치 (prepare 스크립트 무시)
|
|
10
|
+
RUN npm ci --ignore-scripts
|
|
11
|
+
|
|
12
|
+
# 소스 코드 복사
|
|
13
|
+
COPY src/ ./src/
|
|
14
|
+
|
|
15
|
+
# 빌드 실행
|
|
16
|
+
RUN npm run build
|
|
17
|
+
|
|
18
|
+
# 프로덕션 의존성만 남기기
|
|
19
|
+
RUN npm prune --production
|
|
20
|
+
|
|
21
|
+
# 환경 변수
|
|
22
|
+
ENV NODE_ENV=production
|
|
23
|
+
ENV MCP_HTTP_MODE=true
|
|
24
|
+
ENV PORT=3000
|
|
25
|
+
|
|
26
|
+
EXPOSE 3000
|
|
27
|
+
|
|
28
|
+
# 서버 실행
|
|
29
|
+
CMD ["node", "dist/index.js"]
|
package/README.md
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/content-genie-mcp)
|
|
6
6
|
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
[](https://github.com/MUSE-CODE-SPACE/content-genie-mcp/wiki)
|
|
7
8
|
|
|
8
9
|
Content Genie MCP는 블로거, 유튜버, 인스타그래머, 마케터를 위한 **17가지 강력한 도구**를 제공하는 MCP 서버입니다. 한국 시장에 특화된 트렌드 분석, 콘텐츠 아이디어 생성, SEO 최적화, 바이럴 예측, 인플루언서 협업 분석 기능을 제공합니다.
|
|
9
10
|
|
|
@@ -104,10 +105,25 @@ Content Genie MCP는 블로거, 유튜버, 인스타그래머, 마케터를 위
|
|
|
104
105
|
claude mcp add content-genie-mcp -- npx -y content-genie-mcp
|
|
105
106
|
```
|
|
106
107
|
|
|
107
|
-
### PlayMCP
|
|
108
|
+
### PlayMCP (카카오)
|
|
108
109
|
|
|
109
110
|
[PlayMCP](https://playmcp.kakao.com)에서 "Content Genie"를 검색하여 도구함에 추가하세요.
|
|
110
111
|
|
|
112
|
+
> **참고**: PlayMCP는 등록 승인 후 사용 가능합니다. 현재 등록 진행 중입니다.
|
|
113
|
+
|
|
114
|
+
## 문서
|
|
115
|
+
|
|
116
|
+
- **[Wiki 문서](https://github.com/MUSE-CODE-SPACE/content-genie-mcp/wiki)** - 상세 사용법 및 가이드
|
|
117
|
+
- [설치 가이드](https://github.com/MUSE-CODE-SPACE/content-genie-mcp/wiki/Installation)
|
|
118
|
+
- [빠른 시작](https://github.com/MUSE-CODE-SPACE/content-genie-mcp/wiki/Quick-Start)
|
|
119
|
+
- [17가지 도구 개요](https://github.com/MUSE-CODE-SPACE/content-genie-mcp/wiki/Tools-Overview)
|
|
120
|
+
- [API 레퍼런스](https://github.com/MUSE-CODE-SPACE/content-genie-mcp/wiki/API-Reference)
|
|
121
|
+
- **활용 가이드**
|
|
122
|
+
- [블로거 가이드](https://github.com/MUSE-CODE-SPACE/content-genie-mcp/wiki/Guide-Blogger)
|
|
123
|
+
- [유튜버 가이드](https://github.com/MUSE-CODE-SPACE/content-genie-mcp/wiki/Guide-YouTuber)
|
|
124
|
+
- [인스타그래머 가이드](https://github.com/MUSE-CODE-SPACE/content-genie-mcp/wiki/Guide-Instagram)
|
|
125
|
+
- [마케터 가이드](https://github.com/MUSE-CODE-SPACE/content-genie-mcp/wiki/Guide-Marketer)
|
|
126
|
+
|
|
111
127
|
## 도구 상세
|
|
112
128
|
|
|
113
129
|
### 1. get_korean_trends
|
package/dist/index.js
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
3
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
|
|
4
5
|
import { z } from "zod";
|
|
5
6
|
import axios from "axios";
|
|
6
7
|
import * as cheerio from "cheerio";
|
|
8
|
+
import express from "express";
|
|
9
|
+
import cors from "cors";
|
|
10
|
+
import crypto from "crypto";
|
|
7
11
|
// =============================================================================
|
|
8
12
|
// Content Genie MCP v2.5 - 한국 콘텐츠 크리에이터를 위한 AI 어시스턴트 (프로 버전)
|
|
9
13
|
// =============================================================================
|
|
10
14
|
const server = new McpServer({
|
|
11
15
|
name: "content-genie-mcp",
|
|
12
|
-
version: "2.
|
|
16
|
+
version: "2.9.2",
|
|
13
17
|
});
|
|
14
18
|
// =============================================================================
|
|
15
19
|
// 공통 스키마
|
|
@@ -352,13 +356,13 @@ server.tool("optimize_title_hashtags", "AI 기반으로 콘텐츠 제목을 최
|
|
|
352
356
|
// =============================================================================
|
|
353
357
|
// Tool 4: SEO 키워드 분석 (analyze_seo_keywords) - 고도화
|
|
354
358
|
// =============================================================================
|
|
355
|
-
server.tool("analyze_seo_keywords", "키워드의 SEO 잠재력을 심층 분석하고
|
|
359
|
+
server.tool("analyze_seo_keywords", "키워드의 SEO 잠재력을 심층 분석하고 다음/네이버/구글 최적화 전략을 제공합니다.", {
|
|
356
360
|
keyword: z.string().describe("분석할 메인 키워드"),
|
|
357
|
-
search_engine: z.enum(["naver", "google", "
|
|
361
|
+
search_engine: z.enum(["daum", "naver", "google", "all"]).optional().describe("검색엔진 (daum, naver, google, all)"),
|
|
358
362
|
include_questions: z.boolean().optional().describe("관련 질문 키워드 포함"),
|
|
359
363
|
include_longtail: z.boolean().optional().describe("롱테일 키워드 포함"),
|
|
360
364
|
competitor_analysis: z.boolean().optional().describe("경쟁 분석 포함"),
|
|
361
|
-
}, async ({ keyword, search_engine = "
|
|
365
|
+
}, async ({ keyword, search_engine = "all", include_questions = true, include_longtail = true, competitor_analysis = true }) => {
|
|
362
366
|
try {
|
|
363
367
|
const analysis = await analyzeAdvancedSEOKeywords(keyword, search_engine, include_questions, include_longtail, competitor_analysis);
|
|
364
368
|
return {
|
|
@@ -616,6 +620,31 @@ async function getGoogleAutocomplete(keyword) {
|
|
|
616
620
|
return [];
|
|
617
621
|
}
|
|
618
622
|
}
|
|
623
|
+
// 다음 자동완성 키워드
|
|
624
|
+
async function getDaumAutocomplete(keyword) {
|
|
625
|
+
try {
|
|
626
|
+
const response = await axios.get(`https://suggest.search.daum.net/sushi/ns`, {
|
|
627
|
+
params: {
|
|
628
|
+
w: 'tot',
|
|
629
|
+
mod: 'json',
|
|
630
|
+
code: 'utf_in_out',
|
|
631
|
+
q: keyword,
|
|
632
|
+
},
|
|
633
|
+
headers: {
|
|
634
|
+
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36',
|
|
635
|
+
},
|
|
636
|
+
timeout: 5000,
|
|
637
|
+
});
|
|
638
|
+
// 응답 형식: {"q":"keyword","items":["suggestion1", "suggestion2", ...]}
|
|
639
|
+
if (response.data && Array.isArray(response.data.items)) {
|
|
640
|
+
return response.data.items.slice(0, 10);
|
|
641
|
+
}
|
|
642
|
+
return [];
|
|
643
|
+
}
|
|
644
|
+
catch {
|
|
645
|
+
return [];
|
|
646
|
+
}
|
|
647
|
+
}
|
|
619
648
|
// 네이버 연관검색어 스크래핑
|
|
620
649
|
async function getNaverRelatedKeywords(keyword) {
|
|
621
650
|
try {
|
|
@@ -703,6 +732,34 @@ async function getGoogleSearchResultCount(keyword) {
|
|
|
703
732
|
return 100000;
|
|
704
733
|
}
|
|
705
734
|
}
|
|
735
|
+
// 다음 검색 결과 수 추정
|
|
736
|
+
async function getDaumSearchResultCount(keyword) {
|
|
737
|
+
try {
|
|
738
|
+
const response = await axios.get(`https://search.daum.net/search`, {
|
|
739
|
+
params: {
|
|
740
|
+
w: 'blog',
|
|
741
|
+
q: keyword,
|
|
742
|
+
},
|
|
743
|
+
headers: {
|
|
744
|
+
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36',
|
|
745
|
+
},
|
|
746
|
+
timeout: 5000,
|
|
747
|
+
});
|
|
748
|
+
const $ = cheerio.load(response.data);
|
|
749
|
+
// 검색 결과 수 추출 시도
|
|
750
|
+
const countText = $('.sub_expander .txt_info, .cont_result .txt_info, [class*="count"]').first().text();
|
|
751
|
+
const match = countText.match(/[\d,]+/);
|
|
752
|
+
if (match) {
|
|
753
|
+
return parseInt(match[0].replace(/,/g, ''), 10);
|
|
754
|
+
}
|
|
755
|
+
// 대략적 추정: 검색 결과 아이템 수 기반
|
|
756
|
+
const itemCount = $('.wrap_cont.blog, .cont_blog').length;
|
|
757
|
+
return itemCount > 0 ? itemCount * 10000 : 50000;
|
|
758
|
+
}
|
|
759
|
+
catch {
|
|
760
|
+
return 50000; // 기본값
|
|
761
|
+
}
|
|
762
|
+
}
|
|
706
763
|
// 검색량 레벨 추정 (자동완성 순위 기반)
|
|
707
764
|
function estimateSearchVolume(autocompleteRank, resultCount) {
|
|
708
765
|
// 자동완성 상위 + 결과 수 많음 = 검색량 높음
|
|
@@ -1982,20 +2039,26 @@ function calculateReadabilityScore(text) {
|
|
|
1982
2039
|
// 고급 SEO 키워드 분석 - 실시간 데이터 기반
|
|
1983
2040
|
async function analyzeAdvancedSEOKeywords(keyword, searchEngine, includeQuestions, includeLongtail, competitorAnalysis) {
|
|
1984
2041
|
// 병렬로 실시간 데이터 수집
|
|
1985
|
-
const
|
|
1986
|
-
|
|
1987
|
-
|
|
2042
|
+
const includeNaver = searchEngine === 'naver' || searchEngine === 'all';
|
|
2043
|
+
const includeGoogle = searchEngine === 'google' || searchEngine === 'all';
|
|
2044
|
+
const includeDaum = searchEngine === 'daum' || searchEngine === 'all';
|
|
2045
|
+
const [naverAutocomplete, googleAutocomplete, daumAutocomplete, naverRelated, naverResultCount, googleResultCount, daumResultCount] = await Promise.all([
|
|
2046
|
+
includeNaver ? getNaverAutocomplete(keyword) : Promise.resolve([]),
|
|
2047
|
+
includeGoogle ? getGoogleAutocomplete(keyword) : Promise.resolve([]),
|
|
2048
|
+
includeDaum ? getDaumAutocomplete(keyword) : Promise.resolve([]),
|
|
1988
2049
|
getNaverRelatedKeywords(keyword),
|
|
1989
|
-
|
|
1990
|
-
|
|
2050
|
+
includeNaver ? getNaverSearchResultCount(keyword) : Promise.resolve(0),
|
|
2051
|
+
includeGoogle ? getGoogleSearchResultCount(keyword) : Promise.resolve(0),
|
|
2052
|
+
includeDaum ? getDaumSearchResultCount(keyword) : Promise.resolve(0),
|
|
1991
2053
|
]);
|
|
1992
2054
|
// 주요 검색 엔진 결과 수 선택
|
|
1993
2055
|
const primaryResultCount = searchEngine === 'naver' ? naverResultCount :
|
|
1994
2056
|
searchEngine === 'google' ? googleResultCount :
|
|
1995
|
-
|
|
2057
|
+
searchEngine === 'daum' ? daumResultCount :
|
|
2058
|
+
Math.max(naverResultCount, googleResultCount, daumResultCount);
|
|
1996
2059
|
// 경쟁도 및 검색량 추정
|
|
1997
2060
|
const competition = estimateCompetition(primaryResultCount);
|
|
1998
|
-
const autocompleteKeywords = [...new Set([...naverAutocomplete, ...googleAutocomplete])];
|
|
2061
|
+
const autocompleteKeywords = [...new Set([...daumAutocomplete, ...naverAutocomplete, ...googleAutocomplete])];
|
|
1999
2062
|
const keywordRank = autocompleteKeywords.findIndex(k => k.includes(keyword)) + 1 || 10;
|
|
2000
2063
|
const searchVolume = estimateSearchVolume(keywordRank, primaryResultCount);
|
|
2001
2064
|
// SEO 난이도 계산
|
|
@@ -2138,6 +2201,18 @@ async function analyzeAdvancedSEOKeywords(keyword, searchEngine, includeQuestion
|
|
|
2138
2201
|
],
|
|
2139
2202
|
content_types: ["웹사이트", "유튜브", "뉴스"],
|
|
2140
2203
|
},
|
|
2204
|
+
daum: {
|
|
2205
|
+
result_count: daumResultCount.toLocaleString(),
|
|
2206
|
+
competition: estimateCompetition(daumResultCount).level,
|
|
2207
|
+
tips: [
|
|
2208
|
+
"다음 블로그/카페에 발행하세요",
|
|
2209
|
+
"카카오 채널과 연동 고려",
|
|
2210
|
+
"티스토리 블로그 활용 추천",
|
|
2211
|
+
"다음 뉴스 검색 노출 전략",
|
|
2212
|
+
"카카오톡 공유 최적화",
|
|
2213
|
+
],
|
|
2214
|
+
content_types: ["티스토리", "다음카페", "브런치"],
|
|
2215
|
+
},
|
|
2141
2216
|
};
|
|
2142
2217
|
// 추천 액션 생성
|
|
2143
2218
|
const recommendedAction = seoDifficulty > 70
|
|
@@ -2148,9 +2223,11 @@ async function analyzeAdvancedSEOKeywords(keyword, searchEngine, includeQuestion
|
|
|
2148
2223
|
return {
|
|
2149
2224
|
main_keyword: keyword,
|
|
2150
2225
|
data_source: {
|
|
2226
|
+
daum_autocomplete: daumAutocomplete.length,
|
|
2151
2227
|
naver_autocomplete: naverAutocomplete.length,
|
|
2152
2228
|
google_autocomplete: googleAutocomplete.length,
|
|
2153
2229
|
naver_related: naverRelated.length,
|
|
2230
|
+
daum_results: daumResultCount.toLocaleString(),
|
|
2154
2231
|
naver_results: naverResultCount.toLocaleString(),
|
|
2155
2232
|
google_results: googleResultCount.toLocaleString(),
|
|
2156
2233
|
},
|
|
@@ -2167,7 +2244,7 @@ async function analyzeAdvancedSEOKeywords(keyword, searchEngine, includeQuestion
|
|
|
2167
2244
|
related_keywords: relatedKeywords.slice(0, 15),
|
|
2168
2245
|
question_keywords: questionKeywords.slice(0, 8),
|
|
2169
2246
|
longtail_keywords: longtailKeywords.slice(0, 8),
|
|
2170
|
-
search_engine_strategy: searchEngine === "
|
|
2247
|
+
search_engine_strategy: searchEngine === "all" ? searchEngineStrategy : searchEngineStrategy[searchEngine],
|
|
2171
2248
|
content_recommendations: {
|
|
2172
2249
|
ideal_length: seoDifficulty > 60 ? "4000-6000자 (경쟁 대응)" : "2500-4000자",
|
|
2173
2250
|
must_include: ["정의", "방법", "예시", "FAQ", "비교"],
|
|
@@ -3903,8 +3980,131 @@ function predictContentPerformance(title, description, platform, category, posti
|
|
|
3903
3980
|
// Server Start
|
|
3904
3981
|
// =============================================================================
|
|
3905
3982
|
async function main() {
|
|
3906
|
-
const
|
|
3907
|
-
|
|
3908
|
-
|
|
3983
|
+
const isHttpMode = process.env.MCP_HTTP_MODE === 'true' || process.argv.includes('--http');
|
|
3984
|
+
const port = parseInt(process.env.PORT || '3000', 10);
|
|
3985
|
+
if (isHttpMode) {
|
|
3986
|
+
// HTTP/SSE 모드 (PlayMCP, 웹 클라이언트용)
|
|
3987
|
+
console.log(`Starting Content Genie MCP Server v2.9.0 in HTTP mode on port ${port}...`);
|
|
3988
|
+
const app = express();
|
|
3989
|
+
app.use(cors());
|
|
3990
|
+
app.use(express.json());
|
|
3991
|
+
// 도구 목록 (PlayMCP 연결 확인용)
|
|
3992
|
+
const toolsList = [
|
|
3993
|
+
{ name: "get_korean_trends", description: "다음/네이버 실시간 트렌드 조회" },
|
|
3994
|
+
{ name: "analyze_news_trends", description: "뉴스 트렌드 분석" },
|
|
3995
|
+
{ name: "get_seasonal_content_guide", description: "시즌 콘텐츠 가이드" },
|
|
3996
|
+
{ name: "analyze_seo_keywords", description: "SEO 키워드 심층 분석" },
|
|
3997
|
+
{ name: "generate_hashtag_strategy", description: "해시태그 전략 생성" },
|
|
3998
|
+
{ name: "analyze_competitor_content", description: "경쟁사 콘텐츠 분석" },
|
|
3999
|
+
{ name: "generate_content_ideas", description: "콘텐츠 아이디어 생성" },
|
|
4000
|
+
{ name: "optimize_title_hashtags", description: "제목/해시태그 최적화" },
|
|
4001
|
+
{ name: "create_content_calendar", description: "콘텐츠 캘린더 생성" },
|
|
4002
|
+
{ name: "generate_script_outline", description: "스크립트 아웃라인 생성" },
|
|
4003
|
+
{ name: "repurpose_content", description: "콘텐츠 리퍼포징" },
|
|
4004
|
+
{ name: "predict_viral_score", description: "바이럴 점수 예측" },
|
|
4005
|
+
{ name: "benchmark_content_performance", description: "성과 벤치마크" },
|
|
4006
|
+
{ name: "predict_content_performance", description: "콘텐츠 성과 예측" },
|
|
4007
|
+
{ name: "analyze_thumbnail", description: "썸네일 분석" },
|
|
4008
|
+
{ name: "generate_ab_test_variants", description: "A/B 테스트 변형 생성" },
|
|
4009
|
+
{ name: "analyze_influencer_collab", description: "인플루언서 협업 분석" },
|
|
4010
|
+
];
|
|
4011
|
+
// Health check
|
|
4012
|
+
app.get('/', (_req, res) => {
|
|
4013
|
+
res.json({
|
|
4014
|
+
status: 'ok',
|
|
4015
|
+
server: 'content-genie-mcp',
|
|
4016
|
+
version: '2.9.2',
|
|
4017
|
+
tools: 17,
|
|
4018
|
+
timestamp: new Date().toISOString()
|
|
4019
|
+
});
|
|
4020
|
+
});
|
|
4021
|
+
app.get('/health', (_req, res) => {
|
|
4022
|
+
res.json({
|
|
4023
|
+
status: 'ok',
|
|
4024
|
+
server: 'content-genie-mcp',
|
|
4025
|
+
version: '2.9.2',
|
|
4026
|
+
tools: 17,
|
|
4027
|
+
timestamp: new Date().toISOString()
|
|
4028
|
+
});
|
|
4029
|
+
});
|
|
4030
|
+
// MCP 엔드포인트 - PlayMCP 연결 확인용 (간단한 응답)
|
|
4031
|
+
app.post('/mcp', (req, res) => {
|
|
4032
|
+
const { method, id } = req.body;
|
|
4033
|
+
// initialize 요청에 대한 응답
|
|
4034
|
+
if (method === 'initialize') {
|
|
4035
|
+
res.json({
|
|
4036
|
+
jsonrpc: '2.0',
|
|
4037
|
+
id,
|
|
4038
|
+
result: {
|
|
4039
|
+
protocolVersion: '2024-11-05',
|
|
4040
|
+
capabilities: { tools: { listChanged: true } },
|
|
4041
|
+
serverInfo: { name: 'content-genie-mcp', version: '2.9.2' }
|
|
4042
|
+
}
|
|
4043
|
+
});
|
|
4044
|
+
return;
|
|
4045
|
+
}
|
|
4046
|
+
// tools/list 요청에 대한 응답
|
|
4047
|
+
if (method === 'tools/list') {
|
|
4048
|
+
res.json({
|
|
4049
|
+
jsonrpc: '2.0',
|
|
4050
|
+
id,
|
|
4051
|
+
result: { tools: toolsList }
|
|
4052
|
+
});
|
|
4053
|
+
return;
|
|
4054
|
+
}
|
|
4055
|
+
// 기타 요청
|
|
4056
|
+
res.json({
|
|
4057
|
+
jsonrpc: '2.0',
|
|
4058
|
+
id,
|
|
4059
|
+
error: { code: -32601, message: 'Method not found' }
|
|
4060
|
+
});
|
|
4061
|
+
});
|
|
4062
|
+
// SSE endpoint for MCP connection (MCP Inspector용)
|
|
4063
|
+
const transports = new Map();
|
|
4064
|
+
app.get('/sse', async (_req, res) => {
|
|
4065
|
+
console.log('New SSE connection established');
|
|
4066
|
+
const transport = new SSEServerTransport('/message', res);
|
|
4067
|
+
const sessionId = crypto.randomUUID();
|
|
4068
|
+
transports.set(sessionId, transport);
|
|
4069
|
+
res.on('close', () => {
|
|
4070
|
+
console.log('SSE connection closed');
|
|
4071
|
+
transports.delete(sessionId);
|
|
4072
|
+
});
|
|
4073
|
+
await server.connect(transport);
|
|
4074
|
+
});
|
|
4075
|
+
// Message endpoint for MCP communication
|
|
4076
|
+
app.post('/message', async (req, res) => {
|
|
4077
|
+
const sessionId = req.query.sessionId;
|
|
4078
|
+
if (!sessionId) {
|
|
4079
|
+
const transport = Array.from(transports.values())[0];
|
|
4080
|
+
if (transport) {
|
|
4081
|
+
await transport.handlePostMessage(req, res);
|
|
4082
|
+
}
|
|
4083
|
+
else {
|
|
4084
|
+
res.status(400).json({ error: 'No active session' });
|
|
4085
|
+
}
|
|
4086
|
+
return;
|
|
4087
|
+
}
|
|
4088
|
+
const transport = transports.get(sessionId);
|
|
4089
|
+
if (transport) {
|
|
4090
|
+
await transport.handlePostMessage(req, res);
|
|
4091
|
+
}
|
|
4092
|
+
else {
|
|
4093
|
+
res.status(404).json({ error: 'Session not found' });
|
|
4094
|
+
}
|
|
4095
|
+
});
|
|
4096
|
+
app.listen(port, () => {
|
|
4097
|
+
console.log(`Content Genie MCP Server v2.9.0 running on HTTP port ${port}`);
|
|
4098
|
+
console.log(`Health check: http://localhost:${port}/health`);
|
|
4099
|
+
console.log(`MCP endpoint: http://localhost:${port}/mcp`);
|
|
4100
|
+
console.log(`SSE endpoint: http://localhost:${port}/sse`);
|
|
4101
|
+
});
|
|
4102
|
+
}
|
|
4103
|
+
else {
|
|
4104
|
+
// stdio 모드 (Claude Desktop, Claude Code용)
|
|
4105
|
+
const transport = new StdioServerTransport();
|
|
4106
|
+
await server.connect(transport);
|
|
4107
|
+
console.error("Content Genie MCP Server v2.9.0 running on stdio");
|
|
4108
|
+
}
|
|
3909
4109
|
}
|
|
3910
4110
|
main().catch(console.error);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "content-genie-mcp",
|
|
3
|
-
"version": "2.9.
|
|
3
|
+
"version": "2.9.2",
|
|
4
4
|
"description": "AI Content Creation Assistant MCP - 한국 콘텐츠 크리에이터를 위한 트렌드 분석 및 콘텐츠 생성 도우미",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": "dist/index.js",
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"scripts": {
|
|
13
13
|
"build": "tsc",
|
|
14
14
|
"start": "node dist/index.js",
|
|
15
|
+
"start:http": "MCP_HTTP_MODE=true node dist/index.js",
|
|
15
16
|
"dev": "ts-node src/index.ts",
|
|
16
17
|
"prepare": "npm run build"
|
|
17
18
|
},
|
|
@@ -35,9 +36,12 @@
|
|
|
35
36
|
"@modelcontextprotocol/sdk": "^1.25.1",
|
|
36
37
|
"axios": "^1.13.2",
|
|
37
38
|
"cheerio": "^1.1.2",
|
|
39
|
+
"cors": "^2.8.5",
|
|
38
40
|
"zod": "^4.2.1"
|
|
39
41
|
},
|
|
40
42
|
"devDependencies": {
|
|
43
|
+
"@types/cors": "^2.8.19",
|
|
44
|
+
"@types/express": "^5.0.6",
|
|
41
45
|
"@types/node": "^25.0.3",
|
|
42
46
|
"ts-node": "^10.9.2",
|
|
43
47
|
"typescript": "^5.9.3"
|
package/railway.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://railway.app/railway.schema.json",
|
|
3
|
+
"build": {
|
|
4
|
+
"builder": "DOCKERFILE",
|
|
5
|
+
"dockerfilePath": "Dockerfile"
|
|
6
|
+
},
|
|
7
|
+
"deploy": {
|
|
8
|
+
"startCommand": "node dist/index.js",
|
|
9
|
+
"healthcheckPath": "/health",
|
|
10
|
+
"healthcheckTimeout": 30,
|
|
11
|
+
"restartPolicyType": "ON_FAILURE",
|
|
12
|
+
"restartPolicyMaxRetries": 3
|
|
13
|
+
}
|
|
14
|
+
}
|