headlesshost-mcp-server 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 +193 -0
- package/build/index.d.ts +3 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +1766 -0
- package/build/index.js.map +1 -0
- package/package.json +45 -0
package/build/index.js
ADDED
|
@@ -0,0 +1,1766 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Suppress console output during dotenv loading
|
|
3
|
+
const originalConsoleLog = console.log;
|
|
4
|
+
console.log = () => { };
|
|
5
|
+
import dotenv from "dotenv";
|
|
6
|
+
dotenv.config();
|
|
7
|
+
// Restore console.log for debugging purposes
|
|
8
|
+
console.log = originalConsoleLog;
|
|
9
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
10
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
11
|
+
import { z } from "zod";
|
|
12
|
+
import axios from "axios";
|
|
13
|
+
// Configuration
|
|
14
|
+
const API_BASE_URL = "https://api.headlesshost.com";
|
|
15
|
+
const API_KEY = process.env.HEADLESSHOST_API_KEY || "YOUR API KEY HERE";
|
|
16
|
+
// Create axios instance with default config
|
|
17
|
+
const apiClient = axios.create({
|
|
18
|
+
baseURL: API_BASE_URL,
|
|
19
|
+
headers: {
|
|
20
|
+
"Content-Type": "application/json",
|
|
21
|
+
...(API_KEY && { Authorization: `Bearer ${API_KEY}` }),
|
|
22
|
+
},
|
|
23
|
+
timeout: 30000,
|
|
24
|
+
});
|
|
25
|
+
const validClaims = [
|
|
26
|
+
"Administrator",
|
|
27
|
+
"PageCreator",
|
|
28
|
+
"PageEditor",
|
|
29
|
+
"PageDeleter",
|
|
30
|
+
"PageMover",
|
|
31
|
+
"SectionCreator",
|
|
32
|
+
"SectionEditor",
|
|
33
|
+
"SectionDeleter",
|
|
34
|
+
"SectionMover",
|
|
35
|
+
"ContentDesigner",
|
|
36
|
+
"Publisher",
|
|
37
|
+
"BusinessDeleter",
|
|
38
|
+
"BusinessEditor",
|
|
39
|
+
"BusinessCreator",
|
|
40
|
+
"PublishApproval",
|
|
41
|
+
"PublishDeleter",
|
|
42
|
+
"Super",
|
|
43
|
+
"StageCreator",
|
|
44
|
+
"StageDeleter",
|
|
45
|
+
"SiteMerger",
|
|
46
|
+
"CatalogCreator",
|
|
47
|
+
"CatalogEditor",
|
|
48
|
+
"CatalogDeleter",
|
|
49
|
+
"BusinessUserCreator",
|
|
50
|
+
"BusinessUserEditor",
|
|
51
|
+
//wrap
|
|
52
|
+
"BusinessUserDeleter",
|
|
53
|
+
];
|
|
54
|
+
// Create MCP server
|
|
55
|
+
const server = new McpServer({
|
|
56
|
+
name: "headlesshost-tools-server",
|
|
57
|
+
version: "1.0.0",
|
|
58
|
+
capabilities: {
|
|
59
|
+
tools: {},
|
|
60
|
+
resources: {},
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
// Helper function to handle API errors
|
|
64
|
+
function handleApiError(error) {
|
|
65
|
+
if (error.response) {
|
|
66
|
+
return `API Error ${error.response.status}: ${error.response.data?.message || error.response.statusText}`;
|
|
67
|
+
}
|
|
68
|
+
else if (error.request) {
|
|
69
|
+
return "Network Error: Unable to reach API server";
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
return `Error: ${error.message}`;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
// ========== GENERAL TOOLS ENDPOINTS ==========
|
|
76
|
+
// Ping - Test authentication and connection
|
|
77
|
+
server.registerTool("ping", {
|
|
78
|
+
title: "Ping API",
|
|
79
|
+
description: "Test authentication and connection to the Headlesshost API",
|
|
80
|
+
inputSchema: {},
|
|
81
|
+
}, async () => {
|
|
82
|
+
try {
|
|
83
|
+
const response = await apiClient.get("/tools/ping");
|
|
84
|
+
return {
|
|
85
|
+
content: [
|
|
86
|
+
{
|
|
87
|
+
type: "text",
|
|
88
|
+
text: JSON.stringify(response.data, null, 2),
|
|
89
|
+
},
|
|
90
|
+
],
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
return {
|
|
95
|
+
content: [
|
|
96
|
+
{
|
|
97
|
+
type: "text",
|
|
98
|
+
text: handleApiError(error),
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
isError: true,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
// Health - Check API health status
|
|
106
|
+
server.registerTool("health", {
|
|
107
|
+
title: "Health Check",
|
|
108
|
+
description: "Check the health status of the Headlesshost API",
|
|
109
|
+
inputSchema: {},
|
|
110
|
+
}, async () => {
|
|
111
|
+
try {
|
|
112
|
+
const response = await apiClient.get("/tools/health");
|
|
113
|
+
return {
|
|
114
|
+
content: [
|
|
115
|
+
{
|
|
116
|
+
type: "text",
|
|
117
|
+
text: JSON.stringify(response.data, null, 2),
|
|
118
|
+
},
|
|
119
|
+
],
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
return {
|
|
124
|
+
content: [
|
|
125
|
+
{
|
|
126
|
+
type: "text",
|
|
127
|
+
text: handleApiError(error),
|
|
128
|
+
},
|
|
129
|
+
],
|
|
130
|
+
isError: true,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
// Get Reference Data
|
|
135
|
+
server.registerTool("get_ref_data", {
|
|
136
|
+
title: "Get Reference Data",
|
|
137
|
+
description: "Get system reference data and lookups",
|
|
138
|
+
inputSchema: {
|
|
139
|
+
category: z.string().optional().describe("Reference data category to filter by"),
|
|
140
|
+
},
|
|
141
|
+
}, async ({ category }) => {
|
|
142
|
+
try {
|
|
143
|
+
const params = new URLSearchParams();
|
|
144
|
+
if (category)
|
|
145
|
+
params.append("category", category);
|
|
146
|
+
const response = await apiClient.get(`/tools/system/refdata?${params}`);
|
|
147
|
+
return {
|
|
148
|
+
content: [
|
|
149
|
+
{
|
|
150
|
+
type: "text",
|
|
151
|
+
text: JSON.stringify(response.data, null, 2),
|
|
152
|
+
},
|
|
153
|
+
],
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
return {
|
|
158
|
+
content: [
|
|
159
|
+
{
|
|
160
|
+
type: "text",
|
|
161
|
+
text: handleApiError(error),
|
|
162
|
+
},
|
|
163
|
+
],
|
|
164
|
+
isError: true,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
// ========== MEMBERSHIP MANAGEMENT TOOLS ==========
|
|
169
|
+
// Register User
|
|
170
|
+
server.registerTool("register_user", {
|
|
171
|
+
title: "Register User",
|
|
172
|
+
description: "Register a new user in the system with account creation",
|
|
173
|
+
inputSchema: {
|
|
174
|
+
email: z.string().email().describe("User email address"),
|
|
175
|
+
password: z.string().describe("User password"),
|
|
176
|
+
firstName: z.string().optional().describe("User first name"),
|
|
177
|
+
lastName: z.string().optional().describe("User last name"),
|
|
178
|
+
accountName: z.string().optional().describe("Account name to create"),
|
|
179
|
+
},
|
|
180
|
+
}, async ({ email, password, firstName, lastName, accountName }) => {
|
|
181
|
+
try {
|
|
182
|
+
const payload = { email, password, firstName, lastName, accountName };
|
|
183
|
+
const response = await apiClient.post("/tools/membership/register", payload);
|
|
184
|
+
return {
|
|
185
|
+
content: [
|
|
186
|
+
{
|
|
187
|
+
type: "text",
|
|
188
|
+
text: JSON.stringify(response.data, null, 2),
|
|
189
|
+
},
|
|
190
|
+
],
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
catch (error) {
|
|
194
|
+
return {
|
|
195
|
+
content: [
|
|
196
|
+
{
|
|
197
|
+
type: "text",
|
|
198
|
+
text: handleApiError(error),
|
|
199
|
+
},
|
|
200
|
+
],
|
|
201
|
+
isError: true,
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
// Create User
|
|
206
|
+
server.registerTool("create_user", {
|
|
207
|
+
title: "Create User",
|
|
208
|
+
description: "Create a new user in the current account",
|
|
209
|
+
inputSchema: {
|
|
210
|
+
email: z.string().email().describe("User email address"),
|
|
211
|
+
firstName: z.string().describe("User first name"),
|
|
212
|
+
lastName: z.string().describe("User last name"),
|
|
213
|
+
password: z.string().optional().describe("User password"),
|
|
214
|
+
claims: z
|
|
215
|
+
.union([z.string(), z.array(z.string())])
|
|
216
|
+
.optional()
|
|
217
|
+
.describe("User roles/claims (string or array of strings)"),
|
|
218
|
+
},
|
|
219
|
+
}, async ({ email, firstName, lastName, password, claims }) => {
|
|
220
|
+
try {
|
|
221
|
+
// Build payload object more carefully
|
|
222
|
+
const payload = {
|
|
223
|
+
email,
|
|
224
|
+
firstName,
|
|
225
|
+
lastName,
|
|
226
|
+
};
|
|
227
|
+
// Only add password if provided
|
|
228
|
+
if (password) {
|
|
229
|
+
payload.password = password;
|
|
230
|
+
}
|
|
231
|
+
// Only add claims if provided and convert to array format
|
|
232
|
+
if (claims !== undefined && claims !== null) {
|
|
233
|
+
if (typeof claims === "string") {
|
|
234
|
+
payload.claims = [claims];
|
|
235
|
+
}
|
|
236
|
+
else if (Array.isArray(claims) && claims.length > 0) {
|
|
237
|
+
payload.claims = claims;
|
|
238
|
+
}
|
|
239
|
+
// If claims is an empty array or invalid, don't include it in payload
|
|
240
|
+
}
|
|
241
|
+
console.error("Create user payload:", JSON.stringify(payload, null, 2)); // Debug log
|
|
242
|
+
const response = await apiClient.post("/tools/membership/users", payload);
|
|
243
|
+
return {
|
|
244
|
+
content: [
|
|
245
|
+
{
|
|
246
|
+
type: "text",
|
|
247
|
+
text: JSON.stringify(response.data, null, 2),
|
|
248
|
+
},
|
|
249
|
+
],
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
catch (error) {
|
|
253
|
+
return {
|
|
254
|
+
content: [
|
|
255
|
+
{
|
|
256
|
+
type: "text",
|
|
257
|
+
text: handleApiError(error),
|
|
258
|
+
},
|
|
259
|
+
],
|
|
260
|
+
isError: true,
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
});
|
|
264
|
+
// Get User
|
|
265
|
+
server.registerTool("get_user", {
|
|
266
|
+
title: "Get User",
|
|
267
|
+
description: "Get user details by ID",
|
|
268
|
+
inputSchema: {
|
|
269
|
+
id: z.string().describe("User ID"),
|
|
270
|
+
},
|
|
271
|
+
}, async ({ id }) => {
|
|
272
|
+
try {
|
|
273
|
+
const response = await apiClient.get(`/tools/membership/users/${id}`);
|
|
274
|
+
return {
|
|
275
|
+
content: [
|
|
276
|
+
{
|
|
277
|
+
type: "text",
|
|
278
|
+
text: JSON.stringify(response.data, null, 2),
|
|
279
|
+
},
|
|
280
|
+
],
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
catch (error) {
|
|
284
|
+
return {
|
|
285
|
+
content: [
|
|
286
|
+
{
|
|
287
|
+
type: "text",
|
|
288
|
+
text: handleApiError(error),
|
|
289
|
+
},
|
|
290
|
+
],
|
|
291
|
+
isError: true,
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
});
|
|
295
|
+
// Update User
|
|
296
|
+
server.registerTool("update_user", {
|
|
297
|
+
title: "Update User",
|
|
298
|
+
description: "Update user information",
|
|
299
|
+
inputSchema: {
|
|
300
|
+
id: z.string().describe("User ID"),
|
|
301
|
+
email: z.string().email().optional().describe("User email"),
|
|
302
|
+
firstName: z.string().optional().describe("First name"),
|
|
303
|
+
lastName: z.string().optional().describe("Last name"),
|
|
304
|
+
claims: z
|
|
305
|
+
.union([
|
|
306
|
+
z.enum(validClaims), // single claim
|
|
307
|
+
z.array(z.enum(validClaims)), // multiple claims
|
|
308
|
+
])
|
|
309
|
+
.optional()
|
|
310
|
+
.describe(`User roles/claims (choose from: ${validClaims.join(", ")})`),
|
|
311
|
+
},
|
|
312
|
+
}, async ({ id, email, firstName, lastName, claims }) => {
|
|
313
|
+
try {
|
|
314
|
+
const payload = {};
|
|
315
|
+
if (email)
|
|
316
|
+
payload.email = email;
|
|
317
|
+
if (firstName)
|
|
318
|
+
payload.firstName = firstName;
|
|
319
|
+
if (lastName)
|
|
320
|
+
payload.lastName = lastName;
|
|
321
|
+
if (claims !== undefined && claims !== null) {
|
|
322
|
+
// Normalize to array
|
|
323
|
+
payload.claims = Array.isArray(claims) ? claims : [claims];
|
|
324
|
+
}
|
|
325
|
+
const response = await apiClient.put(`/tools/membership/users/${id}`, payload);
|
|
326
|
+
return {
|
|
327
|
+
content: [
|
|
328
|
+
{
|
|
329
|
+
type: "text",
|
|
330
|
+
text: JSON.stringify(response.data, null, 2),
|
|
331
|
+
},
|
|
332
|
+
],
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
catch (error) {
|
|
336
|
+
return {
|
|
337
|
+
content: [
|
|
338
|
+
{
|
|
339
|
+
type: "text",
|
|
340
|
+
text: handleApiError(error),
|
|
341
|
+
},
|
|
342
|
+
],
|
|
343
|
+
isError: true,
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
});
|
|
347
|
+
// Delete User
|
|
348
|
+
server.registerTool("delete_user", {
|
|
349
|
+
title: "Delete User",
|
|
350
|
+
description: "Delete a user from the system",
|
|
351
|
+
inputSchema: {
|
|
352
|
+
id: z.string().describe("User ID"),
|
|
353
|
+
reason: z.string().optional().describe("Reason for deletion"),
|
|
354
|
+
},
|
|
355
|
+
}, async ({ id, reason }) => {
|
|
356
|
+
try {
|
|
357
|
+
const payload = { reason };
|
|
358
|
+
const response = await apiClient.delete(`/tools/membership/users/${id}`, {
|
|
359
|
+
data: payload,
|
|
360
|
+
});
|
|
361
|
+
return {
|
|
362
|
+
content: [
|
|
363
|
+
{
|
|
364
|
+
type: "text",
|
|
365
|
+
text: JSON.stringify(response.data, null, 2),
|
|
366
|
+
},
|
|
367
|
+
],
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
catch (error) {
|
|
371
|
+
return {
|
|
372
|
+
content: [
|
|
373
|
+
{
|
|
374
|
+
type: "text",
|
|
375
|
+
text: handleApiError(error),
|
|
376
|
+
},
|
|
377
|
+
],
|
|
378
|
+
isError: true,
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
});
|
|
382
|
+
// Get Account
|
|
383
|
+
server.registerTool("get_account", {
|
|
384
|
+
title: "Get Account",
|
|
385
|
+
description: "Get current account information",
|
|
386
|
+
inputSchema: {},
|
|
387
|
+
}, async () => {
|
|
388
|
+
try {
|
|
389
|
+
const response = await apiClient.get(`/tools/membership/account`);
|
|
390
|
+
return {
|
|
391
|
+
content: [
|
|
392
|
+
{
|
|
393
|
+
type: "text",
|
|
394
|
+
text: JSON.stringify(response.data, null, 2),
|
|
395
|
+
},
|
|
396
|
+
],
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
catch (error) {
|
|
400
|
+
return {
|
|
401
|
+
content: [
|
|
402
|
+
{
|
|
403
|
+
type: "text",
|
|
404
|
+
text: handleApiError(error),
|
|
405
|
+
},
|
|
406
|
+
],
|
|
407
|
+
isError: true,
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
});
|
|
411
|
+
// Update Account
|
|
412
|
+
server.registerTool("update_account", {
|
|
413
|
+
title: "Update Account",
|
|
414
|
+
description: "Update account information",
|
|
415
|
+
inputSchema: {
|
|
416
|
+
name: z.string().optional().describe("Account name"),
|
|
417
|
+
},
|
|
418
|
+
}, async ({ name }) => {
|
|
419
|
+
try {
|
|
420
|
+
const payload = {};
|
|
421
|
+
if (name)
|
|
422
|
+
payload.name = name;
|
|
423
|
+
const response = await apiClient.put("/tools/membership/account", payload);
|
|
424
|
+
return {
|
|
425
|
+
content: [
|
|
426
|
+
{
|
|
427
|
+
type: "text",
|
|
428
|
+
text: JSON.stringify(response.data, null, 2),
|
|
429
|
+
},
|
|
430
|
+
],
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
catch (error) {
|
|
434
|
+
return {
|
|
435
|
+
content: [
|
|
436
|
+
{
|
|
437
|
+
type: "text",
|
|
438
|
+
text: handleApiError(error),
|
|
439
|
+
},
|
|
440
|
+
],
|
|
441
|
+
isError: true,
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
});
|
|
445
|
+
// ========== FILE MANAGEMENT TOOLS ==========
|
|
446
|
+
// Upload User Profile Image
|
|
447
|
+
server.registerTool("upload_user_profile_image", {
|
|
448
|
+
title: "Upload User Profile Image",
|
|
449
|
+
description: "Upload a profile image for a user",
|
|
450
|
+
inputSchema: {
|
|
451
|
+
userId: z.string().describe("User ID"),
|
|
452
|
+
image: z.string().describe("Base64 encoded file data"),
|
|
453
|
+
},
|
|
454
|
+
}, async ({ userId, image }) => {
|
|
455
|
+
try {
|
|
456
|
+
const payload = { image };
|
|
457
|
+
const response = await apiClient.post(`/tools/files/users/${userId}/profile-image`, payload);
|
|
458
|
+
return {
|
|
459
|
+
content: [
|
|
460
|
+
{
|
|
461
|
+
type: "text",
|
|
462
|
+
text: JSON.stringify(response.data, null, 2),
|
|
463
|
+
},
|
|
464
|
+
],
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
catch (error) {
|
|
468
|
+
return {
|
|
469
|
+
content: [
|
|
470
|
+
{
|
|
471
|
+
type: "text",
|
|
472
|
+
text: handleApiError(error),
|
|
473
|
+
},
|
|
474
|
+
],
|
|
475
|
+
isError: true,
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
});
|
|
479
|
+
// Upload Staging Site File
|
|
480
|
+
server.registerTool("upload_staging_site_file", {
|
|
481
|
+
title: "Upload Staging Site File",
|
|
482
|
+
description: "Upload a file to a staging site",
|
|
483
|
+
inputSchema: {
|
|
484
|
+
contentSiteId: z.string().describe("Content Site ID"),
|
|
485
|
+
stagingSiteId: z.string().describe("Staging Site ID"),
|
|
486
|
+
file: z.string().describe("Base64 encoded file data or file path"),
|
|
487
|
+
filename: z.string().optional().describe("Original filename"),
|
|
488
|
+
mimetype: z.string().optional().describe("File MIME type"),
|
|
489
|
+
},
|
|
490
|
+
}, async ({ contentSiteId, stagingSiteId, file, filename, mimetype }) => {
|
|
491
|
+
try {
|
|
492
|
+
const payload = { file, filename, mimetype };
|
|
493
|
+
const response = await apiClient.post(`/tools/files/contentSite/${contentSiteId}/staging-sites/${stagingSiteId}/files`, payload);
|
|
494
|
+
return {
|
|
495
|
+
content: [
|
|
496
|
+
{
|
|
497
|
+
type: "text",
|
|
498
|
+
text: JSON.stringify(response.data, null, 2),
|
|
499
|
+
},
|
|
500
|
+
],
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
catch (error) {
|
|
504
|
+
return {
|
|
505
|
+
content: [
|
|
506
|
+
{
|
|
507
|
+
type: "text",
|
|
508
|
+
text: handleApiError(error),
|
|
509
|
+
},
|
|
510
|
+
],
|
|
511
|
+
isError: true,
|
|
512
|
+
};
|
|
513
|
+
}
|
|
514
|
+
});
|
|
515
|
+
// ========== CONTENT SITE MANAGEMENT TOOLS ==========
|
|
516
|
+
// Create Content Site
|
|
517
|
+
server.registerTool("create_content_site", {
|
|
518
|
+
title: "Create Content Site",
|
|
519
|
+
description: "Create a new content site in the current account",
|
|
520
|
+
inputSchema: {
|
|
521
|
+
name: z.string().describe("Content site name"),
|
|
522
|
+
sampleDataId: z.string().optional().describe("Optional sample data ID to initialize the site. The sample data list can be found in the ref data."),
|
|
523
|
+
},
|
|
524
|
+
}, async ({ name, sampleDataId }) => {
|
|
525
|
+
try {
|
|
526
|
+
const payload = { name, sampleDataId };
|
|
527
|
+
const response = await apiClient.post("/tools/content-sites", payload);
|
|
528
|
+
return {
|
|
529
|
+
content: [
|
|
530
|
+
{
|
|
531
|
+
type: "text",
|
|
532
|
+
text: JSON.stringify(response.data, null, 2),
|
|
533
|
+
},
|
|
534
|
+
],
|
|
535
|
+
};
|
|
536
|
+
}
|
|
537
|
+
catch (error) {
|
|
538
|
+
return {
|
|
539
|
+
content: [
|
|
540
|
+
{
|
|
541
|
+
type: "text",
|
|
542
|
+
text: handleApiError(error),
|
|
543
|
+
},
|
|
544
|
+
],
|
|
545
|
+
isError: true,
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
});
|
|
549
|
+
// Get Content Sites
|
|
550
|
+
server.registerTool("get_content_sites", {
|
|
551
|
+
title: "Get Content Sites",
|
|
552
|
+
description: "Get all content sites in the current account",
|
|
553
|
+
inputSchema: {},
|
|
554
|
+
}, async ({}) => {
|
|
555
|
+
try {
|
|
556
|
+
const response = await apiClient.get(`/tools/content-sites`);
|
|
557
|
+
return {
|
|
558
|
+
content: [
|
|
559
|
+
{
|
|
560
|
+
type: "text",
|
|
561
|
+
text: JSON.stringify(response.data, null, 2),
|
|
562
|
+
},
|
|
563
|
+
],
|
|
564
|
+
};
|
|
565
|
+
}
|
|
566
|
+
catch (error) {
|
|
567
|
+
return {
|
|
568
|
+
content: [
|
|
569
|
+
{
|
|
570
|
+
type: "text",
|
|
571
|
+
text: handleApiError(error),
|
|
572
|
+
},
|
|
573
|
+
],
|
|
574
|
+
isError: true,
|
|
575
|
+
};
|
|
576
|
+
}
|
|
577
|
+
});
|
|
578
|
+
// Get Content Site
|
|
579
|
+
server.registerTool("get_content_site", {
|
|
580
|
+
title: "Get Content Site",
|
|
581
|
+
description: "Get content site details by ID",
|
|
582
|
+
inputSchema: {
|
|
583
|
+
contentSiteId: z.string().describe("Content Site ID"),
|
|
584
|
+
},
|
|
585
|
+
}, async ({ contentSiteId }) => {
|
|
586
|
+
try {
|
|
587
|
+
const response = await apiClient.get(`/tools/content-sites/${contentSiteId}`);
|
|
588
|
+
return {
|
|
589
|
+
content: [
|
|
590
|
+
{
|
|
591
|
+
type: "text",
|
|
592
|
+
text: JSON.stringify(response.data, null, 2),
|
|
593
|
+
},
|
|
594
|
+
],
|
|
595
|
+
};
|
|
596
|
+
}
|
|
597
|
+
catch (error) {
|
|
598
|
+
return {
|
|
599
|
+
content: [
|
|
600
|
+
{
|
|
601
|
+
type: "text",
|
|
602
|
+
text: handleApiError(error),
|
|
603
|
+
},
|
|
604
|
+
],
|
|
605
|
+
isError: true,
|
|
606
|
+
};
|
|
607
|
+
}
|
|
608
|
+
});
|
|
609
|
+
// Update Content Site
|
|
610
|
+
server.registerTool("update_content_site", {
|
|
611
|
+
title: "Update Staging Site",
|
|
612
|
+
description: "Update staging site information",
|
|
613
|
+
inputSchema: {
|
|
614
|
+
contentSiteId: z.string().describe("Content Site ID"),
|
|
615
|
+
name: z.string().optional().describe("Content Site Name"),
|
|
616
|
+
contactEmail: z.string().optional().describe("Content Site Contact Email"),
|
|
617
|
+
billingEmail: z.string().optional().describe("Content Site Billing Email"),
|
|
618
|
+
addressLine1: z.string().optional().describe("Content Site Address Line 1"),
|
|
619
|
+
addressLine2: z.string().optional().describe("Content Site Address Line 2"),
|
|
620
|
+
city: z.string().optional().describe("Content Site City"),
|
|
621
|
+
state: z.string().optional().describe("Content Site State"),
|
|
622
|
+
country: z.string().optional().describe("Content Site Country"),
|
|
623
|
+
postalCode: z.string().optional().describe("Content Site Postal Code"),
|
|
624
|
+
productionUrl: z.string().optional().describe("Content Site Production URL"),
|
|
625
|
+
repoUrl: z.string().optional().describe("Content Site Repository URL"),
|
|
626
|
+
},
|
|
627
|
+
}, async ({ contentSiteId, name, contactEmail, billingEmail, addressLine1, addressLine2, city, state, country, postalCode, productionUrl, repoUrl }) => {
|
|
628
|
+
try {
|
|
629
|
+
const payload = {};
|
|
630
|
+
if (name)
|
|
631
|
+
payload.name = name;
|
|
632
|
+
if (contactEmail)
|
|
633
|
+
payload.contactEmail = contactEmail;
|
|
634
|
+
if (billingEmail)
|
|
635
|
+
payload.billingEmail = billingEmail;
|
|
636
|
+
if (addressLine1)
|
|
637
|
+
payload.addressLine1 = addressLine1;
|
|
638
|
+
if (addressLine2)
|
|
639
|
+
payload.addressLine2 = addressLine2;
|
|
640
|
+
if (city)
|
|
641
|
+
payload.city = city;
|
|
642
|
+
if (state)
|
|
643
|
+
payload.state = state;
|
|
644
|
+
if (country)
|
|
645
|
+
payload.country = country;
|
|
646
|
+
if (postalCode)
|
|
647
|
+
payload.postalCode = postalCode;
|
|
648
|
+
if (productionUrl)
|
|
649
|
+
payload.productionUrl = productionUrl;
|
|
650
|
+
if (repoUrl)
|
|
651
|
+
payload.repoUrl = repoUrl;
|
|
652
|
+
const response = await apiClient.put(`/tools/content-sites/${contentSiteId}`, payload);
|
|
653
|
+
return {
|
|
654
|
+
content: [
|
|
655
|
+
{
|
|
656
|
+
type: "text",
|
|
657
|
+
text: JSON.stringify(response.data, null, 2),
|
|
658
|
+
},
|
|
659
|
+
],
|
|
660
|
+
};
|
|
661
|
+
}
|
|
662
|
+
catch (error) {
|
|
663
|
+
return {
|
|
664
|
+
content: [
|
|
665
|
+
{
|
|
666
|
+
type: "text",
|
|
667
|
+
text: handleApiError(error),
|
|
668
|
+
},
|
|
669
|
+
],
|
|
670
|
+
isError: true,
|
|
671
|
+
};
|
|
672
|
+
}
|
|
673
|
+
});
|
|
674
|
+
// Delete Content Site
|
|
675
|
+
server.registerTool("delete_content_site", {
|
|
676
|
+
title: "Delete Content Site",
|
|
677
|
+
description: "Delete a content site",
|
|
678
|
+
inputSchema: {
|
|
679
|
+
contentSiteId: z.string().describe("Content Site ID"),
|
|
680
|
+
reason: z.string().optional().describe("Reason for deletion"),
|
|
681
|
+
},
|
|
682
|
+
}, async ({ contentSiteId, reason }) => {
|
|
683
|
+
try {
|
|
684
|
+
const payload = { reason };
|
|
685
|
+
const response = await apiClient.delete(`/tools/content-sites/${contentSiteId}`, {
|
|
686
|
+
data: payload,
|
|
687
|
+
});
|
|
688
|
+
return {
|
|
689
|
+
content: [
|
|
690
|
+
{
|
|
691
|
+
type: "text",
|
|
692
|
+
text: JSON.stringify(response.data, null, 2),
|
|
693
|
+
},
|
|
694
|
+
],
|
|
695
|
+
};
|
|
696
|
+
}
|
|
697
|
+
catch (error) {
|
|
698
|
+
return {
|
|
699
|
+
content: [
|
|
700
|
+
{
|
|
701
|
+
type: "text",
|
|
702
|
+
text: handleApiError(error),
|
|
703
|
+
},
|
|
704
|
+
],
|
|
705
|
+
isError: true,
|
|
706
|
+
};
|
|
707
|
+
}
|
|
708
|
+
});
|
|
709
|
+
// ========== STAGING SITE MANAGEMENT TOOLS ==========
|
|
710
|
+
// Update Staging Site
|
|
711
|
+
server.registerTool("update_staging_site", {
|
|
712
|
+
title: "Update Staging Site",
|
|
713
|
+
description: "Update staging site information",
|
|
714
|
+
inputSchema: {
|
|
715
|
+
contentSiteId: z.string().describe("Content Site ID"),
|
|
716
|
+
stagingSiteId: z.string().describe("Staging Site ID"),
|
|
717
|
+
name: z.string().optional().describe("Staging site name"),
|
|
718
|
+
locale: z.string().optional().describe("Staging site default locale"),
|
|
719
|
+
isHead: z.boolean().describe("Is the default staging site"),
|
|
720
|
+
content: z.record(z.any()).optional().describe("Staging site content"),
|
|
721
|
+
stageUrl: z.string().optional().describe("Staging site stage URL"),
|
|
722
|
+
guideUrl: z.string().optional().describe("Staging site guide URL"),
|
|
723
|
+
},
|
|
724
|
+
}, async ({ contentSiteId, stagingSiteId, name, locale, isHead, content, stageUrl, guideUrl }) => {
|
|
725
|
+
try {
|
|
726
|
+
const payload = {};
|
|
727
|
+
if (name)
|
|
728
|
+
payload.name = name;
|
|
729
|
+
if (locale)
|
|
730
|
+
payload.locale = locale;
|
|
731
|
+
if (isHead)
|
|
732
|
+
payload.isHead = isHead;
|
|
733
|
+
if (content)
|
|
734
|
+
payload.content = content;
|
|
735
|
+
if (stageUrl)
|
|
736
|
+
payload.stageUrl = stageUrl;
|
|
737
|
+
if (guideUrl)
|
|
738
|
+
payload.guideUrl = guideUrl;
|
|
739
|
+
const response = await apiClient.put(`/tools/content-sites/${contentSiteId}/staging-sites/${stagingSiteId}`, payload);
|
|
740
|
+
return {
|
|
741
|
+
content: [
|
|
742
|
+
{
|
|
743
|
+
type: "text",
|
|
744
|
+
text: JSON.stringify(response.data, null, 2),
|
|
745
|
+
},
|
|
746
|
+
],
|
|
747
|
+
};
|
|
748
|
+
}
|
|
749
|
+
catch (error) {
|
|
750
|
+
return {
|
|
751
|
+
content: [
|
|
752
|
+
{
|
|
753
|
+
type: "text",
|
|
754
|
+
text: handleApiError(error),
|
|
755
|
+
},
|
|
756
|
+
],
|
|
757
|
+
isError: true,
|
|
758
|
+
};
|
|
759
|
+
}
|
|
760
|
+
});
|
|
761
|
+
// Delete Staging Site
|
|
762
|
+
server.registerTool("delete_staging_site", {
|
|
763
|
+
title: "Delete Staging Site",
|
|
764
|
+
description: "Delete a staging site",
|
|
765
|
+
inputSchema: {
|
|
766
|
+
contentSiteId: z.string().describe("Content Site ID"),
|
|
767
|
+
stagingSiteId: z.string().describe("Staging Site ID"),
|
|
768
|
+
reason: z.string().optional().describe("Reason for deletion"),
|
|
769
|
+
},
|
|
770
|
+
}, async ({ contentSiteId, stagingSiteId, reason }) => {
|
|
771
|
+
try {
|
|
772
|
+
const payload = { reason };
|
|
773
|
+
const response = await apiClient.delete(`/tools/content-sites/${contentSiteId}/staging-sites/${stagingSiteId}`, {
|
|
774
|
+
data: payload,
|
|
775
|
+
});
|
|
776
|
+
return {
|
|
777
|
+
content: [
|
|
778
|
+
{
|
|
779
|
+
type: "text",
|
|
780
|
+
text: JSON.stringify(response.data, null, 2),
|
|
781
|
+
},
|
|
782
|
+
],
|
|
783
|
+
};
|
|
784
|
+
}
|
|
785
|
+
catch (error) {
|
|
786
|
+
return {
|
|
787
|
+
content: [
|
|
788
|
+
{
|
|
789
|
+
type: "text",
|
|
790
|
+
text: handleApiError(error),
|
|
791
|
+
},
|
|
792
|
+
],
|
|
793
|
+
isError: true,
|
|
794
|
+
};
|
|
795
|
+
}
|
|
796
|
+
});
|
|
797
|
+
// Publish Staging Site
|
|
798
|
+
server.registerTool("publish_staging_site", {
|
|
799
|
+
title: "Publish Staging Site",
|
|
800
|
+
description: "Publish a staging site to make it live",
|
|
801
|
+
inputSchema: {
|
|
802
|
+
contentSiteId: z.string().describe("Content Site ID"),
|
|
803
|
+
stagingSiteId: z.string().describe("Staging Site ID"),
|
|
804
|
+
comments: z.string().describe("Message for this publish"),
|
|
805
|
+
isApproved: z.boolean().describe("Is the publish approved"),
|
|
806
|
+
publishAt: z.date().optional().describe("When to publish the staging site"),
|
|
807
|
+
previewUrl: z.string().optional().describe("Preview URL for the staging site"),
|
|
808
|
+
},
|
|
809
|
+
}, async ({ contentSiteId, stagingSiteId, comments, isApproved, publishAt, previewUrl }) => {
|
|
810
|
+
try {
|
|
811
|
+
const payload = { comments, isApproved, publishAt, previewUrl };
|
|
812
|
+
const response = await apiClient.put(`/tools/content-sites/${contentSiteId}/staging-sites/${stagingSiteId}/publish`, payload);
|
|
813
|
+
return {
|
|
814
|
+
content: [
|
|
815
|
+
{
|
|
816
|
+
type: "text",
|
|
817
|
+
text: JSON.stringify(response.data, null, 2),
|
|
818
|
+
},
|
|
819
|
+
],
|
|
820
|
+
};
|
|
821
|
+
}
|
|
822
|
+
catch (error) {
|
|
823
|
+
return {
|
|
824
|
+
content: [
|
|
825
|
+
{
|
|
826
|
+
type: "text",
|
|
827
|
+
text: handleApiError(error),
|
|
828
|
+
},
|
|
829
|
+
],
|
|
830
|
+
isError: true,
|
|
831
|
+
};
|
|
832
|
+
}
|
|
833
|
+
});
|
|
834
|
+
// Get Staging Site
|
|
835
|
+
server.registerTool("get_staging_site", {
|
|
836
|
+
title: "Get Staging Site",
|
|
837
|
+
description: "Get staging site details by ID",
|
|
838
|
+
inputSchema: {
|
|
839
|
+
contentSiteId: z.string().describe("Content site ID"),
|
|
840
|
+
stagingSiteId: z.string().describe("Staging site ID"),
|
|
841
|
+
},
|
|
842
|
+
}, async ({ contentSiteId, stagingSiteId }) => {
|
|
843
|
+
try {
|
|
844
|
+
const response = await apiClient.get(`/tools/content-sites/${contentSiteId}/staging-sites/${stagingSiteId}`);
|
|
845
|
+
return {
|
|
846
|
+
content: [
|
|
847
|
+
{
|
|
848
|
+
type: "text",
|
|
849
|
+
text: JSON.stringify(response.data, null, 2),
|
|
850
|
+
},
|
|
851
|
+
],
|
|
852
|
+
};
|
|
853
|
+
}
|
|
854
|
+
catch (error) {
|
|
855
|
+
return {
|
|
856
|
+
content: [
|
|
857
|
+
{
|
|
858
|
+
type: "text",
|
|
859
|
+
text: handleApiError(error),
|
|
860
|
+
},
|
|
861
|
+
],
|
|
862
|
+
isError: true,
|
|
863
|
+
};
|
|
864
|
+
}
|
|
865
|
+
});
|
|
866
|
+
// Get Staging Site Pages
|
|
867
|
+
server.registerTool("get_staging_site_pages", {
|
|
868
|
+
title: "Get Staging Site Pages",
|
|
869
|
+
description: "Get staging site pages by ID",
|
|
870
|
+
inputSchema: {
|
|
871
|
+
contentSiteId: z.string().describe("Content site ID"),
|
|
872
|
+
stagingSiteId: z.string().describe("Staging site ID"),
|
|
873
|
+
},
|
|
874
|
+
}, async ({ contentSiteId, stagingSiteId }) => {
|
|
875
|
+
try {
|
|
876
|
+
const response = await apiClient.get(`/tools/content-sites/${contentSiteId}/staging-sites/${stagingSiteId}/pages`);
|
|
877
|
+
return {
|
|
878
|
+
content: [
|
|
879
|
+
{
|
|
880
|
+
type: "text",
|
|
881
|
+
text: JSON.stringify(response.data, null, 2),
|
|
882
|
+
},
|
|
883
|
+
],
|
|
884
|
+
};
|
|
885
|
+
}
|
|
886
|
+
catch (error) {
|
|
887
|
+
return {
|
|
888
|
+
content: [
|
|
889
|
+
{
|
|
890
|
+
type: "text",
|
|
891
|
+
text: handleApiError(error),
|
|
892
|
+
},
|
|
893
|
+
],
|
|
894
|
+
isError: true,
|
|
895
|
+
};
|
|
896
|
+
}
|
|
897
|
+
});
|
|
898
|
+
// Get Staging Site Configuration
|
|
899
|
+
server.registerTool("get_staging_site_configuration", {
|
|
900
|
+
title: "Get Staging Site Configuration",
|
|
901
|
+
description: "Get staging site configuration by ID",
|
|
902
|
+
inputSchema: {
|
|
903
|
+
contentSiteId: z.string().describe("Content site ID"),
|
|
904
|
+
stagingSiteId: z.string().describe("Staging site ID"),
|
|
905
|
+
},
|
|
906
|
+
}, async ({ contentSiteId, stagingSiteId }) => {
|
|
907
|
+
try {
|
|
908
|
+
const response = await apiClient.get(`/tools/content-sites/${contentSiteId}/staging-sites/${stagingSiteId}/configuration`);
|
|
909
|
+
return {
|
|
910
|
+
content: [
|
|
911
|
+
{
|
|
912
|
+
type: "text",
|
|
913
|
+
text: JSON.stringify(response.data, null, 2),
|
|
914
|
+
},
|
|
915
|
+
],
|
|
916
|
+
};
|
|
917
|
+
}
|
|
918
|
+
catch (error) {
|
|
919
|
+
return {
|
|
920
|
+
content: [
|
|
921
|
+
{
|
|
922
|
+
type: "text",
|
|
923
|
+
text: handleApiError(error),
|
|
924
|
+
},
|
|
925
|
+
],
|
|
926
|
+
isError: true,
|
|
927
|
+
};
|
|
928
|
+
}
|
|
929
|
+
});
|
|
930
|
+
// Get Staging Site Logs
|
|
931
|
+
server.registerTool("get_staging_site_logs", {
|
|
932
|
+
title: "Get Staging Site Logs",
|
|
933
|
+
description: "Change logs since last publish",
|
|
934
|
+
inputSchema: {
|
|
935
|
+
contentSiteId: z.string().describe("Content site ID"),
|
|
936
|
+
stagingSiteId: z.string().describe("Staging site ID"),
|
|
937
|
+
},
|
|
938
|
+
}, async ({ contentSiteId, stagingSiteId }) => {
|
|
939
|
+
try {
|
|
940
|
+
const response = await apiClient.get(`/tools/content-sites/${contentSiteId}/staging-sites/${stagingSiteId}/logs`);
|
|
941
|
+
return {
|
|
942
|
+
content: [
|
|
943
|
+
{
|
|
944
|
+
type: "text",
|
|
945
|
+
text: JSON.stringify(response.data, null, 2),
|
|
946
|
+
},
|
|
947
|
+
],
|
|
948
|
+
};
|
|
949
|
+
}
|
|
950
|
+
catch (error) {
|
|
951
|
+
return {
|
|
952
|
+
content: [
|
|
953
|
+
{
|
|
954
|
+
type: "text",
|
|
955
|
+
text: handleApiError(error),
|
|
956
|
+
},
|
|
957
|
+
],
|
|
958
|
+
isError: true,
|
|
959
|
+
};
|
|
960
|
+
}
|
|
961
|
+
});
|
|
962
|
+
// Get Published Sites
|
|
963
|
+
server.registerTool("get_published_sites", {
|
|
964
|
+
title: "Get Published Sites",
|
|
965
|
+
description: "Get published sites for a content site",
|
|
966
|
+
inputSchema: {
|
|
967
|
+
contentSiteId: z.string().describe("Content site ID"),
|
|
968
|
+
},
|
|
969
|
+
}, async ({ contentSiteId }) => {
|
|
970
|
+
try {
|
|
971
|
+
const params = new URLSearchParams();
|
|
972
|
+
const response = await apiClient.get(`/tools/content-sites/${contentSiteId}/published-sites`);
|
|
973
|
+
return {
|
|
974
|
+
content: [
|
|
975
|
+
{
|
|
976
|
+
type: "text",
|
|
977
|
+
text: JSON.stringify(response.data, null, 2),
|
|
978
|
+
},
|
|
979
|
+
],
|
|
980
|
+
};
|
|
981
|
+
}
|
|
982
|
+
catch (error) {
|
|
983
|
+
return {
|
|
984
|
+
content: [
|
|
985
|
+
{
|
|
986
|
+
type: "text",
|
|
987
|
+
text: handleApiError(error),
|
|
988
|
+
},
|
|
989
|
+
],
|
|
990
|
+
isError: true,
|
|
991
|
+
};
|
|
992
|
+
}
|
|
993
|
+
});
|
|
994
|
+
// Revert Staging Site
|
|
995
|
+
server.registerTool("revert_staging_site", {
|
|
996
|
+
title: "Revert Staging Site",
|
|
997
|
+
description: "Revert a staging site to a previous state",
|
|
998
|
+
inputSchema: {
|
|
999
|
+
contentSiteId: z.string().describe("Content site ID"),
|
|
1000
|
+
stagingSiteId: z.string().describe("Staging site ID"),
|
|
1001
|
+
reason: z.string().optional().describe("Reason for reversion"),
|
|
1002
|
+
},
|
|
1003
|
+
}, async ({ contentSiteId, stagingSiteId, reason }) => {
|
|
1004
|
+
try {
|
|
1005
|
+
const payload = { reason };
|
|
1006
|
+
const response = await apiClient.put(`/tools/content-sites/${contentSiteId}/staging-sites/${stagingSiteId}/revert`, payload);
|
|
1007
|
+
return {
|
|
1008
|
+
content: [
|
|
1009
|
+
{
|
|
1010
|
+
type: "text",
|
|
1011
|
+
text: JSON.stringify(response.data, null, 2),
|
|
1012
|
+
},
|
|
1013
|
+
],
|
|
1014
|
+
};
|
|
1015
|
+
}
|
|
1016
|
+
catch (error) {
|
|
1017
|
+
return {
|
|
1018
|
+
content: [
|
|
1019
|
+
{
|
|
1020
|
+
type: "text",
|
|
1021
|
+
text: handleApiError(error),
|
|
1022
|
+
},
|
|
1023
|
+
],
|
|
1024
|
+
isError: true,
|
|
1025
|
+
};
|
|
1026
|
+
}
|
|
1027
|
+
});
|
|
1028
|
+
// Clone Staging Site
|
|
1029
|
+
server.registerTool("clone_staging_site", {
|
|
1030
|
+
title: "Clone Staging Site",
|
|
1031
|
+
description: "Clone a staging site",
|
|
1032
|
+
inputSchema: {
|
|
1033
|
+
contentSiteId: z.string().describe("Content site ID"),
|
|
1034
|
+
stagingSiteId: z.string().describe("Staging site ID"),
|
|
1035
|
+
newName: z.string().optional().describe("Name for the cloned site"),
|
|
1036
|
+
},
|
|
1037
|
+
}, async ({ contentSiteId, stagingSiteId, newName }) => {
|
|
1038
|
+
try {
|
|
1039
|
+
const payload = { newName };
|
|
1040
|
+
const response = await apiClient.post(`/tools/content-sites/${contentSiteId}/staging-sites/${stagingSiteId}/clone`, payload);
|
|
1041
|
+
return {
|
|
1042
|
+
content: [
|
|
1043
|
+
{
|
|
1044
|
+
type: "text",
|
|
1045
|
+
text: JSON.stringify(response.data, null, 2),
|
|
1046
|
+
},
|
|
1047
|
+
],
|
|
1048
|
+
};
|
|
1049
|
+
}
|
|
1050
|
+
catch (error) {
|
|
1051
|
+
return {
|
|
1052
|
+
content: [
|
|
1053
|
+
{
|
|
1054
|
+
type: "text",
|
|
1055
|
+
text: handleApiError(error),
|
|
1056
|
+
},
|
|
1057
|
+
],
|
|
1058
|
+
isError: true,
|
|
1059
|
+
};
|
|
1060
|
+
}
|
|
1061
|
+
});
|
|
1062
|
+
// ========== WORKING SITE SECTION MANAGEMENT TOOLS ==========
|
|
1063
|
+
// Create Staging Site Section
|
|
1064
|
+
server.registerTool("create_staging_site_section", {
|
|
1065
|
+
title: "Create Staging Site Section",
|
|
1066
|
+
description: "Create a new section in a staging site page",
|
|
1067
|
+
inputSchema: {
|
|
1068
|
+
contentSiteId: z.string().describe("Content site ID"),
|
|
1069
|
+
stagingSiteId: z.string().describe("Staging site ID"),
|
|
1070
|
+
pageId: z.string().describe("Page ID"),
|
|
1071
|
+
sectionType: z.string().describe("Section type"),
|
|
1072
|
+
content: z.record(z.any()).optional().describe("Section content"),
|
|
1073
|
+
},
|
|
1074
|
+
}, async ({ contentSiteId, stagingSiteId, pageId, sectionType, content }) => {
|
|
1075
|
+
try {
|
|
1076
|
+
const payload = { sectionType, content };
|
|
1077
|
+
const response = await apiClient.post(`/tools/content-sites/${contentSiteId}/staging-sites/${stagingSiteId}/pages/${pageId}/sections`, payload);
|
|
1078
|
+
return {
|
|
1079
|
+
content: [
|
|
1080
|
+
{
|
|
1081
|
+
type: "text",
|
|
1082
|
+
text: JSON.stringify(response.data, null, 2),
|
|
1083
|
+
},
|
|
1084
|
+
],
|
|
1085
|
+
};
|
|
1086
|
+
}
|
|
1087
|
+
catch (error) {
|
|
1088
|
+
return {
|
|
1089
|
+
content: [
|
|
1090
|
+
{
|
|
1091
|
+
type: "text",
|
|
1092
|
+
text: handleApiError(error),
|
|
1093
|
+
},
|
|
1094
|
+
],
|
|
1095
|
+
isError: true,
|
|
1096
|
+
};
|
|
1097
|
+
}
|
|
1098
|
+
});
|
|
1099
|
+
// Get Staging Site Section
|
|
1100
|
+
server.registerTool("get_staging_site_section", {
|
|
1101
|
+
title: "Get Staging Site Section",
|
|
1102
|
+
description: "Get details of a staging site section",
|
|
1103
|
+
inputSchema: {
|
|
1104
|
+
contentSiteId: z.string().describe("Content site ID"),
|
|
1105
|
+
stagingSiteId: z.string().describe("Staging site ID"),
|
|
1106
|
+
pageId: z.string().describe("Page ID"),
|
|
1107
|
+
sectionId: z.string().describe("Section ID"),
|
|
1108
|
+
},
|
|
1109
|
+
}, async ({ contentSiteId, stagingSiteId, pageId, sectionId }) => {
|
|
1110
|
+
try {
|
|
1111
|
+
const response = await apiClient.get(`/tools/content-sites/${contentSiteId}/staging-sites/${stagingSiteId}/pages/${pageId}/sections/${sectionId}`);
|
|
1112
|
+
return {
|
|
1113
|
+
content: [
|
|
1114
|
+
{
|
|
1115
|
+
type: "text",
|
|
1116
|
+
text: JSON.stringify(response.data, null, 2),
|
|
1117
|
+
},
|
|
1118
|
+
],
|
|
1119
|
+
};
|
|
1120
|
+
}
|
|
1121
|
+
catch (error) {
|
|
1122
|
+
return {
|
|
1123
|
+
content: [
|
|
1124
|
+
{
|
|
1125
|
+
type: "text",
|
|
1126
|
+
text: handleApiError(error),
|
|
1127
|
+
},
|
|
1128
|
+
],
|
|
1129
|
+
isError: true,
|
|
1130
|
+
};
|
|
1131
|
+
}
|
|
1132
|
+
});
|
|
1133
|
+
// Update Staging Site Section
|
|
1134
|
+
server.registerTool("update_staging_site_section", {
|
|
1135
|
+
title: "Update Staging Site Section",
|
|
1136
|
+
description: "Update a staging site section",
|
|
1137
|
+
inputSchema: {
|
|
1138
|
+
contentSiteId: z.string().describe("Content site ID"),
|
|
1139
|
+
stagingSiteId: z.string().describe("Staging site ID"),
|
|
1140
|
+
pageId: z.string().describe("Page ID"),
|
|
1141
|
+
sectionId: z.string().describe("Section ID"),
|
|
1142
|
+
content: z.record(z.any()).optional().describe("Section content"),
|
|
1143
|
+
order: z.number().optional().describe("Section order"),
|
|
1144
|
+
},
|
|
1145
|
+
}, async ({ contentSiteId, stagingSiteId, pageId, sectionId, content, order }) => {
|
|
1146
|
+
try {
|
|
1147
|
+
const payload = {};
|
|
1148
|
+
if (content)
|
|
1149
|
+
payload.content = content;
|
|
1150
|
+
if (order !== undefined)
|
|
1151
|
+
payload.order = order;
|
|
1152
|
+
const response = await apiClient.put(`/tools/content-sites/${contentSiteId}/staging-sites/${stagingSiteId}/pages/${pageId}/sections/${sectionId}`, payload);
|
|
1153
|
+
return {
|
|
1154
|
+
content: [
|
|
1155
|
+
{
|
|
1156
|
+
type: "text",
|
|
1157
|
+
text: JSON.stringify(response.data, null, 2),
|
|
1158
|
+
},
|
|
1159
|
+
],
|
|
1160
|
+
};
|
|
1161
|
+
}
|
|
1162
|
+
catch (error) {
|
|
1163
|
+
return {
|
|
1164
|
+
content: [
|
|
1165
|
+
{
|
|
1166
|
+
type: "text",
|
|
1167
|
+
text: handleApiError(error),
|
|
1168
|
+
},
|
|
1169
|
+
],
|
|
1170
|
+
isError: true,
|
|
1171
|
+
};
|
|
1172
|
+
}
|
|
1173
|
+
});
|
|
1174
|
+
// Delete Staging Site Section
|
|
1175
|
+
server.registerTool("delete_staging_site_section", {
|
|
1176
|
+
title: "Delete Staging Site Section",
|
|
1177
|
+
description: "Delete a staging site section",
|
|
1178
|
+
inputSchema: {
|
|
1179
|
+
contentSiteId: z.string().describe("Content site ID"),
|
|
1180
|
+
stagingSiteId: z.string().describe("Staging site ID"),
|
|
1181
|
+
pageId: z.string().describe("Page ID"),
|
|
1182
|
+
sectionId: z.string().describe("Section ID"),
|
|
1183
|
+
},
|
|
1184
|
+
}, async ({ contentSiteId, stagingSiteId, pageId, sectionId }) => {
|
|
1185
|
+
try {
|
|
1186
|
+
const response = await apiClient.delete(`/tools/content-sites/${contentSiteId}/staging-sites/${stagingSiteId}/pages/${pageId}/sections/${sectionId}`);
|
|
1187
|
+
return {
|
|
1188
|
+
content: [
|
|
1189
|
+
{
|
|
1190
|
+
type: "text",
|
|
1191
|
+
text: JSON.stringify(response.data, null, 2),
|
|
1192
|
+
},
|
|
1193
|
+
],
|
|
1194
|
+
};
|
|
1195
|
+
}
|
|
1196
|
+
catch (error) {
|
|
1197
|
+
return {
|
|
1198
|
+
content: [
|
|
1199
|
+
{
|
|
1200
|
+
type: "text",
|
|
1201
|
+
text: handleApiError(error),
|
|
1202
|
+
},
|
|
1203
|
+
],
|
|
1204
|
+
isError: true,
|
|
1205
|
+
};
|
|
1206
|
+
}
|
|
1207
|
+
});
|
|
1208
|
+
// Publish Staging Site Section
|
|
1209
|
+
server.registerTool("publish_staging_site_section", {
|
|
1210
|
+
title: "Publish Staging Site Section",
|
|
1211
|
+
description: "Publish a staging site section",
|
|
1212
|
+
inputSchema: {
|
|
1213
|
+
contentSiteId: z.string().describe("Content site ID"),
|
|
1214
|
+
stagingSiteId: z.string().describe("Staging site ID"),
|
|
1215
|
+
pageId: z.string().describe("Page ID"),
|
|
1216
|
+
sectionId: z.string().describe("Section ID"),
|
|
1217
|
+
publishMessage: z.string().optional().describe("Message for this publish"),
|
|
1218
|
+
},
|
|
1219
|
+
}, async ({ contentSiteId, stagingSiteId, pageId, sectionId, publishMessage }) => {
|
|
1220
|
+
try {
|
|
1221
|
+
const payload = { publishMessage };
|
|
1222
|
+
const response = await apiClient.put(`/tools/content-sites/${contentSiteId}/staging-sites/${stagingSiteId}/pages/${pageId}/sections/${sectionId}/publish`, payload);
|
|
1223
|
+
return {
|
|
1224
|
+
content: [
|
|
1225
|
+
{
|
|
1226
|
+
type: "text",
|
|
1227
|
+
text: JSON.stringify(response.data, null, 2),
|
|
1228
|
+
},
|
|
1229
|
+
],
|
|
1230
|
+
};
|
|
1231
|
+
}
|
|
1232
|
+
catch (error) {
|
|
1233
|
+
return {
|
|
1234
|
+
content: [
|
|
1235
|
+
{
|
|
1236
|
+
type: "text",
|
|
1237
|
+
text: handleApiError(error),
|
|
1238
|
+
},
|
|
1239
|
+
],
|
|
1240
|
+
isError: true,
|
|
1241
|
+
};
|
|
1242
|
+
}
|
|
1243
|
+
});
|
|
1244
|
+
// Revert Staging Site Section
|
|
1245
|
+
server.registerTool("revert_staging_site_section", {
|
|
1246
|
+
title: "Revert Staging Site Section",
|
|
1247
|
+
description: "Revert a staging site section to a previous state",
|
|
1248
|
+
inputSchema: {
|
|
1249
|
+
contentSiteId: z.string().describe("Content site ID"),
|
|
1250
|
+
stagingSiteId: z.string().describe("Staging site ID"),
|
|
1251
|
+
pageId: z.string().describe("Page ID"),
|
|
1252
|
+
sectionId: z.string().describe("Section ID"),
|
|
1253
|
+
},
|
|
1254
|
+
}, async ({ contentSiteId, stagingSiteId, pageId, sectionId }) => {
|
|
1255
|
+
try {
|
|
1256
|
+
const response = await apiClient.put(`/tools/content-sites/${contentSiteId}/staging-sites/${stagingSiteId}/pages/${pageId}/sections/${sectionId}/revert`);
|
|
1257
|
+
return {
|
|
1258
|
+
content: [
|
|
1259
|
+
{
|
|
1260
|
+
type: "text",
|
|
1261
|
+
text: JSON.stringify(response.data, null, 2),
|
|
1262
|
+
},
|
|
1263
|
+
],
|
|
1264
|
+
};
|
|
1265
|
+
}
|
|
1266
|
+
catch (error) {
|
|
1267
|
+
return {
|
|
1268
|
+
content: [
|
|
1269
|
+
{
|
|
1270
|
+
type: "text",
|
|
1271
|
+
text: handleApiError(error),
|
|
1272
|
+
},
|
|
1273
|
+
],
|
|
1274
|
+
isError: true,
|
|
1275
|
+
};
|
|
1276
|
+
}
|
|
1277
|
+
});
|
|
1278
|
+
// Get Staging Site Section Logs
|
|
1279
|
+
server.registerTool("get_staging_site_section_logs", {
|
|
1280
|
+
title: "Get Staging Site Section Logs",
|
|
1281
|
+
description: "Get logs for a staging site section since the last publish",
|
|
1282
|
+
inputSchema: {
|
|
1283
|
+
contentSiteId: z.string().describe("Content site ID"),
|
|
1284
|
+
stagingSiteId: z.string().describe("Staging site ID"),
|
|
1285
|
+
pageId: z.string().describe("Page ID"),
|
|
1286
|
+
sectionId: z.string().describe("Section Common ID (CID)"),
|
|
1287
|
+
},
|
|
1288
|
+
}, async ({ contentSiteId, stagingSiteId, pageId, sectionId }) => {
|
|
1289
|
+
try {
|
|
1290
|
+
const response = await apiClient.get(`/tools/content-sites/${contentSiteId}/staging-sites/${stagingSiteId}/pages/${pageId}/sections/${sectionId}/logs`);
|
|
1291
|
+
return {
|
|
1292
|
+
content: [
|
|
1293
|
+
{
|
|
1294
|
+
type: "text",
|
|
1295
|
+
text: JSON.stringify(response.data, null, 2),
|
|
1296
|
+
},
|
|
1297
|
+
],
|
|
1298
|
+
};
|
|
1299
|
+
}
|
|
1300
|
+
catch (error) {
|
|
1301
|
+
return {
|
|
1302
|
+
content: [
|
|
1303
|
+
{
|
|
1304
|
+
type: "text",
|
|
1305
|
+
text: handleApiError(error),
|
|
1306
|
+
},
|
|
1307
|
+
],
|
|
1308
|
+
isError: true,
|
|
1309
|
+
};
|
|
1310
|
+
}
|
|
1311
|
+
});
|
|
1312
|
+
// ========== WORKING SITE PAGE MANAGEMENT TOOLS ==========
|
|
1313
|
+
// Create Staging Site Page
|
|
1314
|
+
server.registerTool("create_staging_site_page", {
|
|
1315
|
+
title: "Create Staging Site Page",
|
|
1316
|
+
description: "Create a new page in a staging site",
|
|
1317
|
+
inputSchema: {
|
|
1318
|
+
contentSiteId: z.string().describe("Content site ID"),
|
|
1319
|
+
stagingSiteId: z.string().describe("Staging site ID"),
|
|
1320
|
+
title: z.string().describe("Page title"),
|
|
1321
|
+
identifier: z.string().describe("Page identifier"),
|
|
1322
|
+
content: z.record(z.any()).optional().describe("Page content"),
|
|
1323
|
+
},
|
|
1324
|
+
}, async ({ contentSiteId, stagingSiteId, title, identifier, content }) => {
|
|
1325
|
+
try {
|
|
1326
|
+
const payload = { title, identifier, content };
|
|
1327
|
+
const response = await apiClient.post(`/tools/content-sites/${contentSiteId}/staging-sites/${stagingSiteId}/pages`, payload);
|
|
1328
|
+
return {
|
|
1329
|
+
content: [
|
|
1330
|
+
{
|
|
1331
|
+
type: "text",
|
|
1332
|
+
text: JSON.stringify(response.data, null, 2),
|
|
1333
|
+
},
|
|
1334
|
+
],
|
|
1335
|
+
};
|
|
1336
|
+
}
|
|
1337
|
+
catch (error) {
|
|
1338
|
+
return {
|
|
1339
|
+
content: [
|
|
1340
|
+
{
|
|
1341
|
+
type: "text",
|
|
1342
|
+
text: handleApiError(error),
|
|
1343
|
+
},
|
|
1344
|
+
],
|
|
1345
|
+
isError: true,
|
|
1346
|
+
};
|
|
1347
|
+
}
|
|
1348
|
+
});
|
|
1349
|
+
// Get Staging Site Page
|
|
1350
|
+
server.registerTool("get_staging_site_page", {
|
|
1351
|
+
title: "Get Staging Site Page",
|
|
1352
|
+
description: "Get details of a staging site page",
|
|
1353
|
+
inputSchema: {
|
|
1354
|
+
contentSiteId: z.string().describe("Content site ID"),
|
|
1355
|
+
stagingSiteId: z.string().describe("Staging site ID"),
|
|
1356
|
+
pageId: z.string().describe("Page ID"),
|
|
1357
|
+
includeSections: z.boolean().describe("Include page sections"),
|
|
1358
|
+
},
|
|
1359
|
+
}, async ({ contentSiteId, stagingSiteId, pageId, includeSections }) => {
|
|
1360
|
+
try {
|
|
1361
|
+
const params = new URLSearchParams();
|
|
1362
|
+
if (includeSections)
|
|
1363
|
+
params.append("includeSections", "true");
|
|
1364
|
+
const response = await apiClient.get(`/tools/content-sites/${contentSiteId}/staging-sites/${stagingSiteId}/pages/${pageId}?${params}`);
|
|
1365
|
+
return {
|
|
1366
|
+
content: [
|
|
1367
|
+
{
|
|
1368
|
+
type: "text",
|
|
1369
|
+
text: JSON.stringify(response.data, null, 2),
|
|
1370
|
+
},
|
|
1371
|
+
],
|
|
1372
|
+
};
|
|
1373
|
+
}
|
|
1374
|
+
catch (error) {
|
|
1375
|
+
return {
|
|
1376
|
+
content: [
|
|
1377
|
+
{
|
|
1378
|
+
type: "text",
|
|
1379
|
+
text: handleApiError(error),
|
|
1380
|
+
},
|
|
1381
|
+
],
|
|
1382
|
+
isError: true,
|
|
1383
|
+
};
|
|
1384
|
+
}
|
|
1385
|
+
});
|
|
1386
|
+
// Update Staging Site Page
|
|
1387
|
+
server.registerTool("update_staging_site_page", {
|
|
1388
|
+
title: "Update Staging Site Page",
|
|
1389
|
+
description: "Update a staging site page",
|
|
1390
|
+
inputSchema: {
|
|
1391
|
+
contentSiteId: z.string().describe("Content site ID"),
|
|
1392
|
+
stagingSiteId: z.string().describe("Staging site ID"),
|
|
1393
|
+
pageId: z.string().describe("Page ID"),
|
|
1394
|
+
title: z.string().describe("Page title"),
|
|
1395
|
+
identifier: z.string().describe("Page identifier"),
|
|
1396
|
+
order: z.number().optional().describe("Page order"),
|
|
1397
|
+
},
|
|
1398
|
+
}, async ({ contentSiteId, stagingSiteId, pageId, title, identifier, order }) => {
|
|
1399
|
+
try {
|
|
1400
|
+
const payload = {};
|
|
1401
|
+
if (title)
|
|
1402
|
+
payload.title = title;
|
|
1403
|
+
if (identifier)
|
|
1404
|
+
payload.identifier = identifier;
|
|
1405
|
+
if (order !== undefined)
|
|
1406
|
+
payload.order = order;
|
|
1407
|
+
const response = await apiClient.put(`/tools/content-sites/${contentSiteId}/staging-sites/${stagingSiteId}/pages/${pageId}`, payload);
|
|
1408
|
+
return {
|
|
1409
|
+
content: [
|
|
1410
|
+
{
|
|
1411
|
+
type: "text",
|
|
1412
|
+
text: JSON.stringify(response.data, null, 2),
|
|
1413
|
+
},
|
|
1414
|
+
],
|
|
1415
|
+
};
|
|
1416
|
+
}
|
|
1417
|
+
catch (error) {
|
|
1418
|
+
return {
|
|
1419
|
+
content: [
|
|
1420
|
+
{
|
|
1421
|
+
type: "text",
|
|
1422
|
+
text: handleApiError(error),
|
|
1423
|
+
},
|
|
1424
|
+
],
|
|
1425
|
+
isError: true,
|
|
1426
|
+
};
|
|
1427
|
+
}
|
|
1428
|
+
});
|
|
1429
|
+
// Delete Staging Site Page
|
|
1430
|
+
server.registerTool("delete_staging_site_page", {
|
|
1431
|
+
title: "Delete Staging Site Page",
|
|
1432
|
+
description: "Delete a staging site page",
|
|
1433
|
+
inputSchema: {
|
|
1434
|
+
contentSiteId: z.string().describe("Content site ID"),
|
|
1435
|
+
stagingSiteId: z.string().describe("Staging site ID"),
|
|
1436
|
+
pageId: z.string().describe("Page ID"),
|
|
1437
|
+
},
|
|
1438
|
+
}, async ({ contentSiteId, stagingSiteId, pageId }) => {
|
|
1439
|
+
try {
|
|
1440
|
+
const response = await apiClient.delete(`/tools/content-sites/${contentSiteId}/staging-sites/${stagingSiteId}/pages/${pageId}`);
|
|
1441
|
+
return {
|
|
1442
|
+
content: [
|
|
1443
|
+
{
|
|
1444
|
+
type: "text",
|
|
1445
|
+
text: JSON.stringify(response.data, null, 2),
|
|
1446
|
+
},
|
|
1447
|
+
],
|
|
1448
|
+
};
|
|
1449
|
+
}
|
|
1450
|
+
catch (error) {
|
|
1451
|
+
return {
|
|
1452
|
+
content: [
|
|
1453
|
+
{
|
|
1454
|
+
type: "text",
|
|
1455
|
+
text: handleApiError(error),
|
|
1456
|
+
},
|
|
1457
|
+
],
|
|
1458
|
+
isError: true,
|
|
1459
|
+
};
|
|
1460
|
+
}
|
|
1461
|
+
});
|
|
1462
|
+
// Get Staging Site Page Logs
|
|
1463
|
+
server.registerTool("get_staging_site_page_logs", {
|
|
1464
|
+
title: "Get Staging Site Page Logs",
|
|
1465
|
+
description: "Get the change logs for a staging site page since the last publish",
|
|
1466
|
+
inputSchema: {
|
|
1467
|
+
contentSiteId: z.string().describe("Content site ID"),
|
|
1468
|
+
stagingSiteId: z.string().describe("Staging site ID"),
|
|
1469
|
+
pageId: z.string().describe("Page common ID (CID)"),
|
|
1470
|
+
},
|
|
1471
|
+
}, async ({ contentSiteId, stagingSiteId, pageId }) => {
|
|
1472
|
+
try {
|
|
1473
|
+
const response = await apiClient.get(`/tools/content-sites/${contentSiteId}/staging-sites/${stagingSiteId}/pages/${pageId}/logs`);
|
|
1474
|
+
return {
|
|
1475
|
+
content: [
|
|
1476
|
+
{
|
|
1477
|
+
type: "text",
|
|
1478
|
+
text: JSON.stringify(response.data, null, 2),
|
|
1479
|
+
},
|
|
1480
|
+
],
|
|
1481
|
+
};
|
|
1482
|
+
}
|
|
1483
|
+
catch (error) {
|
|
1484
|
+
return {
|
|
1485
|
+
content: [
|
|
1486
|
+
{
|
|
1487
|
+
type: "text",
|
|
1488
|
+
text: handleApiError(error),
|
|
1489
|
+
},
|
|
1490
|
+
],
|
|
1491
|
+
isError: true,
|
|
1492
|
+
};
|
|
1493
|
+
}
|
|
1494
|
+
});
|
|
1495
|
+
// ========== ContentSite ANALYTICS & ADMIN TOOLS ==========
|
|
1496
|
+
// Get ContentSite Logs
|
|
1497
|
+
server.registerTool("get_content_site_logs", {
|
|
1498
|
+
title: "Get ContentSite Logs",
|
|
1499
|
+
description: "Get the last 15 activity logs for a content site",
|
|
1500
|
+
inputSchema: {
|
|
1501
|
+
contentSiteId: z.string().describe("Content site ID"),
|
|
1502
|
+
},
|
|
1503
|
+
}, async ({ contentSiteId }) => {
|
|
1504
|
+
try {
|
|
1505
|
+
const response = await apiClient.get(`/tools/content-sites/${contentSiteId}/logs`);
|
|
1506
|
+
return {
|
|
1507
|
+
content: [
|
|
1508
|
+
{
|
|
1509
|
+
type: "text",
|
|
1510
|
+
text: JSON.stringify(response.data, null, 2),
|
|
1511
|
+
},
|
|
1512
|
+
],
|
|
1513
|
+
};
|
|
1514
|
+
}
|
|
1515
|
+
catch (error) {
|
|
1516
|
+
return {
|
|
1517
|
+
content: [
|
|
1518
|
+
{
|
|
1519
|
+
type: "text",
|
|
1520
|
+
text: handleApiError(error),
|
|
1521
|
+
},
|
|
1522
|
+
],
|
|
1523
|
+
isError: true,
|
|
1524
|
+
};
|
|
1525
|
+
}
|
|
1526
|
+
});
|
|
1527
|
+
// Get ContentSite Hits (Analytics)
|
|
1528
|
+
server.registerTool("get_content_site_hits", {
|
|
1529
|
+
title: "Get ContentSite Hits",
|
|
1530
|
+
description: "Get daily hits for a content site",
|
|
1531
|
+
inputSchema: {
|
|
1532
|
+
contentSiteId: z.string().describe("Content site ID"),
|
|
1533
|
+
},
|
|
1534
|
+
}, async ({ contentSiteId }) => {
|
|
1535
|
+
try {
|
|
1536
|
+
const response = await apiClient.get(`/tools/content-sites/${contentSiteId}/hits`);
|
|
1537
|
+
return {
|
|
1538
|
+
content: [
|
|
1539
|
+
{
|
|
1540
|
+
type: "text",
|
|
1541
|
+
text: JSON.stringify(response.data, null, 2),
|
|
1542
|
+
},
|
|
1543
|
+
],
|
|
1544
|
+
};
|
|
1545
|
+
}
|
|
1546
|
+
catch (error) {
|
|
1547
|
+
return {
|
|
1548
|
+
content: [
|
|
1549
|
+
{
|
|
1550
|
+
type: "text",
|
|
1551
|
+
text: handleApiError(error),
|
|
1552
|
+
},
|
|
1553
|
+
],
|
|
1554
|
+
isError: true,
|
|
1555
|
+
};
|
|
1556
|
+
}
|
|
1557
|
+
});
|
|
1558
|
+
// Get ContentSite Users
|
|
1559
|
+
server.registerTool("get_content_site_accounts", {
|
|
1560
|
+
title: "Get ContentSite Accounts",
|
|
1561
|
+
description: "Get accounts associated with a content site",
|
|
1562
|
+
inputSchema: {
|
|
1563
|
+
contentSiteId: z.string().describe("Content site ID"),
|
|
1564
|
+
},
|
|
1565
|
+
}, async ({ contentSiteId }) => {
|
|
1566
|
+
try {
|
|
1567
|
+
const response = await apiClient.get(`/tools/content-sites/${contentSiteId}/accounts`);
|
|
1568
|
+
return {
|
|
1569
|
+
content: [
|
|
1570
|
+
{
|
|
1571
|
+
type: "text",
|
|
1572
|
+
text: JSON.stringify(response.data, null, 2),
|
|
1573
|
+
},
|
|
1574
|
+
],
|
|
1575
|
+
};
|
|
1576
|
+
}
|
|
1577
|
+
catch (error) {
|
|
1578
|
+
return {
|
|
1579
|
+
content: [
|
|
1580
|
+
{
|
|
1581
|
+
type: "text",
|
|
1582
|
+
text: handleApiError(error),
|
|
1583
|
+
},
|
|
1584
|
+
],
|
|
1585
|
+
isError: true,
|
|
1586
|
+
};
|
|
1587
|
+
}
|
|
1588
|
+
});
|
|
1589
|
+
// Get Content site Claims
|
|
1590
|
+
server.registerTool("get_content_site_claims", {
|
|
1591
|
+
title: "Get Content site Claims",
|
|
1592
|
+
description: "Get current user claims for the content site",
|
|
1593
|
+
inputSchema: {
|
|
1594
|
+
contentSiteId: z.string().describe("Content site ID"),
|
|
1595
|
+
},
|
|
1596
|
+
}, async ({ contentSiteId }) => {
|
|
1597
|
+
try {
|
|
1598
|
+
const response = await apiClient.get(`/tools/content-sites/${contentSiteId}/claims`);
|
|
1599
|
+
return {
|
|
1600
|
+
content: [
|
|
1601
|
+
{
|
|
1602
|
+
type: "text",
|
|
1603
|
+
text: JSON.stringify(response.data, null, 2),
|
|
1604
|
+
},
|
|
1605
|
+
],
|
|
1606
|
+
};
|
|
1607
|
+
}
|
|
1608
|
+
catch (error) {
|
|
1609
|
+
return {
|
|
1610
|
+
content: [
|
|
1611
|
+
{
|
|
1612
|
+
type: "text",
|
|
1613
|
+
text: handleApiError(error),
|
|
1614
|
+
},
|
|
1615
|
+
],
|
|
1616
|
+
isError: true,
|
|
1617
|
+
};
|
|
1618
|
+
}
|
|
1619
|
+
});
|
|
1620
|
+
// ========== RESOURCES ==========
|
|
1621
|
+
// Register a resource for API configuration
|
|
1622
|
+
server.registerResource("api_config", "config://api", {
|
|
1623
|
+
title: "Headlesshost API Configuration",
|
|
1624
|
+
description: "Current Headlesshost API configuration and available endpoints",
|
|
1625
|
+
mimeType: "application/json",
|
|
1626
|
+
}, async () => {
|
|
1627
|
+
const config = {
|
|
1628
|
+
baseUrl: API_BASE_URL,
|
|
1629
|
+
hasApiKey: !!API_KEY,
|
|
1630
|
+
endpoints: {
|
|
1631
|
+
general: {
|
|
1632
|
+
ping: "GET /tools/ping - Test authentication and connection",
|
|
1633
|
+
},
|
|
1634
|
+
membership: {
|
|
1635
|
+
register: "POST /tools/membership/register - Register new user",
|
|
1636
|
+
createUser: "POST /tools/membership/users - Create user",
|
|
1637
|
+
getUser: "GET /tools/membership/users/:id - Get user details",
|
|
1638
|
+
updateUser: "PUT /tools/membership/users/:id - Update user",
|
|
1639
|
+
deleteUser: "DELETE /tools/membership/users/:id - Delete user",
|
|
1640
|
+
getAccount: "GET /tools/membership/account - Get account info",
|
|
1641
|
+
updateAccount: "PUT /tools/membership/account - Update account",
|
|
1642
|
+
},
|
|
1643
|
+
contentSite: {
|
|
1644
|
+
createContentSite: "POST /tools/content-sites - Create content site",
|
|
1645
|
+
getContentSites: "GET /tools/content-sites - Get content sites",
|
|
1646
|
+
getContentSite: "GET /tools/content-sites/:id - Get content site details",
|
|
1647
|
+
getContentSiteLogs: "GET /tools/content-sites/:contentSiteId/logs - Get content site logs",
|
|
1648
|
+
getContentSiteHits: "GET /tools/content-sites/:contentSiteId/hits - Get content site analytics",
|
|
1649
|
+
getContentSiteUsers: "GET /tools/content-sites/:contentSiteId/users - Get content site users",
|
|
1650
|
+
getContentSiteClaims: "GET /tools/content-sites/:contentSiteId/claims - Get content site claims",
|
|
1651
|
+
},
|
|
1652
|
+
stagingSites: {
|
|
1653
|
+
createStagingSite: "POST /tools/content-sites/:contentSiteId/staging-sites - Create staging site",
|
|
1654
|
+
getStagingSite: "GET /tools/content-sites/:contentSiteId/staging-sites/:stagingSiteId - Get staging site details",
|
|
1655
|
+
getStagingSitePages: "GET /tools/content-sites/:contentSiteId/staging-sites/:stagingSiteId/pages - Get staging site pages",
|
|
1656
|
+
getStagingSiteConfiguration: "GET /tools/content-sites/:contentSiteId/staging-sites/:stagingSiteId/configuration - Get staging site configuration, including section types (BusinessSections) available for pages",
|
|
1657
|
+
updateStagingSite: "PUT /tools/content-sites/:contentSiteId/staging-sites/:stagingSiteId - Update staging site",
|
|
1658
|
+
deleteStagingSite: "DELETE /tools/content-sites/:contentSiteId/staging-sites/:stagingSiteId - Delete staging site",
|
|
1659
|
+
publishStagingSite: "PUT /tools/content-sites/:contentSiteId/staging-sites/:stagingSiteId/publish - Publish staging site",
|
|
1660
|
+
revertStagingSite: "PUT /tools/content-sites/:contentSiteId/staging-sites/:stagingSiteId/revert - Revert staging site",
|
|
1661
|
+
cloneStagingSite: "POST /tools/content-sites/:contentSiteId/staging-sites/:stagingSiteId/clone - Clone staging site",
|
|
1662
|
+
getStagingSiteLogs: "GET /tools/content-sites/:contentSiteId/staging-sites/:stagingSiteId/logs - Get staging site logs",
|
|
1663
|
+
getPublishedSites: "GET /tools/content-sites/:contentSiteId/published-sites - Get published sites",
|
|
1664
|
+
},
|
|
1665
|
+
stagingSitePages: {
|
|
1666
|
+
createStagingSitePage: "POST /tools/content-sites/:contentSiteId/staging-sites/:stagingSiteId/pages - Create staging site page",
|
|
1667
|
+
getStagingSitePage: "GET /tools/content-sites/:contentSiteId/staging-sites/:stagingSiteId/pages/:pageId - Get staging site page",
|
|
1668
|
+
updateStagingSitePage: "PUT /tools/content-sites/:contentSiteId/staging-sites/:stagingSiteId/pages/:pageId - Update staging site page",
|
|
1669
|
+
deleteStagingSitePage: "DELETE /tools/content-sites/:contentSiteId/staging-sites/:stagingSiteId/pages/:pageId - Delete staging site page",
|
|
1670
|
+
getStagingSitePageLogs: "GET /tools/content-sites/:contentSiteId/staging-sites/:stagingSiteId/pages/:pageId/logs - Get staging site page logs",
|
|
1671
|
+
},
|
|
1672
|
+
stagingSiteSections: {
|
|
1673
|
+
createStagingSiteSection: "POST /tools/content-sites/:contentSiteId/staging-sites/:stagingSiteId/pages/:pageId/sections - Create staging site section",
|
|
1674
|
+
getStagingSiteSection: "GET /tools/content-sites/:contentSiteId/staging-sites/:stagingSiteId/pages/:pageId/sections/:sectionId - Get staging site section",
|
|
1675
|
+
updateStagingSiteSection: "PUT /tools/content-sites/:contentSiteId/staging-sites/:stagingSiteId/pages/:pageId/sections/:sectionId - Update staging site section",
|
|
1676
|
+
deleteStagingSiteSection: "DELETE /tools/content-sites/:contentSiteId/staging-sites/:stagingSiteId/pages/:pageId/sections/:sectionId - Delete staging site section",
|
|
1677
|
+
publishStagingSiteSection: "PUT /tools/content-sites/:contentSiteId/staging-sites/:stagingSiteId/pages/:pageId/sections/:sectionId/publish - Publish staging site section",
|
|
1678
|
+
revertStagingSiteSection: "PUT /tools/content-sites/:contentSiteId/staging-sites/:stagingSiteId/pages/:pageId/sections/:sectionId/revert - Revert staging site section",
|
|
1679
|
+
getStagingSiteSectionLogs: "GET /tools/content-sites/:contentSiteId/staging-sites/:stagingSiteId/pages/:pageId/sections/:sectionId/logs - Get staging site section logs",
|
|
1680
|
+
},
|
|
1681
|
+
system: {
|
|
1682
|
+
getRefData: "GET /tools/system/refdata - Get reference data",
|
|
1683
|
+
},
|
|
1684
|
+
},
|
|
1685
|
+
};
|
|
1686
|
+
return {
|
|
1687
|
+
contents: [
|
|
1688
|
+
{
|
|
1689
|
+
uri: "config://api",
|
|
1690
|
+
text: JSON.stringify(config, null, 2),
|
|
1691
|
+
mimeType: "application/json",
|
|
1692
|
+
},
|
|
1693
|
+
],
|
|
1694
|
+
};
|
|
1695
|
+
});
|
|
1696
|
+
// Register a resource for API health status
|
|
1697
|
+
server.registerResource("api_health", "health://api", {
|
|
1698
|
+
title: "Headlesshost API Health Status",
|
|
1699
|
+
description: "Current health status and connectivity information for the Headlesshost API",
|
|
1700
|
+
mimeType: "application/json",
|
|
1701
|
+
}, async () => {
|
|
1702
|
+
try {
|
|
1703
|
+
const startTime = Date.now();
|
|
1704
|
+
const response = await apiClient.get("/tools/ping");
|
|
1705
|
+
const endTime = Date.now();
|
|
1706
|
+
const responseTime = endTime - startTime;
|
|
1707
|
+
const healthInfo = {
|
|
1708
|
+
status: "healthy",
|
|
1709
|
+
responseTime: `${responseTime}ms`,
|
|
1710
|
+
timestamp: new Date().toISOString(),
|
|
1711
|
+
apiUrl: API_BASE_URL,
|
|
1712
|
+
authenticated: response.status === 200,
|
|
1713
|
+
serverResponse: response.data,
|
|
1714
|
+
};
|
|
1715
|
+
return {
|
|
1716
|
+
contents: [
|
|
1717
|
+
{
|
|
1718
|
+
uri: "health://api",
|
|
1719
|
+
text: JSON.stringify(healthInfo, null, 2),
|
|
1720
|
+
mimeType: "application/json",
|
|
1721
|
+
},
|
|
1722
|
+
],
|
|
1723
|
+
};
|
|
1724
|
+
}
|
|
1725
|
+
catch (error) {
|
|
1726
|
+
const healthInfo = {
|
|
1727
|
+
status: "unhealthy",
|
|
1728
|
+
timestamp: new Date().toISOString(),
|
|
1729
|
+
apiUrl: API_BASE_URL,
|
|
1730
|
+
error: error instanceof Error ? error.message : "Unknown error",
|
|
1731
|
+
authenticated: false,
|
|
1732
|
+
};
|
|
1733
|
+
return {
|
|
1734
|
+
contents: [
|
|
1735
|
+
{
|
|
1736
|
+
uri: "health://api",
|
|
1737
|
+
text: JSON.stringify(healthInfo, null, 2),
|
|
1738
|
+
mimeType: "application/json",
|
|
1739
|
+
},
|
|
1740
|
+
],
|
|
1741
|
+
};
|
|
1742
|
+
}
|
|
1743
|
+
});
|
|
1744
|
+
// Start the server
|
|
1745
|
+
async function main() {
|
|
1746
|
+
const transport = new StdioServerTransport();
|
|
1747
|
+
await server.connect(transport);
|
|
1748
|
+
// Log to stderr so it doesn't interfere with the JSON-RPC protocol on stdout
|
|
1749
|
+
console.error("Headlesshost MCP Server started successfully");
|
|
1750
|
+
console.error(`API Base URL: ${API_BASE_URL}`);
|
|
1751
|
+
console.error(`API Key configured: ${!!API_KEY}`);
|
|
1752
|
+
}
|
|
1753
|
+
main().catch((error) => {
|
|
1754
|
+
console.error("Unhandled error in main:", error);
|
|
1755
|
+
process.exit(1);
|
|
1756
|
+
});
|
|
1757
|
+
// Handle graceful shutdown
|
|
1758
|
+
process.on("SIGINT", async () => {
|
|
1759
|
+
console.error("Shutting down Headlesshost MCP Server...");
|
|
1760
|
+
process.exit(0);
|
|
1761
|
+
});
|
|
1762
|
+
process.on("SIGTERM", async () => {
|
|
1763
|
+
console.error("Shutting down Headlesshost MCP Server...");
|
|
1764
|
+
process.exit(0);
|
|
1765
|
+
});
|
|
1766
|
+
//# sourceMappingURL=index.js.map
|