@roottale/cms-mcp 0.42.0 → 0.44.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/CHANGELOG.md +14 -0
- package/README.md +41 -7
- package/dist/index.js +589 -58
- package/dist/index.js.map +1 -1
- package/docs/api-reference.md +124 -2
- package/docs/blog.md +5 -0
- package/docs/collections.md +38 -3
- package/docs/getting-started.md +52 -1
- package/docs/overview.md +9 -9
- package/examples/nextjs/app/blog/[slug]/page.tsx +2 -0
- package/package.json +4 -2
package/dist/index.js
CHANGED
|
@@ -3,6 +3,535 @@
|
|
|
3
3
|
// src/index.ts
|
|
4
4
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
5
|
|
|
6
|
+
// src/cli.ts
|
|
7
|
+
import { readFile as readFile2 } from "fs/promises";
|
|
8
|
+
import { Command, InvalidArgumentError } from "commander";
|
|
9
|
+
|
|
10
|
+
// src/api.ts
|
|
11
|
+
import ky from "ky";
|
|
12
|
+
var DEFAULT_API_BASE = "https://api.roottale.com";
|
|
13
|
+
var CmsAutomationError = class extends Error {
|
|
14
|
+
name = "CmsAutomationError";
|
|
15
|
+
};
|
|
16
|
+
function apiConfig() {
|
|
17
|
+
const apiKey = process.env.ROOTTALE_API_KEY;
|
|
18
|
+
if (!apiKey) {
|
|
19
|
+
throw new CmsAutomationError(
|
|
20
|
+
"ROOTTALE_API_KEY \uD658\uACBD\uBCC0\uC218\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4. \uC5B4\uB4DC\uBBFC \uC124\uC815 > \uC0AC\uC774\uD2B8 \uC5F0\uACB0 \uD0A4\uC5D0\uC11C read_write \uD0A4\uB97C \uBC1C\uAE09\uD574 MCP env\uC5D0 \uCD94\uAC00\uD558\uC138\uC694."
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
apiKey,
|
|
25
|
+
baseUrl: (process.env.ROOTTALE_API_BASE ?? DEFAULT_API_BASE).replace(
|
|
26
|
+
/\/+$/,
|
|
27
|
+
""
|
|
28
|
+
)
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
async function requestRootTaleApi(request) {
|
|
32
|
+
const { apiKey, baseUrl } = apiConfig();
|
|
33
|
+
const url = new URL(`${baseUrl}${request.pathname}`);
|
|
34
|
+
for (const [key, value] of Object.entries(request.query ?? {})) {
|
|
35
|
+
if (value !== void 0) url.searchParams.set(key, value);
|
|
36
|
+
}
|
|
37
|
+
return ky(url, {
|
|
38
|
+
method: request.method,
|
|
39
|
+
headers: { authorization: `Bearer ${apiKey}` },
|
|
40
|
+
json: request.body,
|
|
41
|
+
retry: 0,
|
|
42
|
+
timeout: 3e4
|
|
43
|
+
}).json();
|
|
44
|
+
}
|
|
45
|
+
async function putUpload(uploadUrl, bytes, contentType) {
|
|
46
|
+
const body = new Uint8Array(bytes.byteLength);
|
|
47
|
+
body.set(bytes);
|
|
48
|
+
await ky.put(uploadUrl, {
|
|
49
|
+
body: body.buffer,
|
|
50
|
+
headers: { "content-type": contentType },
|
|
51
|
+
retry: 0,
|
|
52
|
+
timeout: 12e4
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// src/automation-definitions.ts
|
|
57
|
+
var AUTOMATION_TOOL_DEFINITIONS = [
|
|
58
|
+
tool("listManagedCmsPosts", "\uCD08\uC548\xB7\uC608\uC57D\xB7\uBC1C\uD589 \uAE00\uC744 \uD3EC\uD568\uD55C \uAD00\uB9AC\uC6A9 \uAE00 \uBAA9\uB85D\uC744 \uC870\uD68C\uD569\uB2C8\uB2E4.", {
|
|
59
|
+
siteId: stringProperty("\uC0AC\uC774\uD2B8 ID"),
|
|
60
|
+
limit: numberProperty("1-100"),
|
|
61
|
+
type: enumProperty(["post", "page"]),
|
|
62
|
+
status: enumProperty(["draft", "published", "scheduled", "private"]),
|
|
63
|
+
cursor: stringProperty("\uC774\uC804 \uC751\uB2F5\uC758 next_cursor")
|
|
64
|
+
}),
|
|
65
|
+
tool(
|
|
66
|
+
"createCmsPost",
|
|
67
|
+
"Tiptap bodyJson\uC73C\uB85C \uAE00 \uB610\uB294 \uD398\uC774\uC9C0\uB97C \uC0DD\uC131\uD569\uB2C8\uB2E4. \uAE30\uBCF8\uC740 \uCD08\uC548\uC774\uBA70 publish=true\uBA74 \uC989\uC2DC \uBC1C\uD589\uD569\uB2C8\uB2E4.",
|
|
68
|
+
{
|
|
69
|
+
siteId: stringProperty("\uC0AC\uC774\uD2B8 ID"),
|
|
70
|
+
type: enumProperty(["post", "page"]),
|
|
71
|
+
title: stringProperty("\uC81C\uBAA9"),
|
|
72
|
+
slug: stringProperty("\uC2AC\uB7EC\uADF8"),
|
|
73
|
+
bodyJson: { type: "object", description: "Tiptap \uBB38\uC11C JSON" },
|
|
74
|
+
excerpt: nullableStringProperty("\uC694\uC57D"),
|
|
75
|
+
featuredMediaId: nullableStringProperty("\uB300\uD45C \uC774\uBBF8\uC9C0 media id"),
|
|
76
|
+
publish: { type: "boolean" },
|
|
77
|
+
scheduledAt: stringProperty("\uBBF8\uB798 ISO 8601 \uBC1C\uD589 \uC2DC\uAC01"),
|
|
78
|
+
categoryIds: arrayProperty("\uCE74\uD14C\uACE0\uB9AC term id"),
|
|
79
|
+
tagIds: arrayProperty("\uD0DC\uADF8 term id")
|
|
80
|
+
},
|
|
81
|
+
["title", "slug", "bodyJson"]
|
|
82
|
+
),
|
|
83
|
+
tool("updateCmsPost", "\uAE30\uC874 CMS \uAE00\uC744 \uBD80\uBD84 \uC218\uC815\uD569\uB2C8\uB2E4.", {
|
|
84
|
+
postId: stringProperty("\uAE00 ID"),
|
|
85
|
+
siteId: stringProperty("\uC0AC\uC774\uD2B8 ID"),
|
|
86
|
+
title: stringProperty("\uC81C\uBAA9"),
|
|
87
|
+
slug: stringProperty("\uC2AC\uB7EC\uADF8"),
|
|
88
|
+
bodyJson: { type: "object", description: "Tiptap \uBB38\uC11C JSON" },
|
|
89
|
+
excerpt: nullableStringProperty("\uC694\uC57D"),
|
|
90
|
+
featuredMediaId: nullableStringProperty("\uB300\uD45C \uC774\uBBF8\uC9C0 media id"),
|
|
91
|
+
scheduledAt: nullableStringProperty("\uC608\uC57D \uC2DC\uAC01")
|
|
92
|
+
}, ["postId"]),
|
|
93
|
+
tool("publishCmsPost", "\uCD08\uC548 \uB610\uB294 \uC608\uC57D \uAE00\uC744 \uC989\uC2DC \uBC1C\uD589\uD558\uACE0 \uC6F9\uD6C5\uC744 \uC804\uC1A1\uD569\uB2C8\uB2E4.", {
|
|
94
|
+
postId: stringProperty("\uAE00 ID"),
|
|
95
|
+
siteId: stringProperty("\uC0AC\uC774\uD2B8 ID")
|
|
96
|
+
}, ["postId"]),
|
|
97
|
+
tool("unpublishCmsPost", "\uBC1C\uD589 \uAE00\uC744 \uCD08\uC548\uC73C\uB85C \uB418\uB3CC\uB9BD\uB2C8\uB2E4.", {
|
|
98
|
+
postId: stringProperty("\uAE00 ID"),
|
|
99
|
+
siteId: stringProperty("\uC0AC\uC774\uD2B8 ID")
|
|
100
|
+
}, ["postId"]),
|
|
101
|
+
tool("setCmsPostTerms", "\uAE00\uC758 \uCE74\uD14C\uACE0\uB9AC \uB610\uB294 \uD0DC\uADF8 \uC5F0\uACB0\uC744 \uAD50\uCCB4\uD569\uB2C8\uB2E4.", {
|
|
102
|
+
postId: stringProperty("\uAE00 ID"),
|
|
103
|
+
siteId: stringProperty("\uC0AC\uC774\uD2B8 ID"),
|
|
104
|
+
taxonomy: enumProperty(["category", "tag"]),
|
|
105
|
+
termIds: arrayProperty("term id")
|
|
106
|
+
}, ["postId", "taxonomy", "termIds"]),
|
|
107
|
+
tool("listCmsMedia", "CMS \uBBF8\uB514\uC5B4 \uB77C\uC774\uBE0C\uB7EC\uB9AC\uB97C \uC870\uD68C\uD569\uB2C8\uB2E4.", {
|
|
108
|
+
siteId: stringProperty("\uC0AC\uC774\uD2B8 ID"),
|
|
109
|
+
limit: numberProperty("1-100"),
|
|
110
|
+
offset: numberProperty("0 \uC774\uC0C1")
|
|
111
|
+
}),
|
|
112
|
+
tool(
|
|
113
|
+
"uploadCmsMedia",
|
|
114
|
+
"\uB85C\uCEEC \uC774\uBBF8\uC9C0/PDF \uD30C\uC77C\uC744 \uC5C5\uB85C\uB4DC\uD558\uACE0 CMS media id\uC640 \uACF5\uAC1C URL\uC744 \uBC18\uD658\uD569\uB2C8\uB2E4.",
|
|
115
|
+
{
|
|
116
|
+
filePath: stringProperty("\uB85C\uCEEC \uD30C\uC77C \uC808\uB300/\uC0C1\uB300 \uACBD\uB85C"),
|
|
117
|
+
siteId: stringProperty("\uC0AC\uC774\uD2B8 ID"),
|
|
118
|
+
contentType: enumProperty([
|
|
119
|
+
"image/jpeg",
|
|
120
|
+
"image/png",
|
|
121
|
+
"image/webp",
|
|
122
|
+
"image/gif",
|
|
123
|
+
"application/pdf"
|
|
124
|
+
]),
|
|
125
|
+
alt: nullableStringProperty("\uB300\uCCB4 \uD14D\uC2A4\uD2B8"),
|
|
126
|
+
caption: nullableStringProperty("\uCEA1\uC158")
|
|
127
|
+
},
|
|
128
|
+
["filePath"]
|
|
129
|
+
),
|
|
130
|
+
tool("updateCmsMedia", "CMS \uBBF8\uB514\uC5B4\uC758 \uB300\uCCB4 \uD14D\uC2A4\uD2B8 \uB610\uB294 \uCEA1\uC158\uC744 \uC218\uC815\uD569\uB2C8\uB2E4.", {
|
|
131
|
+
mediaId: stringProperty("media id"),
|
|
132
|
+
siteId: stringProperty("\uC0AC\uC774\uD2B8 ID"),
|
|
133
|
+
alt: nullableStringProperty("\uB300\uCCB4 \uD14D\uC2A4\uD2B8"),
|
|
134
|
+
caption: nullableStringProperty("\uCEA1\uC158")
|
|
135
|
+
}, ["mediaId"]),
|
|
136
|
+
tool("deleteCmsMedia", "CMS \uBBF8\uB514\uC5B4\uB97C R2\uC640 \uB77C\uC774\uBE0C\uB7EC\uB9AC\uC5D0\uC11C \uC0AD\uC81C\uD569\uB2C8\uB2E4.", {
|
|
137
|
+
mediaId: stringProperty("media id"),
|
|
138
|
+
siteId: stringProperty("\uC0AC\uC774\uD2B8 ID")
|
|
139
|
+
}, ["mediaId"])
|
|
140
|
+
];
|
|
141
|
+
function isAutomationToolName(name) {
|
|
142
|
+
return AUTOMATION_TOOL_DEFINITIONS.some(
|
|
143
|
+
(toolDefinition) => toolDefinition.name === name
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
function tool(name, description, properties, required = []) {
|
|
147
|
+
return {
|
|
148
|
+
name,
|
|
149
|
+
description,
|
|
150
|
+
inputSchema: {
|
|
151
|
+
type: "object",
|
|
152
|
+
properties,
|
|
153
|
+
...required.length > 0 ? { required } : {},
|
|
154
|
+
additionalProperties: false
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
function stringProperty(description) {
|
|
159
|
+
return { type: "string", description };
|
|
160
|
+
}
|
|
161
|
+
function nullableStringProperty(description) {
|
|
162
|
+
return { type: ["string", "null"], description };
|
|
163
|
+
}
|
|
164
|
+
function numberProperty(description) {
|
|
165
|
+
return { type: "number", description };
|
|
166
|
+
}
|
|
167
|
+
function enumProperty(values) {
|
|
168
|
+
return { type: "string", enum: values };
|
|
169
|
+
}
|
|
170
|
+
function arrayProperty(description) {
|
|
171
|
+
return { type: "array", items: { type: "string" }, description };
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// src/automation-media.ts
|
|
175
|
+
import { readFile } from "fs/promises";
|
|
176
|
+
import { basename, extname, resolve } from "path";
|
|
177
|
+
import { z as z2 } from "zod";
|
|
178
|
+
|
|
179
|
+
// src/automation-schemas.ts
|
|
180
|
+
import { z } from "zod";
|
|
181
|
+
var SiteId = z.string().min(1).optional();
|
|
182
|
+
var PostId = z.string().min(1);
|
|
183
|
+
var NullableText = z.string().nullable().optional();
|
|
184
|
+
var CreatePostInput = z.object({
|
|
185
|
+
siteId: SiteId,
|
|
186
|
+
type: z.enum(["post", "page"]).optional(),
|
|
187
|
+
title: z.string().min(1).max(500),
|
|
188
|
+
slug: z.string().min(1).max(120),
|
|
189
|
+
bodyJson: z.record(z.string(), z.unknown()),
|
|
190
|
+
excerpt: z.string().max(1e3).nullable().optional(),
|
|
191
|
+
featuredMediaId: z.string().nullable().optional(),
|
|
192
|
+
publish: z.boolean().optional(),
|
|
193
|
+
scheduledAt: z.string().datetime({ offset: true }).optional(),
|
|
194
|
+
categoryIds: z.array(z.string()).optional(),
|
|
195
|
+
tagIds: z.array(z.string()).optional()
|
|
196
|
+
}).strict();
|
|
197
|
+
var UpdatePostInput = z.object({
|
|
198
|
+
postId: PostId,
|
|
199
|
+
siteId: SiteId,
|
|
200
|
+
title: z.string().min(1).max(500).optional(),
|
|
201
|
+
slug: z.string().min(1).max(120).optional(),
|
|
202
|
+
bodyJson: z.record(z.string(), z.unknown()).optional(),
|
|
203
|
+
excerpt: NullableText,
|
|
204
|
+
featuredMediaId: z.string().nullable().optional(),
|
|
205
|
+
scheduledAt: z.string().datetime({ offset: true }).nullable().optional()
|
|
206
|
+
}).strict();
|
|
207
|
+
var PostLifecycleInput = z.object({ postId: PostId, siteId: SiteId }).strict();
|
|
208
|
+
var ListManagedPostsInput = z.object({
|
|
209
|
+
siteId: SiteId,
|
|
210
|
+
limit: z.number().int().min(1).max(100).optional(),
|
|
211
|
+
type: z.enum(["post", "page"]).optional(),
|
|
212
|
+
status: z.enum(["draft", "published", "scheduled", "private"]).optional(),
|
|
213
|
+
cursor: z.string().optional()
|
|
214
|
+
}).strict();
|
|
215
|
+
var SetTermsInput = z.object({
|
|
216
|
+
postId: PostId,
|
|
217
|
+
siteId: SiteId,
|
|
218
|
+
taxonomy: z.enum(["category", "tag"]),
|
|
219
|
+
termIds: z.array(z.string())
|
|
220
|
+
}).strict();
|
|
221
|
+
var UploadMediaInput = z.object({
|
|
222
|
+
filePath: z.string().min(1),
|
|
223
|
+
siteId: SiteId,
|
|
224
|
+
contentType: z.enum([
|
|
225
|
+
"image/jpeg",
|
|
226
|
+
"image/png",
|
|
227
|
+
"image/webp",
|
|
228
|
+
"image/gif",
|
|
229
|
+
"application/pdf"
|
|
230
|
+
]).optional(),
|
|
231
|
+
alt: NullableText,
|
|
232
|
+
caption: NullableText
|
|
233
|
+
}).strict();
|
|
234
|
+
var ListMediaInput = z.object({
|
|
235
|
+
siteId: SiteId,
|
|
236
|
+
limit: z.number().int().min(1).max(100).optional(),
|
|
237
|
+
offset: z.number().int().nonnegative().optional()
|
|
238
|
+
}).strict();
|
|
239
|
+
var UpdateMediaInput = z.object({
|
|
240
|
+
mediaId: z.string().min(1),
|
|
241
|
+
siteId: SiteId,
|
|
242
|
+
alt: NullableText,
|
|
243
|
+
caption: NullableText
|
|
244
|
+
}).strict().refine((input) => input.alt !== void 0 || input.caption !== void 0, {
|
|
245
|
+
message: "alt \uB610\uB294 caption \uC911 \uD558\uB098 \uC774\uC0C1\uC774 \uD544\uC694\uD569\uB2C8\uB2E4."
|
|
246
|
+
});
|
|
247
|
+
var DeleteMediaInput = z.object({ mediaId: z.string().min(1), siteId: SiteId }).strict();
|
|
248
|
+
|
|
249
|
+
// src/automation-media.ts
|
|
250
|
+
async function uploadCmsMedia(args) {
|
|
251
|
+
const input = UploadMediaInput.parse(args);
|
|
252
|
+
const filePath = resolve(input.filePath);
|
|
253
|
+
const bytes = await readFile(filePath);
|
|
254
|
+
const contentType = input.contentType ?? inferContentType(filePath);
|
|
255
|
+
if (!contentType) {
|
|
256
|
+
throw new CmsAutomationError(
|
|
257
|
+
"contentType\uC744 \uCD94\uB860\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. jpg/png/webp/gif/pdf \uD30C\uC77C\uC774 \uC544\uB2C8\uBA74 contentType\uC744 \uC9C0\uC815\uD558\uC138\uC694."
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
const requested = z2.object({
|
|
261
|
+
upload_url: z2.string().url(),
|
|
262
|
+
r2_key: z2.string().min(1)
|
|
263
|
+
}).parse(
|
|
264
|
+
await requestRootTaleApi({
|
|
265
|
+
method: "POST",
|
|
266
|
+
pathname: "/v1/cms/media/uploads",
|
|
267
|
+
body: {
|
|
268
|
+
site_id: input.siteId,
|
|
269
|
+
original_name: basename(filePath),
|
|
270
|
+
content_type: contentType,
|
|
271
|
+
size_bytes: bytes.byteLength
|
|
272
|
+
}
|
|
273
|
+
})
|
|
274
|
+
);
|
|
275
|
+
await putUpload(requested.upload_url, bytes, contentType);
|
|
276
|
+
return requestRootTaleApi({
|
|
277
|
+
method: "POST",
|
|
278
|
+
pathname: "/v1/cms/media/uploads/complete",
|
|
279
|
+
body: {
|
|
280
|
+
site_id: input.siteId,
|
|
281
|
+
r2_key: requested.r2_key,
|
|
282
|
+
original_name: basename(filePath),
|
|
283
|
+
content_type: contentType,
|
|
284
|
+
size_bytes: bytes.byteLength,
|
|
285
|
+
alt: input.alt,
|
|
286
|
+
caption: input.caption
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
function inferContentType(filePath) {
|
|
291
|
+
switch (extname(filePath).toLowerCase()) {
|
|
292
|
+
case ".jpg":
|
|
293
|
+
case ".jpeg":
|
|
294
|
+
return "image/jpeg";
|
|
295
|
+
case ".png":
|
|
296
|
+
return "image/png";
|
|
297
|
+
case ".webp":
|
|
298
|
+
return "image/webp";
|
|
299
|
+
case ".gif":
|
|
300
|
+
return "image/gif";
|
|
301
|
+
case ".pdf":
|
|
302
|
+
return "application/pdf";
|
|
303
|
+
default:
|
|
304
|
+
return void 0;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// src/automation-tools.ts
|
|
309
|
+
async function callAutomationTool(name, args) {
|
|
310
|
+
switch (name) {
|
|
311
|
+
case "listManagedCmsPosts": {
|
|
312
|
+
const input = ListManagedPostsInput.parse(args);
|
|
313
|
+
return requestRootTaleApi({
|
|
314
|
+
method: "GET",
|
|
315
|
+
pathname: "/v1/cms/posts",
|
|
316
|
+
query: optionalQuery({
|
|
317
|
+
site_id: input.siteId,
|
|
318
|
+
limit: input.limit,
|
|
319
|
+
type: input.type,
|
|
320
|
+
status: input.status,
|
|
321
|
+
cursor: input.cursor
|
|
322
|
+
})
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
case "createCmsPost": {
|
|
326
|
+
const input = CreatePostInput.parse(args);
|
|
327
|
+
return requestRootTaleApi({
|
|
328
|
+
method: "POST",
|
|
329
|
+
pathname: "/v1/cms/posts",
|
|
330
|
+
body: {
|
|
331
|
+
site_id: input.siteId,
|
|
332
|
+
type: input.type,
|
|
333
|
+
title: input.title,
|
|
334
|
+
slug: input.slug,
|
|
335
|
+
body_json: input.bodyJson,
|
|
336
|
+
excerpt: input.excerpt,
|
|
337
|
+
featured_media_id: input.featuredMediaId,
|
|
338
|
+
publish: input.publish,
|
|
339
|
+
scheduled_at: input.scheduledAt,
|
|
340
|
+
category_ids: input.categoryIds,
|
|
341
|
+
tag_ids: input.tagIds
|
|
342
|
+
}
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
case "updateCmsPost": {
|
|
346
|
+
const input = UpdatePostInput.parse(args);
|
|
347
|
+
return requestRootTaleApi({
|
|
348
|
+
method: "PATCH",
|
|
349
|
+
pathname: `/v1/cms/posts/${encodeURIComponent(input.postId)}`,
|
|
350
|
+
body: {
|
|
351
|
+
site_id: input.siteId,
|
|
352
|
+
title: input.title,
|
|
353
|
+
slug: input.slug,
|
|
354
|
+
body_json: input.bodyJson,
|
|
355
|
+
excerpt: input.excerpt,
|
|
356
|
+
featured_media_id: input.featuredMediaId,
|
|
357
|
+
scheduled_at: input.scheduledAt
|
|
358
|
+
}
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
case "publishCmsPost":
|
|
362
|
+
case "unpublishCmsPost": {
|
|
363
|
+
const input = PostLifecycleInput.parse(args);
|
|
364
|
+
const action = name === "publishCmsPost" ? "publish" : "unpublish";
|
|
365
|
+
return requestRootTaleApi({
|
|
366
|
+
method: "POST",
|
|
367
|
+
pathname: `/v1/cms/posts/${encodeURIComponent(input.postId)}/${action}`,
|
|
368
|
+
body: { site_id: input.siteId }
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
case "setCmsPostTerms": {
|
|
372
|
+
const input = SetTermsInput.parse(args);
|
|
373
|
+
return requestRootTaleApi({
|
|
374
|
+
method: "PATCH",
|
|
375
|
+
pathname: `/v1/cms/posts/${encodeURIComponent(input.postId)}/terms`,
|
|
376
|
+
body: {
|
|
377
|
+
site_id: input.siteId,
|
|
378
|
+
taxonomy: input.taxonomy,
|
|
379
|
+
term_ids: input.termIds
|
|
380
|
+
}
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
case "listCmsMedia": {
|
|
384
|
+
const input = ListMediaInput.parse(args);
|
|
385
|
+
return requestRootTaleApi({
|
|
386
|
+
method: "GET",
|
|
387
|
+
pathname: "/v1/cms/media",
|
|
388
|
+
query: optionalQuery({
|
|
389
|
+
site_id: input.siteId,
|
|
390
|
+
limit: input.limit,
|
|
391
|
+
offset: input.offset
|
|
392
|
+
})
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
case "uploadCmsMedia":
|
|
396
|
+
return uploadCmsMedia(args);
|
|
397
|
+
case "updateCmsMedia": {
|
|
398
|
+
const input = UpdateMediaInput.parse(args);
|
|
399
|
+
return requestRootTaleApi({
|
|
400
|
+
method: "PATCH",
|
|
401
|
+
pathname: `/v1/cms/media/${encodeURIComponent(input.mediaId)}`,
|
|
402
|
+
body: {
|
|
403
|
+
site_id: input.siteId,
|
|
404
|
+
alt: input.alt,
|
|
405
|
+
caption: input.caption
|
|
406
|
+
}
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
case "deleteCmsMedia": {
|
|
410
|
+
const input = DeleteMediaInput.parse(args);
|
|
411
|
+
return requestRootTaleApi({
|
|
412
|
+
method: "DELETE",
|
|
413
|
+
pathname: `/v1/cms/media/${encodeURIComponent(input.mediaId)}`,
|
|
414
|
+
query: optionalQuery({ site_id: input.siteId })
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
default:
|
|
418
|
+
return assertNever(name);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
function optionalQuery(values) {
|
|
422
|
+
return Object.fromEntries(
|
|
423
|
+
Object.entries(values).filter((entry) => entry[1] !== void 0).map(([key, value]) => [key, String(value)])
|
|
424
|
+
);
|
|
425
|
+
}
|
|
426
|
+
function assertNever(value) {
|
|
427
|
+
throw new CmsAutomationError(`Unknown automation tool: ${String(value)}`);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// src/cli.ts
|
|
431
|
+
function createCmsCli() {
|
|
432
|
+
const cli = new Command().name("roottale-cms").description("RootTale CMS \uAE00\xB7\uC378\uB124\uC77C\xB7\uBCF8\uBB38 \uC774\uBBF8\uC9C0 \uC790\uB3D9\uD654 CLI");
|
|
433
|
+
registerPostCommands(cli);
|
|
434
|
+
registerMediaCommands(cli);
|
|
435
|
+
return cli;
|
|
436
|
+
}
|
|
437
|
+
async function runCmsCli(argv) {
|
|
438
|
+
try {
|
|
439
|
+
await createCmsCli().parseAsync([
|
|
440
|
+
argv[0] ?? "node",
|
|
441
|
+
"roottale-cms",
|
|
442
|
+
...argv.slice(3)
|
|
443
|
+
]);
|
|
444
|
+
} catch (error) {
|
|
445
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
446
|
+
process.stderr.write(`${message}
|
|
447
|
+
`);
|
|
448
|
+
process.exitCode = 1;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
function registerPostCommands(cli) {
|
|
452
|
+
const posts = cli.command("posts").description("CMS \uAE00 \uC790\uB3D9\uD654");
|
|
453
|
+
posts.command("list").description("\uCD08\uC548\xB7\uC608\uC57D\xB7\uBC1C\uD589 \uAE00 \uBAA9\uB85D \uC870\uD68C").option("--site-id <id>", "\uC0AC\uC774\uD2B8 ID").option("--limit <number>", "\uC870\uD68C \uAC1C\uC218", integer, 20).option("--cursor <cursor>", "\uB2E4\uC74C \uD398\uC774\uC9C0 \uCEE4\uC11C").option("--type <type>", "post \uB610\uB294 page").option("--status <status>", "draft, published, scheduled, private").action(async (options) => {
|
|
454
|
+
await run("listManagedCmsPosts", options);
|
|
455
|
+
});
|
|
456
|
+
posts.command("create").description("Tiptap JSON \uBCF8\uBB38\uC73C\uB85C \uC0C8 \uAE00 \uC0DD\uC131").requiredOption("--title <title>", "\uAE00 \uC81C\uBAA9").requiredOption("--slug <slug>", "URL \uC2AC\uB7EC\uADF8").requiredOption("--body-file <path>", "Tiptap \uBCF8\uBB38 JSON \uD30C\uC77C").option("--site-id <id>", "\uC0AC\uC774\uD2B8 ID").option("--type <type>", "post \uB610\uB294 page", "post").option("--excerpt <text>", "\uC694\uC57D").option("--featured-media-id <id>", "\uC378\uB124\uC77C \uBBF8\uB514\uC5B4 ID").option("--publish", "\uC989\uC2DC \uBC1C\uD589").option("--scheduled-at <iso>", "\uC608\uC57D \uBC1C\uD589 ISO \uC2DC\uAC01").option("--category-ids <ids>", "\uC27C\uD45C\uB85C \uAD6C\uBD84\uD55C \uCE74\uD14C\uACE0\uB9AC ID").option("--tag-ids <ids>", "\uC27C\uD45C\uB85C \uAD6C\uBD84\uD55C \uD0DC\uADF8 ID").action(async (options) => {
|
|
457
|
+
await run("createCmsPost", {
|
|
458
|
+
...options,
|
|
459
|
+
bodyJson: await readJsonObject(options.bodyFile),
|
|
460
|
+
categoryIds: commaSeparated(options.categoryIds),
|
|
461
|
+
tagIds: commaSeparated(options.tagIds),
|
|
462
|
+
bodyFile: void 0
|
|
463
|
+
});
|
|
464
|
+
});
|
|
465
|
+
posts.command("update").description("\uAE30\uC874 \uAE00\uC758 \uC77C\uBD80 \uD544\uB4DC \uC218\uC815").argument("<post-id>", "\uAE00 ID").option("--site-id <id>", "\uC0AC\uC774\uD2B8 ID").option("--title <title>", "\uAE00 \uC81C\uBAA9").option("--slug <slug>", "URL \uC2AC\uB7EC\uADF8").option("--body-file <path>", "Tiptap \uBCF8\uBB38 JSON \uD30C\uC77C").option("--excerpt <text>", "\uC694\uC57D").option("--featured-media-id <id>", "\uC378\uB124\uC77C \uBBF8\uB514\uC5B4 ID").option("--clear-featured-media", "\uC378\uB124\uC77C \uC5F0\uACB0 \uD574\uC81C").option("--scheduled-at <iso>", "\uC608\uC57D \uBC1C\uD589 ISO \uC2DC\uAC01").option("--clear-schedule", "\uC608\uC57D \uD574\uC81C").action(async (postId, options) => {
|
|
466
|
+
await run("updateCmsPost", {
|
|
467
|
+
postId,
|
|
468
|
+
siteId: options.siteId,
|
|
469
|
+
title: options.title,
|
|
470
|
+
slug: options.slug,
|
|
471
|
+
bodyJson: options.bodyFile ? await readJsonObject(options.bodyFile) : void 0,
|
|
472
|
+
excerpt: options.excerpt,
|
|
473
|
+
featuredMediaId: options.clearFeaturedMedia ? null : options.featuredMediaId,
|
|
474
|
+
scheduledAt: options.clearSchedule ? null : options.scheduledAt
|
|
475
|
+
});
|
|
476
|
+
});
|
|
477
|
+
lifecycle(posts, "publish", "\uAE00\uC744 \uC989\uC2DC \uBC1C\uD589", "publishCmsPost");
|
|
478
|
+
lifecycle(posts, "unpublish", "\uBC1C\uD589 \uAE00\uC744 \uCD08\uC548\uC73C\uB85C \uC804\uD658", "unpublishCmsPost");
|
|
479
|
+
posts.command("set-terms").description("\uAE00\uC758 \uCE74\uD14C\uACE0\uB9AC \uB610\uB294 \uD0DC\uADF8 \uC804\uCCB4 \uAD50\uCCB4").argument("<post-id>", "\uAE00 ID").requiredOption("--taxonomy <type>", "category \uB610\uB294 tag").requiredOption("--term-ids <ids>", "\uC27C\uD45C\uB85C \uAD6C\uBD84\uD55C term ID").option("--site-id <id>", "\uC0AC\uC774\uD2B8 ID").action(async (postId, options) => {
|
|
480
|
+
await run("setCmsPostTerms", {
|
|
481
|
+
postId,
|
|
482
|
+
siteId: options.siteId,
|
|
483
|
+
taxonomy: options.taxonomy,
|
|
484
|
+
termIds: commaSeparated(options.termIds) ?? []
|
|
485
|
+
});
|
|
486
|
+
});
|
|
487
|
+
}
|
|
488
|
+
function registerMediaCommands(cli) {
|
|
489
|
+
const media = cli.command("media").description("CMS \uBBF8\uB514\uC5B4 \uC790\uB3D9\uD654");
|
|
490
|
+
media.command("list").description("\uBBF8\uB514\uC5B4 \uB77C\uC774\uBE0C\uB7EC\uB9AC \uC870\uD68C").option("--site-id <id>", "\uC0AC\uC774\uD2B8 ID").option("--limit <number>", "\uC870\uD68C \uAC1C\uC218", integer, 20).option("--offset <number>", "\uC870\uD68C \uC2DC\uC791 \uC704\uCE58", integer, 0).action(async (options) => {
|
|
491
|
+
await run("listCmsMedia", options);
|
|
492
|
+
});
|
|
493
|
+
media.command("upload").description("\uB85C\uCEEC \uD30C\uC77C\uC744 \uC5C5\uB85C\uB4DC\uD558\uACE0 CMS \uBBF8\uB514\uC5B4\uB85C \uB4F1\uB85D").argument("<file>", "jpg, png, webp, gif \uB610\uB294 pdf \uD30C\uC77C").option("--site-id <id>", "\uC0AC\uC774\uD2B8 ID").option("--content-type <type>", "MIME type \uC9C1\uC811 \uC9C0\uC815").option("--alt <text>", "\uB300\uCCB4 \uD14D\uC2A4\uD2B8").option("--caption <text>", "\uCEA1\uC158").action(async (filePath, options) => {
|
|
494
|
+
await run("uploadCmsMedia", { filePath, ...options });
|
|
495
|
+
});
|
|
496
|
+
media.command("update").description("\uBBF8\uB514\uC5B4 \uB300\uCCB4 \uD14D\uC2A4\uD2B8 \uB610\uB294 \uCEA1\uC158 \uC218\uC815").argument("<media-id>", "\uBBF8\uB514\uC5B4 ID").option("--site-id <id>", "\uC0AC\uC774\uD2B8 ID").option("--alt <text>", "\uB300\uCCB4 \uD14D\uC2A4\uD2B8").option("--caption <text>", "\uCEA1\uC158").action(async (mediaId, options) => {
|
|
497
|
+
await run("updateCmsMedia", { mediaId, ...options });
|
|
498
|
+
});
|
|
499
|
+
media.command("delete").description("\uBBF8\uB514\uC5B4 \uD30C\uC77C\uACFC \uB77C\uC774\uBE0C\uB7EC\uB9AC \uD56D\uBAA9 \uC0AD\uC81C").argument("<media-id>", "\uBBF8\uB514\uC5B4 ID").option("--site-id <id>", "\uC0AC\uC774\uD2B8 ID").action(async (mediaId, options) => {
|
|
500
|
+
await run("deleteCmsMedia", { mediaId, ...options });
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
function lifecycle(posts, commandName, description, toolName) {
|
|
504
|
+
posts.command(commandName).description(description).argument("<post-id>", "\uAE00 ID").option("--site-id <id>", "\uC0AC\uC774\uD2B8 ID").action(async (postId, options) => {
|
|
505
|
+
await run(toolName, { postId, ...options });
|
|
506
|
+
});
|
|
507
|
+
}
|
|
508
|
+
async function run(name, args) {
|
|
509
|
+
const definedArgs = Object.fromEntries(
|
|
510
|
+
Object.entries(args).filter(([, value]) => value !== void 0)
|
|
511
|
+
);
|
|
512
|
+
const result = await callAutomationTool(name, definedArgs);
|
|
513
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}
|
|
514
|
+
`);
|
|
515
|
+
}
|
|
516
|
+
async function readJsonObject(filePath) {
|
|
517
|
+
const parsed = JSON.parse(await readFile2(filePath, "utf8"));
|
|
518
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
519
|
+
throw new InvalidArgumentError("\uBCF8\uBB38 \uD30C\uC77C\uC740 Tiptap JSON \uAC1D\uCCB4\uC5EC\uC57C \uD569\uB2C8\uB2E4.");
|
|
520
|
+
}
|
|
521
|
+
return parsed;
|
|
522
|
+
}
|
|
523
|
+
function commaSeparated(value) {
|
|
524
|
+
if (value === void 0) return void 0;
|
|
525
|
+
return value.split(",").map((item) => item.trim()).filter(Boolean);
|
|
526
|
+
}
|
|
527
|
+
function integer(value) {
|
|
528
|
+
const parsed = Number.parseInt(value, 10);
|
|
529
|
+
if (!Number.isInteger(parsed) || parsed < 0) {
|
|
530
|
+
throw new InvalidArgumentError("0 \uC774\uC0C1\uC758 \uC815\uC218\uB97C \uC785\uB825\uD558\uC138\uC694.");
|
|
531
|
+
}
|
|
532
|
+
return parsed;
|
|
533
|
+
}
|
|
534
|
+
|
|
6
535
|
// src/server.ts
|
|
7
536
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
8
537
|
|
|
@@ -13,10 +542,10 @@ import {
|
|
|
13
542
|
ListToolsRequestSchema,
|
|
14
543
|
McpError
|
|
15
544
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
16
|
-
import { z } from "zod";
|
|
545
|
+
import { z as z3 } from "zod";
|
|
17
546
|
|
|
18
547
|
// src/docs.ts
|
|
19
|
-
import { readdir, readFile } from "fs/promises";
|
|
548
|
+
import { readdir, readFile as readFile3 } from "fs/promises";
|
|
20
549
|
import path from "path";
|
|
21
550
|
import { fileURLToPath } from "url";
|
|
22
551
|
var PKG_ROOT = fileURLToPath(new URL("..", import.meta.url));
|
|
@@ -53,7 +582,7 @@ async function listDocs() {
|
|
|
53
582
|
const files = (await walkFiles(DOCS_ROOT)).filter((f) => f.endsWith(".md"));
|
|
54
583
|
return Promise.all(
|
|
55
584
|
files.map(async (rel) => {
|
|
56
|
-
const content = await
|
|
585
|
+
const content = await readFile3(path.join(DOCS_ROOT, rel), "utf8");
|
|
57
586
|
const fm = parseFrontmatter(content);
|
|
58
587
|
return { path: rel, title: fm.title || rel, description: fm.description };
|
|
59
588
|
})
|
|
@@ -63,7 +592,7 @@ async function readDoc(relPath) {
|
|
|
63
592
|
const resolved = path.resolve(DOCS_ROOT, relPath);
|
|
64
593
|
if (!resolved.startsWith(DOCS_ROOT + path.sep)) return null;
|
|
65
594
|
try {
|
|
66
|
-
return await
|
|
595
|
+
return await readFile3(resolved, "utf8");
|
|
67
596
|
} catch {
|
|
68
597
|
return null;
|
|
69
598
|
}
|
|
@@ -87,7 +616,7 @@ async function readNextjsExampleCode() {
|
|
|
87
616
|
const files = await walkFiles(root);
|
|
88
617
|
const sections = await Promise.all(
|
|
89
618
|
files.map(async (rel) => {
|
|
90
|
-
const content = await
|
|
619
|
+
const content = await readFile3(path.join(root, rel), "utf8");
|
|
91
620
|
return `--- FILE: ${rel} ---
|
|
92
621
|
${content}`;
|
|
93
622
|
})
|
|
@@ -96,17 +625,16 @@ ${content}`;
|
|
|
96
625
|
}
|
|
97
626
|
|
|
98
627
|
// src/tools.ts
|
|
99
|
-
var
|
|
100
|
-
var
|
|
101
|
-
var
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
cursor: z.string().optional()
|
|
628
|
+
var ReadDocInput = z3.object({ path: z3.string().min(1) }).strict();
|
|
629
|
+
var SearchDocsInput = z3.object({ query: z3.string().min(1) }).strict();
|
|
630
|
+
var ListPostsInput = z3.object({
|
|
631
|
+
limit: z3.number().int().min(1).max(100).optional(),
|
|
632
|
+
type: z3.enum(["post", "page"]).optional(),
|
|
633
|
+
cursor: z3.string().optional()
|
|
106
634
|
}).strict();
|
|
107
|
-
var GetPostInput =
|
|
108
|
-
var GetSiteKnowledgeInput =
|
|
109
|
-
var
|
|
635
|
+
var GetPostInput = z3.object({ slugOrId: z3.string().min(1) }).strict();
|
|
636
|
+
var GetSiteKnowledgeInput = z3.object({ siteId: z3.string().optional() }).strict();
|
|
637
|
+
var DOCUMENTATION_TOOL_DEFINITIONS = [
|
|
110
638
|
{
|
|
111
639
|
name: "listRootTaleDocs",
|
|
112
640
|
description: "RootTale CMS \uD1B5\uD569 \uBB38\uC11C \uC804\uCCB4 \uBAA9\uB85D(\uACBD\uB85C\xB7\uC81C\uBAA9\xB7\uC124\uBA85)\uC744 \uBC18\uD658\uD569\uB2C8\uB2E4. RootTale \uC5F0\uB3D9 \uC791\uC5C5\uC744 \uC2DC\uC791\uD558\uAE30 \uC804 \uAC00\uC7A5 \uBA3C\uC800 \uD638\uCD9C\uD558\uC138\uC694.",
|
|
@@ -181,45 +709,28 @@ var TOOL_DEFINITIONS = [
|
|
|
181
709
|
}
|
|
182
710
|
}
|
|
183
711
|
];
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
ErrorCode.InvalidRequest,
|
|
189
|
-
"ROOTTALE_API_KEY \uD658\uACBD\uBCC0\uC218\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4. MCP \uC11C\uBC84 \uC124\uC815\uC758 env\uC5D0 rtlk_cust_* \uD0A4\uB97C \uCD94\uAC00\uD558\uC138\uC694 (\uBC1C\uAE09: \uC5B4\uB4DC\uBBFC \uC124\uC815 > \uC0AC\uC774\uD2B8 \uC5F0\uACB0 \uD0A4)."
|
|
190
|
-
);
|
|
191
|
-
}
|
|
192
|
-
const baseUrl = (process.env.ROOTTALE_API_BASE ?? DEFAULT_API_BASE).replace(/\/+$/, "");
|
|
193
|
-
return { apiKey, baseUrl };
|
|
194
|
-
}
|
|
195
|
-
async function fetchPublicApi(pathname, params) {
|
|
196
|
-
const { apiKey, baseUrl } = requireApiKey();
|
|
197
|
-
const url = new URL(`${baseUrl}${pathname}`);
|
|
198
|
-
for (const [key, value] of Object.entries(params ?? {})) {
|
|
199
|
-
url.searchParams.set(key, value);
|
|
200
|
-
}
|
|
201
|
-
const response = await fetch(url, {
|
|
202
|
-
headers: { authorization: `Bearer ${apiKey}` }
|
|
203
|
-
});
|
|
204
|
-
const body = await response.text();
|
|
205
|
-
if (!response.ok) {
|
|
206
|
-
throw new Error(`RootTale API ${response.status}: ${body.slice(0, 500)}`);
|
|
207
|
-
}
|
|
208
|
-
return JSON.parse(body);
|
|
209
|
-
}
|
|
712
|
+
var TOOL_DEFINITIONS = [
|
|
713
|
+
...DOCUMENTATION_TOOL_DEFINITIONS,
|
|
714
|
+
...AUTOMATION_TOOL_DEFINITIONS
|
|
715
|
+
];
|
|
210
716
|
function textResponse(text) {
|
|
211
717
|
return { content: [{ type: "text", text }] };
|
|
212
718
|
}
|
|
213
719
|
function jsonResponse(value) {
|
|
214
720
|
return textResponse(JSON.stringify(value, null, 2));
|
|
215
721
|
}
|
|
216
|
-
function registerTools(
|
|
217
|
-
|
|
722
|
+
function registerTools(server) {
|
|
723
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
218
724
|
tools: TOOL_DEFINITIONS.map((t) => ({ ...t }))
|
|
219
725
|
}));
|
|
220
|
-
|
|
726
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
221
727
|
const args = request.params.arguments ?? {};
|
|
222
728
|
try {
|
|
729
|
+
if (isAutomationToolName(request.params.name)) {
|
|
730
|
+
return jsonResponse(
|
|
731
|
+
await callAutomationTool(request.params.name, args)
|
|
732
|
+
);
|
|
733
|
+
}
|
|
223
734
|
switch (request.params.name) {
|
|
224
735
|
case "listRootTaleDocs":
|
|
225
736
|
return jsonResponse(await listDocs());
|
|
@@ -246,14 +757,21 @@ function registerTools(server2) {
|
|
|
246
757
|
if (input.limit) params.limit = String(input.limit);
|
|
247
758
|
if (input.type) params.type = input.type;
|
|
248
759
|
if (input.cursor) params.cursor = input.cursor;
|
|
249
|
-
return jsonResponse(
|
|
760
|
+
return jsonResponse(
|
|
761
|
+
await requestRootTaleApi({
|
|
762
|
+
method: "GET",
|
|
763
|
+
pathname: "/v1/cms/public/posts",
|
|
764
|
+
query: params
|
|
765
|
+
})
|
|
766
|
+
);
|
|
250
767
|
}
|
|
251
768
|
case "getPublishedPost": {
|
|
252
769
|
const input = GetPostInput.parse(args);
|
|
253
770
|
return jsonResponse(
|
|
254
|
-
await
|
|
255
|
-
|
|
256
|
-
|
|
771
|
+
await requestRootTaleApi({
|
|
772
|
+
method: "GET",
|
|
773
|
+
pathname: `/v1/cms/public/posts/${encodeURIComponent(input.slugOrId)}`
|
|
774
|
+
})
|
|
257
775
|
);
|
|
258
776
|
}
|
|
259
777
|
case "getSiteKnowledge": {
|
|
@@ -261,7 +779,11 @@ function registerTools(server2) {
|
|
|
261
779
|
const params = {};
|
|
262
780
|
if (input.siteId) params.site_id = input.siteId;
|
|
263
781
|
return jsonResponse(
|
|
264
|
-
await
|
|
782
|
+
await requestRootTaleApi({
|
|
783
|
+
method: "GET",
|
|
784
|
+
pathname: "/v1/cms/public/site-knowledge",
|
|
785
|
+
query: params
|
|
786
|
+
})
|
|
265
787
|
);
|
|
266
788
|
}
|
|
267
789
|
default:
|
|
@@ -279,10 +801,10 @@ function registerTools(server2) {
|
|
|
279
801
|
}
|
|
280
802
|
|
|
281
803
|
// src/server.ts
|
|
282
|
-
var VERSION = true ? "0.
|
|
804
|
+
var VERSION = true ? "0.44.0" : "dev";
|
|
283
805
|
var SERVER_INSTRUCTIONS = `
|
|
284
|
-
roottale-cms-mcp\uB294 RootTale CMS\uB97C \uC678\uBD80 \uC0AC\uC774\uD2B8(\uC8FC\uB85C Next.js)\uC5D0 \uC5F0\uB3D9\uD558\
|
|
285
|
-
\
|
|
806
|
+
roottale-cms-mcp\uB294 RootTale CMS\uB97C \uC678\uBD80 \uC0AC\uC774\uD2B8(\uC8FC\uB85C Next.js)\uC5D0 \uC5F0\uB3D9\uD558\uACE0
|
|
807
|
+
\uAE00\xB7\uC378\uB124\uC77C\xB7\uBCF8\uBB38 \uC774\uBBF8\uC9C0\uB97C \uC790\uB3D9\uD654\uD558\uAE30 \uC704\uD55C \uBB38\uC11C\xB7\uC608\uC2DC \uCF54\uB4DC\xB7API tool\uC744 \uC81C\uACF5\uD569\uB2C8\uB2E4.
|
|
286
808
|
|
|
287
809
|
\uC9C0\uCF1C\uC57C \uD560 \uADDC\uCE59:
|
|
288
810
|
- RootTale \uC5F0\uB3D9 \uAD00\uB828 \uC791\uC5C5\uC740 \uAC00\uC7A5 \uBA3C\uC800 listRootTaleDocs\uB97C \uD638\uCD9C\uD574 \uBB38\uC11C \uBAA9\uB85D\uC744 \uD30C\uC545\uD558\uC138\uC694.
|
|
@@ -290,19 +812,28 @@ roottale-cms-mcp\uB294 RootTale CMS\uB97C \uC678\uBD80 \uC0AC\uC774\uD2B8(\uC8FC
|
|
|
290
812
|
\uCC38\uACE0\uD55C \uD6C4 \uADF8 \uD328\uD134\uC744 \uB530\uB77C \uC791\uC131\uD558\uC138\uC694.
|
|
291
813
|
- API \uD0A4(rtlk_cust_*)\uB294 \uC11C\uBC84 \uC804\uC6A9\uC785\uB2C8\uB2E4. NEXT_PUBLIC_* \uB4F1 \uBE0C\uB77C\uC6B0\uC800\uB85C \uB178\uCD9C\uB418\uB294
|
|
292
814
|
\uD658\uACBD\uBCC0\uC218\uC5D0 \uC808\uB300 \uB123\uC9C0 \uB9C8\uC138\uC694.
|
|
815
|
+
- \uAE00\uC4F0\uAE30 \uC804\uC5D0 getSiteKnowledge\uB85C \uBE0C\uB79C\uB4DC \uBCF4\uC774\uC2A4\uC640 \uC6A9\uC5B4 \uADDC\uCE59\uC744 \uD655\uC778\uD558\uC138\uC694.
|
|
816
|
+
- \uC0C8 \uAE00\uC740 \uAE30\uBCF8\uC801\uC73C\uB85C draft\uB85C \uB9CC\uB4E4\uACE0, \uC0AC\uC6A9\uC790\uAC00 \uC989\uC2DC \uBC1C\uD589\uC744 \uBA85\uC2DC\uD588\uC744 \uB54C\uB9CC
|
|
817
|
+
publish=true \uB610\uB294 publishCmsPost\uB97C \uC0AC\uC6A9\uD558\uC138\uC694.
|
|
818
|
+
- \uC774\uBBF8\uC9C0\uB294 uploadCmsMedia\uB85C \uBA3C\uC800 \uB4F1\uB85D\uD55C \uB4A4 \uBC18\uD658\uB41C id\uB97C featuredMediaId\uC5D0,
|
|
819
|
+
\uBC18\uD658\uB41C URL\uC744 Tiptap image \uB178\uB4DC\uC758 attrs.src\uC5D0 \uC0AC\uC6A9\uD558\uC138\uC694.
|
|
293
820
|
- \uC774\uBBF8 \uD559\uC2B5\uB41C \uB0B4\uC6A9\uC774\uB354\uB77C\uB3C4 \uBCF8 \uC11C\uBC84\uC758 \uBB38\uC11C\uB85C \uB354\uBE14\uCCB4\uD06C \uD6C4 \uC791\uC5C5\uD558\uC138\uC694.
|
|
294
821
|
`.trim();
|
|
295
822
|
function createServer() {
|
|
296
|
-
const
|
|
823
|
+
const server = new Server(
|
|
297
824
|
{ name: "roottale-cms", version: VERSION },
|
|
298
825
|
{ capabilities: { tools: {} }, instructions: SERVER_INSTRUCTIONS }
|
|
299
826
|
);
|
|
300
|
-
registerTools(
|
|
301
|
-
return
|
|
827
|
+
registerTools(server);
|
|
828
|
+
return server;
|
|
302
829
|
}
|
|
303
830
|
|
|
304
831
|
// src/index.ts
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
832
|
+
if (process.argv[2] === "cli") {
|
|
833
|
+
await runCmsCli(process.argv);
|
|
834
|
+
} else {
|
|
835
|
+
const server = createServer();
|
|
836
|
+
const transport = new StdioServerTransport();
|
|
837
|
+
await server.connect(transport);
|
|
838
|
+
}
|
|
308
839
|
//# sourceMappingURL=index.js.map
|