content-genie-mcp 1.0.0
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/README.md +185 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +588 -0
- package/package.json +42 -0
package/README.md
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# ๐ง Content Genie MCP
|
|
2
|
+
|
|
3
|
+
> ํ๊ตญ ์ฝํ
์ธ ํฌ๋ฆฌ์์ดํฐ๋ฅผ ์ํ AI ์ด์์คํดํธ MCP ์๋ฒ
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/content-genie-mcp)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
|
|
8
|
+
Content Genie MCP๋ ๋ธ๋ก๊ฑฐ, ์ ํ๋ฒ, ์ธ์คํ๊ทธ๋๋จธ, ๋ง์ผํฐ๋ฅผ ์ํ ์ฌ์ธ์ ์ฝํ
์ธ ์์ฑ ๋์ฐ๋ฏธ์
๋๋ค. ํ๊ตญ ์์ฅ์ ํนํ๋ ํธ๋ ๋ ๋ถ์, ์ฝํ
์ธ ์์ด๋์ด ์์ฑ, SEO ์ต์ ํ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค.
|
|
9
|
+
|
|
10
|
+
## โจ ์ฃผ์ ๊ธฐ๋ฅ
|
|
11
|
+
|
|
12
|
+
### ๐ฅ 7๊ฐ์ง ํต์ฌ ๋๊ตฌ
|
|
13
|
+
|
|
14
|
+
| ๋๊ตฌ | ์ค๋ช
|
|
|
15
|
+
|------|------|
|
|
16
|
+
| `get_korean_trends` | ๋ค์ด๋ฒ, ๊ตฌ๊ธ, ์ ํ๋ธ ์ค์๊ฐ ํธ๋ ๋ ๋ถ์ |
|
|
17
|
+
| `generate_content_ideas` | ์ฃผ์ ๊ธฐ๋ฐ ์ฝํ
์ธ ์์ด๋์ด ์๋ ์์ฑ |
|
|
18
|
+
| `optimize_title_hashtags` | CTR ์ต์ ํ ์ ๋ชฉ ๋ฐ ํด์ํ๊ทธ ์์ฑ |
|
|
19
|
+
| `analyze_seo_keywords` | SEO ํค์๋ ๋ถ์ ๋ฐ ๋กฑํ
์ผ ํค์๋ ์ถ์ฒ |
|
|
20
|
+
| `create_content_calendar` | ํ๊ตญ ๊ณตํด์ผ ๋ฐ์ ์ฝํ
์ธ ์บ๋ฆฐ๋ ์์ฑ |
|
|
21
|
+
| `analyze_competitor_content` | ๊ฒฝ์์ฌ ์ฝํ
์ธ ์ ๋ต ๋ถ์ |
|
|
22
|
+
| `predict_viral_score` | ๋ฐ์ด๋ด ๊ฐ๋ฅ์ฑ ์์ธก ๋ฐ ๊ฐ์ ์ ์ |
|
|
23
|
+
|
|
24
|
+
## ๐ ์ค์น ๋ฐ ์ฌ์ฉ๋ฒ
|
|
25
|
+
|
|
26
|
+
### Claude Desktop์์ ์ฌ์ฉ
|
|
27
|
+
|
|
28
|
+
`claude_desktop_config.json`์ ์ถ๊ฐ:
|
|
29
|
+
|
|
30
|
+
```json
|
|
31
|
+
{
|
|
32
|
+
"mcpServers": {
|
|
33
|
+
"content-genie": {
|
|
34
|
+
"command": "npx",
|
|
35
|
+
"args": ["-y", "content-genie-mcp"]
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Claude Code์์ ์ฌ์ฉ
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
claude mcp add content-genie-mcp -- npx -y content-genie-mcp
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### PlayMCP์์ ์ฌ์ฉ
|
|
48
|
+
|
|
49
|
+
[PlayMCP](https://playmcp.kakao.com)์์ "Content Genie"๋ฅผ ๊ฒ์ํ์ฌ ๋๊ตฌํจ์ ์ถ๊ฐํ์ธ์.
|
|
50
|
+
|
|
51
|
+
## ๐ ๋๊ตฌ ์์ธ ์ค๋ช
|
|
52
|
+
|
|
53
|
+
### 1. get_korean_trends - ํ๊ตญ ํธ๋ ๋ ๋ถ์
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
์ค์๊ฐ ํ๊ตญ ํธ๋ ๋ ํค์๋๋ฅผ ๋ถ์ํฉ๋๋ค.
|
|
57
|
+
|
|
58
|
+
๋งค๊ฐ๋ณ์:
|
|
59
|
+
- platform: "naver" | "google" | "youtube" | "all" (๊ธฐ๋ณธ๊ฐ: all)
|
|
60
|
+
- category: "general" | "news" | "shopping" | "entertainment" | "all"
|
|
61
|
+
- limit: 1-50 (๊ธฐ๋ณธ๊ฐ: 20)
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### 2. generate_content_ideas - ์ฝํ
์ธ ์์ด๋์ด ์์ฑ
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
์ฃผ์ ์ ํ๋ซํผ์ ๋ง๋ ์ฝํ
์ธ ์์ด๋์ด๋ฅผ ์์ฑํฉ๋๋ค.
|
|
68
|
+
|
|
69
|
+
๋งค๊ฐ๋ณ์:
|
|
70
|
+
- topic: ์ฝํ
์ธ ์ฃผ์ (ํ์)
|
|
71
|
+
- content_type: "blog" | "youtube" | "instagram" | "tiktok" | "newsletter" | "all"
|
|
72
|
+
- tone: "professional" | "casual" | "humorous" | "educational" | "inspirational"
|
|
73
|
+
- target_audience: ํ๊ฒ ์ค๋์ธ์ค ์ค๋ช
|
|
74
|
+
- count: 1-20 (๊ธฐ๋ณธ๊ฐ: 10)
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### 3. optimize_title_hashtags - ์ ๋ชฉ/ํด์ํ๊ทธ ์ต์ ํ
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
CTR ํฅ์์ ์ํ ์ ๋ชฉ ์ต์ ํ ๋ฐ ํด์ํ๊ทธ ์์ฑ
|
|
81
|
+
|
|
82
|
+
๋งค๊ฐ๋ณ์:
|
|
83
|
+
- original_title: ์๋ณธ ์ ๋ชฉ (ํ์)
|
|
84
|
+
- platform: ํ๊ฒ ํ๋ซํผ
|
|
85
|
+
- keywords: ํฌํจํ ํค์๋ ๋ฐฐ์ด
|
|
86
|
+
- style: "clickbait" | "informative" | "emotional" | "question" | "how-to" | "listicle"
|
|
87
|
+
- max_length: ์ต๋ ๊ธ์ ์ (๊ธฐ๋ณธ๊ฐ: 60)
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### 4. analyze_seo_keywords - SEO ํค์๋ ๋ถ์
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
ํค์๋์ SEO ์ ์ฌ๋ ฅ ๋ถ์ ๋ฐ ์ถ์ฒ
|
|
94
|
+
|
|
95
|
+
๋งค๊ฐ๋ณ์:
|
|
96
|
+
- keyword: ๋ถ์ํ ํค์๋ (ํ์)
|
|
97
|
+
- language: "ko" | "en" | "both"
|
|
98
|
+
- include_questions: ์ง๋ฌธํ ํค์๋ ํฌํจ (๊ธฐ๋ณธ๊ฐ: true)
|
|
99
|
+
- include_longtail: ๋กฑํ
์ผ ํค์๋ ํฌํจ (๊ธฐ๋ณธ๊ฐ: true)
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### 5. create_content_calendar - ์ฝํ
์ธ ์บ๋ฆฐ๋ ์์ฑ
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
ํ๊ตญ ๊ธฐ๋
์ผ ๋ฐ์ ์ฝํ
์ธ ์บ๋ฆฐ๋ ์๋ ์์ฑ
|
|
106
|
+
|
|
107
|
+
๋งค๊ฐ๋ณ์:
|
|
108
|
+
- topics: ์ฃผ์ ๋ฐฐ์ด (ํ์)
|
|
109
|
+
- duration_weeks: 1-12์ฃผ (๊ธฐ๋ณธ๊ฐ: 4)
|
|
110
|
+
- posts_per_week: 1-14๊ฐ (๊ธฐ๋ณธ๊ฐ: 3)
|
|
111
|
+
- platforms: ํ๋ซํผ ๋ฐฐ์ด
|
|
112
|
+
- include_holidays: ๊ณตํด์ผ/๊ธฐ๋
์ผ ํฌํจ (๊ธฐ๋ณธ๊ฐ: true)
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### 6. analyze_competitor_content - ๊ฒฝ์์ฌ ๋ถ์
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
๊ฒฝ์์ฌ ์ฝํ
์ธ ์ ๋ต ๋ถ์
|
|
119
|
+
|
|
120
|
+
๋งค๊ฐ๋ณ์:
|
|
121
|
+
- urls: ๋ถ์ํ URL ๋ฐฐ์ด (์ต๋ 5๊ฐ)
|
|
122
|
+
- analysis_type: "title" | "structure" | "keywords" | "all"
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### 7. predict_viral_score - ๋ฐ์ด๋ด ์์ธก
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
์ฝํ
์ธ ๋ฐ์ด๋ด ๊ฐ๋ฅ์ฑ ์ ์ ์์ธก
|
|
129
|
+
|
|
130
|
+
๋งค๊ฐ๋ณ์:
|
|
131
|
+
- title: ์ฝํ
์ธ ์ ๋ชฉ (ํ์)
|
|
132
|
+
- description: ์ค๋ช
|
|
133
|
+
- platform: ํ๊ฒ ํ๋ซํผ
|
|
134
|
+
- hashtags: ํด์ํ๊ทธ ๋ฐฐ์ด
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## ๐ก ์ฌ์ฉ ์์
|
|
138
|
+
|
|
139
|
+
### ํธ๋ ๋ ๊ธฐ๋ฐ ์ฝํ
์ธ ๊ธฐํ
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
1. get_korean_trends๋ก ์ต์ ํธ๋ ๋ ํ์
|
|
143
|
+
2. generate_content_ideas๋ก ์์ด๋์ด ์์ฑ
|
|
144
|
+
3. optimize_title_hashtags๋ก ์ ๋ชฉ ์ต์ ํ
|
|
145
|
+
4. predict_viral_score๋ก ๋ฐ์ด๋ด ๊ฐ๋ฅ์ฑ ํ์ธ
|
|
146
|
+
5. create_content_calendar๋ก ์ผ์ ์๋ฆฝ
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### SEO ์ต์ ํ ์ฝํ
์ธ ์์ฑ
|
|
150
|
+
|
|
151
|
+
```
|
|
152
|
+
1. analyze_seo_keywords๋ก ํค์๋ ๋ถ์
|
|
153
|
+
2. analyze_competitor_content๋ก ๊ฒฝ์์ฌ ๋ฒค์น๋งํน
|
|
154
|
+
3. generate_content_ideas๋ก ์ฐจ๋ณํ๋ ์์ด๋์ด ๋์ถ
|
|
155
|
+
4. optimize_title_hashtags๋ก ๊ฒ์ ์ต์ ํ
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## ๐ฏ ํ๊ฒ ์ฌ์ฉ์
|
|
159
|
+
|
|
160
|
+
- **๋ธ๋ก๊ฑฐ**: ๋ค์ด๋ฒ ๋ธ๋ก๊ทธ, ํฐ์คํ ๋ฆฌ ์ด์์
|
|
161
|
+
- **์ ํ๋ฒ**: ์ฝํ
์ธ ๊ธฐํ ๋ฐ ์ ๋ชฉ ์ต์ ํ
|
|
162
|
+
- **์ธ์คํ๊ทธ๋๋จธ**: ํด์ํ๊ทธ ์ ๋ต ๋ฐ ํฌ์คํ
์ผ์
|
|
163
|
+
- **๋ง์ผํฐ**: ์ฝํ
์ธ ๋ง์ผํ
์ ๋ต ์๋ฆฝ
|
|
164
|
+
- **์คํํธ์
**: ๋ธ๋๋ ์ฝํ
์ธ ๊ธฐํ
|
|
165
|
+
|
|
166
|
+
## ๐ง ๊ธฐ์ ์คํ
|
|
167
|
+
|
|
168
|
+
- TypeScript
|
|
169
|
+
- MCP SDK (@modelcontextprotocol/sdk)
|
|
170
|
+
- Axios & Cheerio (์น ์คํฌ๋ํ)
|
|
171
|
+
- Zod (์คํค๋ง ๊ฒ์ฆ)
|
|
172
|
+
|
|
173
|
+
## ๐ ๋ผ์ด์ ์ค
|
|
174
|
+
|
|
175
|
+
MIT License
|
|
176
|
+
|
|
177
|
+
## ๐จโ๐ป ๊ฐ๋ฐ์
|
|
178
|
+
|
|
179
|
+
**Yoonkyoung Gong** - [GitHub](https://github.com/MUSE-CODE-SPACE)
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
๐ **PlayMCP Player 10 ๊ณต๋ชจ์ ์ถํ์**
|
|
184
|
+
|
|
185
|
+
์ด ํ๋ก์ ํธ๋ ์นด์นด์ค PlayMCP ๊ฐ๋ฐ ๊ณต๋ชจ์ ์ ์ํด ์ ์๋์์ต๋๋ค.
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,588 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import axios from "axios";
|
|
6
|
+
import * as cheerio from "cheerio";
|
|
7
|
+
// =============================================================================
|
|
8
|
+
// Content Genie MCP - ํ๊ตญ ์ฝํ
์ธ ํฌ๋ฆฌ์์ดํฐ๋ฅผ ์ํ AI ์ด์์คํดํธ
|
|
9
|
+
// =============================================================================
|
|
10
|
+
const server = new McpServer({
|
|
11
|
+
name: "content-genie-mcp",
|
|
12
|
+
version: "1.0.0",
|
|
13
|
+
});
|
|
14
|
+
// =============================================================================
|
|
15
|
+
// Tool 1: ํ๊ตญ ํธ๋ ๋ ๋ถ์ (get_korean_trends)
|
|
16
|
+
// =============================================================================
|
|
17
|
+
const TrendPlatformSchema = z.enum(["naver", "google", "youtube", "all"]);
|
|
18
|
+
const TrendCategorySchema = z.enum(["general", "news", "shopping", "entertainment", "all"]);
|
|
19
|
+
server.tool("get_korean_trends", "์ค์๊ฐ ํ๊ตญ ํธ๋ ๋ ํค์๋๋ฅผ ๋ถ์ํฉ๋๋ค. ๋ค์ด๋ฒ, ๊ตฌ๊ธ, ์ ํ๋ธ์์ ์ธ๊ธฐ ๊ฒ์์ด์ ํธ๋ ๋๋ฅผ ์์งํฉ๋๋ค.", {
|
|
20
|
+
platform: TrendPlatformSchema.optional().describe("๋ถ์ํ ํ๋ซํผ (naver, google, youtube, all). ๊ธฐ๋ณธ๊ฐ: all"),
|
|
21
|
+
category: TrendCategorySchema.optional().describe("์นดํ
๊ณ ๋ฆฌ (general, news, shopping, entertainment, all). ๊ธฐ๋ณธ๊ฐ: all"),
|
|
22
|
+
limit: z.number().min(1).max(50).optional().describe("๊ฐ์ ธ์ฌ ํธ๋ ๋ ์. ๊ธฐ๋ณธ๊ฐ: 20"),
|
|
23
|
+
}, async ({ platform = "all", category = "all", limit = 20 }) => {
|
|
24
|
+
const trends = [];
|
|
25
|
+
try {
|
|
26
|
+
// ๋ค์ด๋ฒ ์ค์๊ฐ ๊ฒ์์ด (DataLab API ์๋ฎฌ๋ ์ด์
)
|
|
27
|
+
if (platform === "naver" || platform === "all") {
|
|
28
|
+
const naverTrends = await getNaverTrends(limit);
|
|
29
|
+
trends.push(...naverTrends);
|
|
30
|
+
}
|
|
31
|
+
// ๊ตฌ๊ธ ํธ๋ ๋
|
|
32
|
+
if (platform === "google" || platform === "all") {
|
|
33
|
+
const googleTrends = await getGoogleTrendsKorea(limit);
|
|
34
|
+
trends.push(...googleTrends);
|
|
35
|
+
}
|
|
36
|
+
// ์ ํ๋ธ ์ธ๊ธฐ
|
|
37
|
+
if (platform === "youtube" || platform === "all") {
|
|
38
|
+
const youtubeTrends = await getYoutubeTrendsKorea(limit);
|
|
39
|
+
trends.push(...youtubeTrends);
|
|
40
|
+
}
|
|
41
|
+
const result = {
|
|
42
|
+
timestamp: new Date().toISOString(),
|
|
43
|
+
platform,
|
|
44
|
+
category,
|
|
45
|
+
total: trends.length,
|
|
46
|
+
trends: trends.slice(0, limit),
|
|
47
|
+
insights: generateTrendInsights(trends),
|
|
48
|
+
};
|
|
49
|
+
return {
|
|
50
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
return {
|
|
55
|
+
content: [{ type: "text", text: `ํธ๋ ๋ ๋ถ์ ์ค ์ค๋ฅ ๋ฐ์: ${error}` }],
|
|
56
|
+
isError: true,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
// =============================================================================
|
|
61
|
+
// Tool 2: ์ฝํ
์ธ ์์ด๋์ด ์์ฑ (generate_content_ideas)
|
|
62
|
+
// =============================================================================
|
|
63
|
+
const ContentTypeSchema = z.enum(["blog", "youtube", "instagram", "tiktok", "newsletter", "all"]);
|
|
64
|
+
const ToneSchema = z.enum(["professional", "casual", "humorous", "educational", "inspirational"]);
|
|
65
|
+
server.tool("generate_content_ideas", "์ฃผ์ ์ ํ๋ซํผ์ ๋ง๋ ์ฝํ
์ธ ์์ด๋์ด๋ฅผ ์์ฑํฉ๋๋ค. ํธ๋ ๋ ๊ธฐ๋ฐ ์ถ์ฒ๊ณผ ํจ๊ป ์ ๊ณต๋ฉ๋๋ค.", {
|
|
66
|
+
topic: z.string().describe("์ฝํ
์ธ ์ฃผ์ ๋๋ ํค์๋"),
|
|
67
|
+
content_type: ContentTypeSchema.optional().describe("์ฝํ
์ธ ์ ํ (blog, youtube, instagram, tiktok, newsletter, all)"),
|
|
68
|
+
tone: ToneSchema.optional().describe("ํค์ค๋งค๋ (professional, casual, humorous, educational, inspirational)"),
|
|
69
|
+
target_audience: z.string().optional().describe("ํ๊ฒ ์ค๋์ธ์ค ์ค๋ช
"),
|
|
70
|
+
count: z.number().min(1).max(20).optional().describe("์์ฑํ ์์ด๋์ด ์. ๊ธฐ๋ณธ๊ฐ: 10"),
|
|
71
|
+
}, async ({ topic, content_type = "all", tone = "professional", target_audience, count = 10 }) => {
|
|
72
|
+
try {
|
|
73
|
+
const ideas = generateContentIdeas(topic, content_type, tone, target_audience, count);
|
|
74
|
+
const result = {
|
|
75
|
+
topic,
|
|
76
|
+
content_type,
|
|
77
|
+
tone,
|
|
78
|
+
target_audience: target_audience || "์ผ๋ฐ",
|
|
79
|
+
generated_at: new Date().toISOString(),
|
|
80
|
+
ideas,
|
|
81
|
+
tips: getContentCreationTips(content_type),
|
|
82
|
+
};
|
|
83
|
+
return {
|
|
84
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
return {
|
|
89
|
+
content: [{ type: "text", text: `์์ด๋์ด ์์ฑ ์ค ์ค๋ฅ ๋ฐ์: ${error}` }],
|
|
90
|
+
isError: true,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
// =============================================================================
|
|
95
|
+
// Tool 3: ์ ๋ชฉ ๋ฐ ํด์ํ๊ทธ ์ต์ ํ (optimize_title_hashtags)
|
|
96
|
+
// =============================================================================
|
|
97
|
+
server.tool("optimize_title_hashtags", "์ฝํ
์ธ ์ ๋ชฉ์ ์ต์ ํํ๊ณ ๊ด๋ จ ํด์ํ๊ทธ๋ฅผ ์์ฑํฉ๋๋ค. CTR(ํด๋ฆญ๋ฅ ) ํฅ์์ ์ํ A/B ํ
์คํธ์ฉ ์ ๋ชฉ ๋ณํ๋ ์ ๊ณตํฉ๋๋ค.", {
|
|
98
|
+
original_title: z.string().describe("์๋ณธ ์ ๋ชฉ ๋๋ ์ฃผ์ "),
|
|
99
|
+
platform: ContentTypeSchema.optional().describe("ํ๊ฒ ํ๋ซํผ"),
|
|
100
|
+
keywords: z.array(z.string()).optional().describe("ํฌํจํ ํค์๋ ๋ชฉ๋ก"),
|
|
101
|
+
style: z.enum(["clickbait", "informative", "emotional", "question", "how-to", "listicle"]).optional().describe("์ ๋ชฉ ์คํ์ผ"),
|
|
102
|
+
max_length: z.number().optional().describe("์ต๋ ๊ธ์ ์"),
|
|
103
|
+
}, async ({ original_title, platform = "all", keywords = [], style = "informative", max_length = 60 }) => {
|
|
104
|
+
try {
|
|
105
|
+
const optimized = optimizeTitleAndHashtags(original_title, platform, keywords, style, max_length);
|
|
106
|
+
return {
|
|
107
|
+
content: [{ type: "text", text: JSON.stringify(optimized, null, 2) }],
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
return {
|
|
112
|
+
content: [{ type: "text", text: `์ ๋ชฉ ์ต์ ํ ์ค ์ค๋ฅ ๋ฐ์: ${error}` }],
|
|
113
|
+
isError: true,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
// =============================================================================
|
|
118
|
+
// Tool 4: SEO ํค์๋ ๋ถ์ (analyze_seo_keywords)
|
|
119
|
+
// =============================================================================
|
|
120
|
+
server.tool("analyze_seo_keywords", "ํค์๋์ SEO ์ ์ฌ๋ ฅ์ ๋ถ์ํ๊ณ ๊ด๋ จ ํค์๋, ๋กฑํ
์ผ ํค์๋๋ฅผ ์ถ์ฒํฉ๋๋ค.", {
|
|
121
|
+
keyword: z.string().describe("๋ถ์ํ ๋ฉ์ธ ํค์๋"),
|
|
122
|
+
language: z.enum(["ko", "en", "both"]).optional().describe("์ธ์ด (ko, en, both)"),
|
|
123
|
+
include_questions: z.boolean().optional().describe("๊ด๋ จ ์ง๋ฌธ ํค์๋ ํฌํจ ์ฌ๋ถ"),
|
|
124
|
+
include_longtail: z.boolean().optional().describe("๋กฑํ
์ผ ํค์๋ ํฌํจ ์ฌ๋ถ"),
|
|
125
|
+
}, async ({ keyword, language = "ko", include_questions = true, include_longtail = true }) => {
|
|
126
|
+
try {
|
|
127
|
+
const analysis = await analyzeSEOKeywords(keyword, language, include_questions, include_longtail);
|
|
128
|
+
return {
|
|
129
|
+
content: [{ type: "text", text: JSON.stringify(analysis, null, 2) }],
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
return {
|
|
134
|
+
content: [{ type: "text", text: `SEO ๋ถ์ ์ค ์ค๋ฅ ๋ฐ์: ${error}` }],
|
|
135
|
+
isError: true,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
// =============================================================================
|
|
140
|
+
// Tool 5: ์ฝํ
์ธ ์บ๋ฆฐ๋ ์์ฑ (create_content_calendar)
|
|
141
|
+
// =============================================================================
|
|
142
|
+
server.tool("create_content_calendar", "์ฃผ์ ์ ๊ธฐ๊ฐ์ ๋ง๋ ์ฝํ
์ธ ์บ๋ฆฐ๋๋ฅผ ์์ฑํฉ๋๋ค. ํ๊ตญ ๊ธฐ๋
์ผ๊ณผ ์์ฆ ์ด๋ฒคํธ๋ฅผ ๋ฐ์ํฉ๋๋ค.", {
|
|
143
|
+
topics: z.array(z.string()).describe("์ฝํ
์ธ ์ฃผ์ ๋ชฉ๋ก"),
|
|
144
|
+
duration_weeks: z.number().min(1).max(12).optional().describe("์บ๋ฆฐ๋ ๊ธฐ๊ฐ (์ฃผ ๋จ์). ๊ธฐ๋ณธ๊ฐ: 4"),
|
|
145
|
+
posts_per_week: z.number().min(1).max(14).optional().describe("์ฃผ๋น ํฌ์คํ
์. ๊ธฐ๋ณธ๊ฐ: 3"),
|
|
146
|
+
platforms: z.array(ContentTypeSchema).optional().describe("ํ๊ฒ ํ๋ซํผ ๋ชฉ๋ก"),
|
|
147
|
+
include_holidays: z.boolean().optional().describe("ํ๊ตญ ๊ณตํด์ผ/๊ธฐ๋
์ผ ํฌํจ ์ฌ๋ถ"),
|
|
148
|
+
}, async ({ topics, duration_weeks = 4, posts_per_week = 3, platforms = ["blog"], include_holidays = true }) => {
|
|
149
|
+
try {
|
|
150
|
+
const calendar = createContentCalendar(topics, duration_weeks, posts_per_week, platforms, include_holidays);
|
|
151
|
+
return {
|
|
152
|
+
content: [{ type: "text", text: JSON.stringify(calendar, null, 2) }],
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
catch (error) {
|
|
156
|
+
return {
|
|
157
|
+
content: [{ type: "text", text: `์บ๋ฆฐ๋ ์์ฑ ์ค ์ค๋ฅ ๋ฐ์: ${error}` }],
|
|
158
|
+
isError: true,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
// =============================================================================
|
|
163
|
+
// Tool 6: ๊ฒฝ์์ฌ ์ฝํ
์ธ ๋ถ์ (analyze_competitor_content)
|
|
164
|
+
// =============================================================================
|
|
165
|
+
server.tool("analyze_competitor_content", "๊ฒฝ์์ฌ ๋๋ ๋ฒค์น๋งํฌ ๋์์ ์ฝํ
์ธ ์ ๋ต์ ๋ถ์ํฉ๋๋ค.", {
|
|
166
|
+
urls: z.array(z.string()).describe("๋ถ์ํ URL ๋ชฉ๋ก (์ต๋ 5๊ฐ)"),
|
|
167
|
+
analysis_type: z.enum(["title", "structure", "keywords", "all"]).optional().describe("๋ถ์ ์ ํ"),
|
|
168
|
+
}, async ({ urls, analysis_type = "all" }) => {
|
|
169
|
+
try {
|
|
170
|
+
const analysis = await analyzeCompetitorContent(urls.slice(0, 5), analysis_type);
|
|
171
|
+
return {
|
|
172
|
+
content: [{ type: "text", text: JSON.stringify(analysis, null, 2) }],
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
catch (error) {
|
|
176
|
+
return {
|
|
177
|
+
content: [{ type: "text", text: `๊ฒฝ์์ฌ ๋ถ์ ์ค ์ค๋ฅ ๋ฐ์: ${error}` }],
|
|
178
|
+
isError: true,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
// =============================================================================
|
|
183
|
+
// Tool 7: ๋ฐ์ด๋ด ์ ์ ์์ธก (predict_viral_score)
|
|
184
|
+
// =============================================================================
|
|
185
|
+
server.tool("predict_viral_score", "์ฝํ
์ธ ์ ๋ฐ์ด๋ด ๊ฐ๋ฅ์ฑ์ ์์ธกํ๊ณ ๊ฐ์ ์ ์์ ์ ๊ณตํฉ๋๋ค.", {
|
|
186
|
+
title: z.string().describe("์ฝํ
์ธ ์ ๋ชฉ"),
|
|
187
|
+
description: z.string().optional().describe("์ฝํ
์ธ ์ค๋ช
๋๋ ์์ฝ"),
|
|
188
|
+
platform: ContentTypeSchema.optional().describe("ํ๊ฒ ํ๋ซํผ"),
|
|
189
|
+
hashtags: z.array(z.string()).optional().describe("์ฌ์ฉํ ํด์ํ๊ทธ"),
|
|
190
|
+
}, async ({ title, description = "", platform = "all", hashtags = [] }) => {
|
|
191
|
+
try {
|
|
192
|
+
const prediction = predictViralScore(title, description, platform, hashtags);
|
|
193
|
+
return {
|
|
194
|
+
content: [{ type: "text", text: JSON.stringify(prediction, null, 2) }],
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
catch (error) {
|
|
198
|
+
return {
|
|
199
|
+
content: [{ type: "text", text: `๋ฐ์ด๋ด ์์ธก ์ค ์ค๋ฅ ๋ฐ์: ${error}` }],
|
|
200
|
+
isError: true,
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
// =============================================================================
|
|
205
|
+
// Helper Functions
|
|
206
|
+
// =============================================================================
|
|
207
|
+
async function getNaverTrends(limit) {
|
|
208
|
+
// ๋ค์ด๋ฒ ์ค์๊ฐ ๊ฒ์์ด ์๋ฎฌ๋ ์ด์
(์ค์ ๋ก๋ DataLab API ์ฌ์ฉ)
|
|
209
|
+
const trendKeywords = [
|
|
210
|
+
{ keyword: "AI ํ์ฉ๋ฒ", platform: "naver", rank: 1, change: "up", category: "tech" },
|
|
211
|
+
{ keyword: "2025 ํธ๋ ๋", platform: "naver", rank: 2, change: "new", category: "lifestyle" },
|
|
212
|
+
{ keyword: "์ฐ๋ง์ ์ฐ", platform: "naver", rank: 3, change: "up", category: "finance" },
|
|
213
|
+
{ keyword: "๊ฒจ์ธ ์ฌํ์ง", platform: "naver", rank: 4, change: "same", category: "travel" },
|
|
214
|
+
{ keyword: "ChatGPT ํ์ฉ", platform: "naver", rank: 5, change: "up", category: "tech" },
|
|
215
|
+
{ keyword: "์ฐ๋ด ํ์", platform: "naver", rank: 6, change: "new", category: "career" },
|
|
216
|
+
{ keyword: "๊ฑด๊ฐ ๊ด๋ฆฌ", platform: "naver", rank: 7, change: "up", category: "health" },
|
|
217
|
+
{ keyword: "์ฌํ
ํฌ ๋ฐฉ๋ฒ", platform: "naver", rank: 8, change: "same", category: "finance" },
|
|
218
|
+
{ keyword: "์ ๋
๊ณํ", platform: "naver", rank: 9, change: "new", category: "lifestyle" },
|
|
219
|
+
{ keyword: "MZ์ธ๋ ํธ๋ ๋", platform: "naver", rank: 10, change: "up", category: "culture" },
|
|
220
|
+
];
|
|
221
|
+
return trendKeywords.slice(0, limit);
|
|
222
|
+
}
|
|
223
|
+
async function getGoogleTrendsKorea(limit) {
|
|
224
|
+
const trendKeywords = [
|
|
225
|
+
{ keyword: "์ธ๊ณต์ง๋ฅ ๋ด์ค", platform: "google", rank: 1, change: "up", category: "tech" },
|
|
226
|
+
{ keyword: "K-์ฝํ
์ธ ", platform: "google", rank: 2, change: "up", category: "entertainment" },
|
|
227
|
+
{ keyword: "์๊ธฐ๊ณ๋ฐ", platform: "google", rank: 3, change: "new", category: "education" },
|
|
228
|
+
{ keyword: "ํฌ์ ์ ๋ต", platform: "google", rank: 4, change: "same", category: "finance" },
|
|
229
|
+
{ keyword: "์๊ฒฉ๊ทผ๋ฌด", platform: "google", rank: 5, change: "up", category: "work" },
|
|
230
|
+
];
|
|
231
|
+
return trendKeywords.slice(0, limit);
|
|
232
|
+
}
|
|
233
|
+
async function getYoutubeTrendsKorea(limit) {
|
|
234
|
+
const trendKeywords = [
|
|
235
|
+
{ keyword: "๋ธ์ด๋ก๊ทธ", platform: "youtube", rank: 1, views: "1.2M", category: "lifestyle" },
|
|
236
|
+
{ keyword: "๋จน๋ฐฉ ASMR", platform: "youtube", rank: 2, views: "980K", category: "food" },
|
|
237
|
+
{ keyword: "๊ฒ์ ์คํธ๋ฆฌ๋ฐ", platform: "youtube", rank: 3, views: "850K", category: "gaming" },
|
|
238
|
+
{ keyword: "์ฝ๋ฉ ๊ฐ์", platform: "youtube", rank: 4, views: "720K", category: "education" },
|
|
239
|
+
{ keyword: "์ผ์ ๊ณต์ ", platform: "youtube", rank: 5, views: "650K", category: "lifestyle" },
|
|
240
|
+
];
|
|
241
|
+
return trendKeywords.slice(0, limit);
|
|
242
|
+
}
|
|
243
|
+
function generateTrendInsights(trends) {
|
|
244
|
+
return [
|
|
245
|
+
"๐ฅ AI/๊ธฐ์ ๊ด๋ จ ํค์๋๊ฐ ์์๊ถ์ ๋ค์ ํฌ์ง - AI ์ฝํ
์ธ ์์ ์ฆ๊ฐ",
|
|
246
|
+
"๐ฐ ์ฌํ
ํฌ/๊ธ์ต ํค์๋ ๊พธ์คํ ์ธ๊ธฐ - ๊ฒฝ์ ์ฝํ
์ธ ๊ธฐํ",
|
|
247
|
+
"โ๏ธ ์ฌํ ๊ด๋ จ ๊ฒ์ ์ฆ๊ฐ - ์์ฆ ์ฝํ
์ธ ํ์ด๋ฐ",
|
|
248
|
+
"๐ ์๊ธฐ๊ณ๋ฐ/๊ต์ก ํค์๋ ์์น์ธ - ์ ๋
์์ฆ ํจ๊ณผ",
|
|
249
|
+
];
|
|
250
|
+
}
|
|
251
|
+
function generateContentIdeas(topic, contentType, tone, targetAudience, count) {
|
|
252
|
+
const ideas = [];
|
|
253
|
+
const templates = [
|
|
254
|
+
{ format: "๋ฆฌ์คํธ", prefix: "X๊ฐ์ง", suffix: "๋ฐฉ๋ฒ/ํ/๋น๋ฒ" },
|
|
255
|
+
{ format: "ํ์ฐํฌ", prefix: "์ด๋ป๊ฒ", suffix: "ํ๋๊ฐ" },
|
|
256
|
+
{ format: "๋น๊ต", prefix: "A vs B:", suffix: "์๋ฒฝ ๋น๊ต" },
|
|
257
|
+
{ format: "์ผ์ด์ค์คํฐ๋", prefix: "์ฑ๊ณต ์ฌ๋ก:", suffix: "๋ถ์" },
|
|
258
|
+
{ format: "ํธ๋ ๋", prefix: "2025๋
", suffix: "ํธ๋ ๋ ์ ๋ง" },
|
|
259
|
+
{ format: "์ด๋ณด์๊ฐ์ด๋", prefix: "์๋ฒฝ ๊ฐ์ด๋:", suffix: "์
๋ฌธ๋ถํฐ ์ค์ ๊น์ง" },
|
|
260
|
+
{ format: "์ค์", prefix: "ํํ ์ค์", suffix: "ํผํ๋ ๋ฒ" },
|
|
261
|
+
{ format: "๋น๋ฐ", prefix: "์๋ ค์ง์ง ์์", suffix: "๋น๋ฐ ํ" },
|
|
262
|
+
{ format: "Q&A", prefix: "์์ฃผ ๋ฌป๋ ์ง๋ฌธ:", suffix: "๋ต๋ณ ๋ชจ์" },
|
|
263
|
+
{ format: "์ฒดํฌ๋ฆฌ์คํธ", prefix: "ํ์", suffix: "์ฒดํฌ๋ฆฌ์คํธ" },
|
|
264
|
+
];
|
|
265
|
+
for (let i = 0; i < count; i++) {
|
|
266
|
+
const template = templates[i % templates.length];
|
|
267
|
+
ideas.push({
|
|
268
|
+
id: i + 1,
|
|
269
|
+
title: `${template.prefix} ${topic} ${template.suffix}`,
|
|
270
|
+
format: template.format,
|
|
271
|
+
estimated_engagement: ["๋์", "์ค๊ฐ", "๋งค์ฐ ๋์"][Math.floor(Math.random() * 3)],
|
|
272
|
+
suggested_length: contentType === "youtube" ? "10-15๋ถ" : contentType === "tiktok" ? "30-60์ด" : "1500-2500์",
|
|
273
|
+
best_posting_time: getOptimalPostingTime(contentType),
|
|
274
|
+
hooks: generateHooks(topic, template.format),
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
return ideas;
|
|
278
|
+
}
|
|
279
|
+
function generateHooks(topic, format) {
|
|
280
|
+
return [
|
|
281
|
+
`"${topic}์ ๋ํด ์ด๊ฒ๋ง ์๋ฉด ๋ฉ๋๋ค"`,
|
|
282
|
+
`"99%๊ฐ ๋ชจ๋ฅด๋ ${topic}์ ๋น๋ฐ"`,
|
|
283
|
+
`"${topic} ์ ๋ฌธ๊ฐ๊ฐ ์ ๋ ์๋ ค์ฃผ์ง ์๋ ๊ฒ"`,
|
|
284
|
+
];
|
|
285
|
+
}
|
|
286
|
+
function getOptimalPostingTime(contentType) {
|
|
287
|
+
const times = {
|
|
288
|
+
blog: "ํ์ผ ์ค์ 9-11์, ์ ๋
7-9์",
|
|
289
|
+
youtube: "์ฃผ๋ง ์คํ 2-4์, ํ์ผ ์ ๋
8-10์",
|
|
290
|
+
instagram: "์ ์ฌ 12-1์, ์ ๋
7-9์",
|
|
291
|
+
tiktok: "์ ๋
6-10์, ์ฃผ๋ง ์คํ",
|
|
292
|
+
newsletter: "ํ์์ผ/๋ชฉ์์ผ ์ค์ 8-9์",
|
|
293
|
+
all: "ํ๋ซํผ๋ณ ์ต์ ์๊ฐ ๋ถ์ ํ์",
|
|
294
|
+
};
|
|
295
|
+
return times[contentType] || times.all;
|
|
296
|
+
}
|
|
297
|
+
function getContentCreationTips(contentType) {
|
|
298
|
+
const tips = {
|
|
299
|
+
blog: [
|
|
300
|
+
"์ฒซ ๋ฌธ๋จ์์ ํต์ฌ ๊ฐ์น๋ฅผ ์ ๋ฌํ์ธ์",
|
|
301
|
+
"์์ ๋ชฉ์ ํ์ฉํด ์ค์บ ๊ฐ๋ฅํ ๊ตฌ์กฐ๋ก ์์ฑํ์ธ์",
|
|
302
|
+
"๋ด๋ถ/์ธ๋ถ ๋งํฌ๋ฅผ ์ ์ ํ ํ์ฉํ์ธ์",
|
|
303
|
+
],
|
|
304
|
+
youtube: [
|
|
305
|
+
"์ฒ์ 30์ด๊ฐ ์์ฒญ ์ ์ง์จ์ ๊ฒฐ์ ํฉ๋๋ค",
|
|
306
|
+
"์ฑํฐ๋ฅผ ํ์ฉํด ํ์์ฑ์ ๋์ด์ธ์",
|
|
307
|
+
"์๋์นด๋์ ์นด๋๋ฅผ ์ ๊ทน ํ์ฉํ์ธ์",
|
|
308
|
+
],
|
|
309
|
+
instagram: [
|
|
310
|
+
"์ฒซ ์ค์์ ๊ด์ฌ์ ๋์ธ์ (์ค๋ฐ๊ฟ ์ )",
|
|
311
|
+
"์บ๋ฌ์
์ ํ์ฉํด ์ค์์ดํ๋ฅผ ์ ๋ํ์ธ์",
|
|
312
|
+
"์คํ ๋ฆฌ์ ๋ฆด์ค๋ฅผ ํจ๊ป ํ์ฉํ์ธ์",
|
|
313
|
+
],
|
|
314
|
+
tiktok: [
|
|
315
|
+
"์ฒ์ 1์ด๊ฐ ์น๋ถ์
๋๋ค",
|
|
316
|
+
"ํธ๋ ๋ฉ ์ฌ์ด๋๋ฅผ ํ์ฉํ์ธ์",
|
|
317
|
+
"๋๊ธ์ ์ ๊ทน ๋ฐ์ํ์ธ์",
|
|
318
|
+
],
|
|
319
|
+
newsletter: [
|
|
320
|
+
"์ ๋ชฉ์ ๊ตฌ์ฒด์ ์ธ ๊ฐ์น๋ฅผ ๋ช
์ํ์ธ์",
|
|
321
|
+
"๊ฐ์ธํ๋ ์ธ์ฌ๋ง์ ์ฌ์ฉํ์ธ์",
|
|
322
|
+
"๋ช
ํํ CTA๋ฅผ ํฌํจํ์ธ์",
|
|
323
|
+
],
|
|
324
|
+
all: [
|
|
325
|
+
"์ผ๊ด๋ ๋ธ๋๋ ํค์ ์ ์งํ์ธ์",
|
|
326
|
+
"๋ฐ์ดํฐ ๊ธฐ๋ฐ์ผ๋ก ๊ฐ์ ํ์ธ์",
|
|
327
|
+
"์ปค๋ฎค๋ํฐ์ ์ํตํ์ธ์",
|
|
328
|
+
],
|
|
329
|
+
};
|
|
330
|
+
return tips[contentType] || tips.all;
|
|
331
|
+
}
|
|
332
|
+
function optimizeTitleAndHashtags(originalTitle, platform, keywords, style, maxLength) {
|
|
333
|
+
const variations = generateTitleVariations(originalTitle, style, maxLength);
|
|
334
|
+
const hashtags = generateOptimalHashtags(originalTitle, keywords, platform);
|
|
335
|
+
return {
|
|
336
|
+
original: originalTitle,
|
|
337
|
+
optimized_titles: variations,
|
|
338
|
+
recommended_title: variations[0],
|
|
339
|
+
hashtags: {
|
|
340
|
+
primary: hashtags.slice(0, 5),
|
|
341
|
+
secondary: hashtags.slice(5, 15),
|
|
342
|
+
trending: hashtags.slice(15, 20),
|
|
343
|
+
},
|
|
344
|
+
character_count: variations[0].title.length,
|
|
345
|
+
seo_score: Math.floor(Math.random() * 20) + 80,
|
|
346
|
+
tips: [
|
|
347
|
+
"์ซ์๋ฅผ ํฌํจํ๋ฉด CTR์ด 36% ์ฆ๊ฐํฉ๋๋ค",
|
|
348
|
+
"๊ฐ์ ์ ์๊ทนํ๋ ๋จ์ด๋ฅผ ์ฌ์ฉํ์ธ์",
|
|
349
|
+
"์ง๋ฌธํ ์ ๋ชฉ์ ์ฐธ์ฌ์จ์ ๋์
๋๋ค",
|
|
350
|
+
],
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
function generateTitleVariations(original, style, maxLength) {
|
|
354
|
+
const variations = [
|
|
355
|
+
{ title: `[์๋ฒฝ์ ๋ฆฌ] ${original}`, style: "informative", ctr_prediction: "๋์" },
|
|
356
|
+
{ title: `${original} (์ด๊ฒ๋ง ๋ณด์ธ์)`, style: "clickbait", ctr_prediction: "๋งค์ฐ ๋์" },
|
|
357
|
+
{ title: `${original}? ์ ๋ฌธ๊ฐ๊ฐ ๋ตํฉ๋๋ค`, style: "question", ctr_prediction: "๋์" },
|
|
358
|
+
{ title: `${original} ํ๋ 5๊ฐ์ง ๋ฐฉ๋ฒ`, style: "listicle", ctr_prediction: "๋์" },
|
|
359
|
+
{ title: `${original}: ์ด๋ณด์๋ ์ฝ๊ฒ ๋ฐ๋ผํ๊ธฐ`, style: "how-to", ctr_prediction: "์ค๊ฐ" },
|
|
360
|
+
];
|
|
361
|
+
return variations.map(v => ({
|
|
362
|
+
...v,
|
|
363
|
+
length: v.title.length,
|
|
364
|
+
within_limit: v.title.length <= maxLength,
|
|
365
|
+
}));
|
|
366
|
+
}
|
|
367
|
+
function generateOptimalHashtags(title, keywords, platform) {
|
|
368
|
+
const baseHashtags = keywords.map(k => `#${k.replace(/\s/g, '')}`);
|
|
369
|
+
const trendingHashtags = [
|
|
370
|
+
"#ํธ๋ ๋", "#๊ฟํ", "#์ถ์ฒ", "#๋ฆฌ๋ทฐ", "#์ผ์",
|
|
371
|
+
"#์ ๋ณด", "#๊ณต์ ", "#๋ธ์ด๋ก๊ทธ", "#์ํต", "#๋งํ",
|
|
372
|
+
"#ํ๋ก์ฐ", "#์ข์์", "#์ธ์คํ๊ทธ๋จ", "#์ ํ๋ธ", "#๋ธ๋ก๊ทธ",
|
|
373
|
+
"#์๊ธฐ๊ณ๋ฐ", "#์ฑ์ฅ", "#๋๊ธฐ๋ถ์ฌ", "#์ธ์ฌ์ดํธ", "#2025",
|
|
374
|
+
];
|
|
375
|
+
return [...baseHashtags, ...trendingHashtags];
|
|
376
|
+
}
|
|
377
|
+
async function analyzeSEOKeywords(keyword, language, includeQuestions, includeLongtail) {
|
|
378
|
+
const relatedKeywords = [
|
|
379
|
+
{ keyword: `${keyword} ๋ฐฉ๋ฒ`, volume: "๋์", competition: "์ค๊ฐ", trend: "์์น" },
|
|
380
|
+
{ keyword: `${keyword} ์ถ์ฒ`, volume: "๋์", competition: "๋์", trend: "์ ์ง" },
|
|
381
|
+
{ keyword: `${keyword} ๋น๊ต`, volume: "์ค๊ฐ", competition: "๋ฎ์", trend: "์์น" },
|
|
382
|
+
{ keyword: `${keyword} ํ๊ธฐ`, volume: "์ค๊ฐ", competition: "์ค๊ฐ", trend: "์ ์ง" },
|
|
383
|
+
{ keyword: `${keyword} ๊ฐ๊ฒฉ`, volume: "๋์", competition: "๋์", trend: "์ ์ง" },
|
|
384
|
+
];
|
|
385
|
+
const questionKeywords = includeQuestions ? [
|
|
386
|
+
`${keyword}์ด๋?`,
|
|
387
|
+
`${keyword} ์ด๋ป๊ฒ?`,
|
|
388
|
+
`${keyword} ์ ํ์ํ๊ฐ?`,
|
|
389
|
+
`${keyword} ์ฅ๋จ์ ์?`,
|
|
390
|
+
`${keyword} ์์ํ๋ ค๋ฉด?`,
|
|
391
|
+
] : [];
|
|
392
|
+
const longtailKeywords = includeLongtail ? [
|
|
393
|
+
`์ด๋ณด์๋ฅผ ์ํ ${keyword} ๊ฐ์ด๋`,
|
|
394
|
+
`${keyword} ์ค์ ํผํ๋ ๋ฒ`,
|
|
395
|
+
`${keyword} ์ ๋ฌธ๊ฐ ์ถ์ฒ`,
|
|
396
|
+
`2025๋
${keyword} ํธ๋ ๋`,
|
|
397
|
+
`${keyword} ์๋ฒฝ ์ ๋ฆฌ`,
|
|
398
|
+
] : [];
|
|
399
|
+
return {
|
|
400
|
+
main_keyword: keyword,
|
|
401
|
+
search_volume_estimate: "๋์",
|
|
402
|
+
competition_level: "์ค๊ฐ",
|
|
403
|
+
seo_difficulty: 65,
|
|
404
|
+
content_suggestions: [
|
|
405
|
+
"ํฌ๊ด์ ์ธ ๊ฐ์ด๋ ์ฝํ
์ธ ์์ฑ",
|
|
406
|
+
"FAQ ์น์
์ถ๊ฐ",
|
|
407
|
+
"๋น์ฃผ์ผ ์ฝํ
์ธ ํ์ฉ",
|
|
408
|
+
],
|
|
409
|
+
related_keywords: relatedKeywords,
|
|
410
|
+
question_keywords: questionKeywords,
|
|
411
|
+
longtail_keywords: longtailKeywords,
|
|
412
|
+
monthly_trend: "์์น์ธ",
|
|
413
|
+
best_content_type: "์ข
ํฉ ๊ฐ์ด๋ + ๋น๋์ค",
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
function createContentCalendar(topics, durationWeeks, postsPerWeek, platforms, includeHolidays) {
|
|
417
|
+
const calendar = [];
|
|
418
|
+
const startDate = new Date();
|
|
419
|
+
// ํ๊ตญ ๊ณตํด์ผ/๊ธฐ๋
์ผ (2025๋
๊ธฐ์ค)
|
|
420
|
+
const koreanHolidays = [
|
|
421
|
+
{ date: "01-01", name: "์ํด", type: "holiday" },
|
|
422
|
+
{ date: "01-28", name: "์ค๋ ์ฐํด ์์", type: "holiday" },
|
|
423
|
+
{ date: "02-14", name: "๋ฐ๋ ํ์ธ๋ฐ์ด", type: "event" },
|
|
424
|
+
{ date: "03-01", name: "์ผ์ผ์ ", type: "holiday" },
|
|
425
|
+
{ date: "03-14", name: "ํ์ดํธ๋ฐ์ด", type: "event" },
|
|
426
|
+
{ date: "05-05", name: "์ด๋ฆฐ์ด๋ ", type: "holiday" },
|
|
427
|
+
{ date: "05-15", name: "์ค์น์๋ ", type: "event" },
|
|
428
|
+
{ date: "11-11", name: "๋นผ๋นผ๋ก๋ฐ์ด", type: "event" },
|
|
429
|
+
{ date: "12-25", name: "ํฌ๋ฆฌ์ค๋ง์ค", type: "holiday" },
|
|
430
|
+
];
|
|
431
|
+
for (let week = 0; week < durationWeeks; week++) {
|
|
432
|
+
const weekStart = new Date(startDate);
|
|
433
|
+
weekStart.setDate(startDate.getDate() + week * 7);
|
|
434
|
+
const weekPlan = {
|
|
435
|
+
week: week + 1,
|
|
436
|
+
start_date: weekStart.toISOString().split('T')[0],
|
|
437
|
+
posts: [],
|
|
438
|
+
theme: topics[week % topics.length],
|
|
439
|
+
};
|
|
440
|
+
for (let post = 0; post < postsPerWeek; post++) {
|
|
441
|
+
const postDate = new Date(weekStart);
|
|
442
|
+
postDate.setDate(weekStart.getDate() + Math.floor((post / postsPerWeek) * 7));
|
|
443
|
+
const dateStr = postDate.toISOString().split('T')[0];
|
|
444
|
+
const holiday = includeHolidays ?
|
|
445
|
+
koreanHolidays.find(h => dateStr.endsWith(h.date)) : null;
|
|
446
|
+
weekPlan.posts.push({
|
|
447
|
+
id: week * postsPerWeek + post + 1,
|
|
448
|
+
date: dateStr,
|
|
449
|
+
day: ["์ผ", "์", "ํ", "์", "๋ชฉ", "๊ธ", "ํ "][postDate.getDay()],
|
|
450
|
+
topic: holiday ? `${holiday.name} ํน์ง: ${topics[post % topics.length]}` : topics[post % topics.length],
|
|
451
|
+
platform: platforms[post % platforms.length],
|
|
452
|
+
status: "planned",
|
|
453
|
+
suggested_time: getOptimalPostingTime(platforms[post % platforms.length]),
|
|
454
|
+
special_event: holiday?.name || null,
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
calendar.push(weekPlan);
|
|
458
|
+
}
|
|
459
|
+
return {
|
|
460
|
+
duration: `${durationWeeks}์ฃผ`,
|
|
461
|
+
total_posts: durationWeeks * postsPerWeek,
|
|
462
|
+
platforms,
|
|
463
|
+
topics,
|
|
464
|
+
calendar,
|
|
465
|
+
recommendations: [
|
|
466
|
+
"์ฃผ์ ๊ณตํด์ผ ์ ํ๋ก ๊ด๋ จ ์ฝํ
์ธ ๋ฏธ๋ฆฌ ์ค๋นํ์ธ์",
|
|
467
|
+
"ํ๋ซํผ๋ณ ์ต์ ๊ฒ์ ์๊ฐ์ ํ์ฉํ์ธ์",
|
|
468
|
+
"์ฃผ์ ๋ณ ์๋ฆฌ์ฆ๋ก ์ผ๊ด์ฑ์ ์ ์งํ์ธ์",
|
|
469
|
+
],
|
|
470
|
+
};
|
|
471
|
+
}
|
|
472
|
+
async function analyzeCompetitorContent(urls, analysisType) {
|
|
473
|
+
const results = [];
|
|
474
|
+
for (const url of urls) {
|
|
475
|
+
try {
|
|
476
|
+
const response = await axios.get(url, {
|
|
477
|
+
headers: { 'User-Agent': 'Mozilla/5.0 (compatible; ContentGenieBot/1.0)' },
|
|
478
|
+
timeout: 10000,
|
|
479
|
+
});
|
|
480
|
+
const $ = cheerio.load(response.data);
|
|
481
|
+
const analysis = {
|
|
482
|
+
url,
|
|
483
|
+
title: $('title').text().trim(),
|
|
484
|
+
meta_description: $('meta[name="description"]').attr('content') || '',
|
|
485
|
+
headings: {
|
|
486
|
+
h1: $('h1').map((_, el) => $(el).text().trim()).get(),
|
|
487
|
+
h2: $('h2').map((_, el) => $(el).text().trim()).get().slice(0, 10),
|
|
488
|
+
},
|
|
489
|
+
word_count: $('body').text().split(/\s+/).length,
|
|
490
|
+
images_count: $('img').length,
|
|
491
|
+
internal_links: $('a[href^="/"]').length,
|
|
492
|
+
external_links: $('a[href^="http"]').length,
|
|
493
|
+
};
|
|
494
|
+
if (analysisType === "keywords" || analysisType === "all") {
|
|
495
|
+
const text = $('body').text().toLowerCase();
|
|
496
|
+
const words = text.match(/[\uAC00-\uD7AF]+|[a-z]+/g) || [];
|
|
497
|
+
const wordFreq = {};
|
|
498
|
+
words.forEach(word => {
|
|
499
|
+
if (word.length > 2)
|
|
500
|
+
wordFreq[word] = (wordFreq[word] || 0) + 1;
|
|
501
|
+
});
|
|
502
|
+
analysis.top_keywords = Object.entries(wordFreq)
|
|
503
|
+
.sort((a, b) => b[1] - a[1])
|
|
504
|
+
.slice(0, 20)
|
|
505
|
+
.map(([word, count]) => ({ word, count }));
|
|
506
|
+
}
|
|
507
|
+
results.push(analysis);
|
|
508
|
+
}
|
|
509
|
+
catch (error) {
|
|
510
|
+
results.push({ url, error: "๋ถ์ ์คํจ - ์ ๊ทผ ๋ถ๊ฐ ๋๋ ํ์์์" });
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
return {
|
|
514
|
+
analyzed_at: new Date().toISOString(),
|
|
515
|
+
total_urls: urls.length,
|
|
516
|
+
successful: results.filter(r => !r.error).length,
|
|
517
|
+
results,
|
|
518
|
+
insights: [
|
|
519
|
+
"๊ฒฝ์์ฌ ์ฝํ
์ธ ์ ํ๊ท ๊ธธ์ด๋ฅผ ์ฐธ๊ณ ํ์ธ์",
|
|
520
|
+
"์์ฃผ ์ฌ์ฉ๋๋ ํค์๋๋ฅผ ํ์
ํ์ธ์",
|
|
521
|
+
"์ ๋ชฉ๊ณผ ๋ฉํ ์ค๋ช
์ ํจํด์ ๋ถ์ํ์ธ์",
|
|
522
|
+
],
|
|
523
|
+
};
|
|
524
|
+
}
|
|
525
|
+
function predictViralScore(title, description, platform, hashtags) {
|
|
526
|
+
// ๋ฐ์ด๋ด ์์ ๋ถ์
|
|
527
|
+
const viralFactors = {
|
|
528
|
+
emotional_words: /๋๋ผ์ด|์ถฉ๊ฒฉ|๋น๋ฐ|์ต๊ณ |์๋ฒฝ|ํ์|๊ธ|ํซ|๋๋ฐ|๋ ์ ๋/g,
|
|
529
|
+
numbers: /\d+/g,
|
|
530
|
+
questions: /\?/g,
|
|
531
|
+
urgency: /์ง๊ธ|์ค๋|๋ฐ๋ก|์ฆ์|ํ์ /g,
|
|
532
|
+
social_proof: /๋ง๋ช
|๋ฆฌ๋ทฐ|ํ๊ธฐ|์ธ์ฆ|์ถ์ฒ/g,
|
|
533
|
+
};
|
|
534
|
+
let score = 50; // ๊ธฐ๋ณธ ์ ์
|
|
535
|
+
// ์ ๋ชฉ ๋ถ์
|
|
536
|
+
if (viralFactors.emotional_words.test(title))
|
|
537
|
+
score += 15;
|
|
538
|
+
if (viralFactors.numbers.test(title))
|
|
539
|
+
score += 10;
|
|
540
|
+
if (viralFactors.questions.test(title))
|
|
541
|
+
score += 8;
|
|
542
|
+
if (viralFactors.urgency.test(title))
|
|
543
|
+
score += 7;
|
|
544
|
+
if (viralFactors.social_proof.test(title))
|
|
545
|
+
score += 10;
|
|
546
|
+
// ๊ธธ์ด ๋ถ์
|
|
547
|
+
if (title.length >= 20 && title.length <= 50)
|
|
548
|
+
score += 5;
|
|
549
|
+
// ํด์ํ๊ทธ ๋ถ์
|
|
550
|
+
if (hashtags.length >= 5 && hashtags.length <= 15)
|
|
551
|
+
score += 5;
|
|
552
|
+
score = Math.min(score, 100);
|
|
553
|
+
const improvements = [];
|
|
554
|
+
if (!viralFactors.numbers.test(title))
|
|
555
|
+
improvements.push("์ซ์๋ฅผ ์ถ๊ฐํ์ธ์ (์: '5๊ฐ์ง ๋ฐฉ๋ฒ')");
|
|
556
|
+
if (!viralFactors.emotional_words.test(title))
|
|
557
|
+
improvements.push("๊ฐ์ ์ ์๊ทนํ๋ ๋จ์ด๋ฅผ ์ถ๊ฐํ์ธ์");
|
|
558
|
+
if (title.length > 60)
|
|
559
|
+
improvements.push("์ ๋ชฉ์ 60์ ์ด๋ด๋ก ์ค์ด์ธ์");
|
|
560
|
+
if (hashtags.length < 5)
|
|
561
|
+
improvements.push("ํด์ํ๊ทธ๋ฅผ 5๊ฐ ์ด์ ์ถ๊ฐํ์ธ์");
|
|
562
|
+
return {
|
|
563
|
+
title,
|
|
564
|
+
viral_score: score,
|
|
565
|
+
grade: score >= 80 ? "A (๋งค์ฐ ๋์)" : score >= 60 ? "B (๋์)" : score >= 40 ? "C (๋ณดํต)" : "D (๊ฐ์ ํ์)",
|
|
566
|
+
factors: {
|
|
567
|
+
emotional_appeal: viralFactors.emotional_words.test(title) ? "๊ฐํจ" : "์ฝํจ",
|
|
568
|
+
curiosity_gap: viralFactors.questions.test(title) ? "์์" : "์์",
|
|
569
|
+
specificity: viralFactors.numbers.test(title) ? "๊ตฌ์ฒด์ " : "๋ชจํธํจ",
|
|
570
|
+
urgency: viralFactors.urgency.test(title) ? "์์" : "์์",
|
|
571
|
+
},
|
|
572
|
+
improvements,
|
|
573
|
+
predicted_engagement: {
|
|
574
|
+
likes: score >= 70 ? "๋์" : "๋ณดํต",
|
|
575
|
+
shares: score >= 80 ? "๋์" : "๋ณดํต",
|
|
576
|
+
comments: score >= 60 ? "ํ๋ฐ" : "๋ณดํต",
|
|
577
|
+
},
|
|
578
|
+
};
|
|
579
|
+
}
|
|
580
|
+
// =============================================================================
|
|
581
|
+
// Server Start
|
|
582
|
+
// =============================================================================
|
|
583
|
+
async function main() {
|
|
584
|
+
const transport = new StdioServerTransport();
|
|
585
|
+
await server.connect(transport);
|
|
586
|
+
console.error("Content Genie MCP Server running on stdio");
|
|
587
|
+
}
|
|
588
|
+
main().catch(console.error);
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "content-genie-mcp",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "AI Content Creation Assistant MCP - ํ๊ตญ ์ฝํ
์ธ ํฌ๋ฆฌ์์ดํฐ๋ฅผ ์ํ ํธ๋ ๋ ๋ถ์ ๋ฐ ์ฝํ
์ธ ์์ฑ ๋์ฐ๋ฏธ",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"content-genie-mcp": "./dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc",
|
|
11
|
+
"start": "node dist/index.js",
|
|
12
|
+
"dev": "ts-node src/index.ts",
|
|
13
|
+
"prepare": "npm run build"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"mcp",
|
|
17
|
+
"content",
|
|
18
|
+
"trend",
|
|
19
|
+
"korean",
|
|
20
|
+
"ai",
|
|
21
|
+
"creator",
|
|
22
|
+
"marketing",
|
|
23
|
+
"seo"
|
|
24
|
+
],
|
|
25
|
+
"author": "Yoonkyoung Gong",
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"type": "module",
|
|
28
|
+
"engines": {
|
|
29
|
+
"node": ">=18.0.0"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@modelcontextprotocol/sdk": "^1.25.1",
|
|
33
|
+
"axios": "^1.13.2",
|
|
34
|
+
"cheerio": "^1.1.2",
|
|
35
|
+
"zod": "^4.2.1"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@types/node": "^25.0.3",
|
|
39
|
+
"ts-node": "^10.9.2",
|
|
40
|
+
"typescript": "^5.9.3"
|
|
41
|
+
}
|
|
42
|
+
}
|