@jgardner04/ghost-mcp-server 1.12.0 → 1.12.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -40,13 +40,17 @@ dotenv.config();
40
40
  // Lazy-loaded modules (to avoid Node.js v25 Buffer compatibility issues at startup)
41
41
  let ghostService = null;
42
42
  let postService = null;
43
+ let pageService = null;
44
+ let newsletterService = null;
43
45
  let imageProcessingService = null;
44
46
  let urlValidator = null;
45
47
 
46
48
  const loadServices = async () => {
47
49
  if (!ghostService) {
48
- ghostService = await import('./services/ghostService.js');
50
+ ghostService = await import('./services/ghostServiceImproved.js');
49
51
  postService = await import('./services/postService.js');
52
+ pageService = await import('./services/pageService.js');
53
+ newsletterService = await import('./services/newsletterService.js');
50
54
  imageProcessingService = await import('./services/imageProcessingService.js');
51
55
  urlValidator = await import('./utils/urlValidator.js');
52
56
  }
@@ -78,11 +82,18 @@ const server = new McpServer({
78
82
 
79
83
  // --- Schema Definitions for Tools ---
80
84
  const getTagsSchema = tagQuerySchema.partial();
81
- const getTagSchema = z.object({
82
- id: ghostIdSchema.optional().describe('The ID of the tag to retrieve.'),
83
- slug: z.string().optional().describe('The slug of the tag to retrieve.'),
84
- include: z.string().optional().describe('Additional resources to include (e.g., "count.posts").'),
85
- });
85
+ const getTagSchema = z
86
+ .object({
87
+ id: ghostIdSchema.optional().describe('The ID of the tag to retrieve.'),
88
+ slug: z.string().optional().describe('The slug of the tag to retrieve.'),
89
+ include: z
90
+ .string()
91
+ .optional()
92
+ .describe('Additional resources to include (e.g., "count.posts").'),
93
+ })
94
+ .refine((data) => data.id || data.slug, {
95
+ message: 'Either id or slug is required to retrieve a tag',
96
+ });
86
97
  const updateTagInputSchema = updateTagSchema.extend({ id: ghostIdSchema });
87
98
  const deleteTagSchema = z.object({ id: ghostIdSchema });
88
99
 
@@ -183,18 +194,13 @@ server.tool(
183
194
 
184
195
  console.error(`Executing tool: ghost_get_tag`);
185
196
  try {
186
- if (!id && !slug) {
187
- throw new Error('Either id or slug must be provided');
188
- }
189
-
190
197
  await loadServices();
191
198
 
192
199
  // If slug is provided, use the slug/slug-name format
193
200
  const identifier = slug ? `slug/${slug}` : id;
194
201
  const options = include ? { include } : {};
195
202
 
196
- const ghostServiceImproved = await import('./services/ghostServiceImproved.js');
197
- const tag = await ghostServiceImproved.getTag(identifier, options);
203
+ const tag = await ghostService.getTag(identifier, options);
198
204
  console.error(`Tag retrieved successfully. Tag ID: ${tag.id}`);
199
205
 
200
206
  return {
@@ -240,8 +246,7 @@ server.tool(
240
246
  // Build update data object with only provided fields (exclude id from update data)
241
247
  const { id, ...updateData } = input;
242
248
 
243
- const ghostServiceImproved = await import('./services/ghostServiceImproved.js');
244
- const updatedTag = await ghostServiceImproved.updateTag(id, updateData);
249
+ const updatedTag = await ghostService.updateTag(id, updateData);
245
250
  console.error(`Tag updated successfully. Tag ID: ${updatedTag.id}`);
246
251
 
247
252
  return {
@@ -284,8 +289,7 @@ server.tool(
284
289
 
285
290
  await loadServices();
286
291
 
287
- const ghostServiceImproved = await import('./services/ghostServiceImproved.js');
288
- await ghostServiceImproved.deleteTag(id);
292
+ await ghostService.deleteTag(id);
289
293
  console.error(`Tag deleted successfully. Tag ID: ${id}`);
290
294
 
291
295
  return {
@@ -408,14 +412,18 @@ const getPostsSchema = postQuerySchema.extend({
408
412
  .optional()
409
413
  .describe('Filter posts by status. Options: published, draft, scheduled, all.'),
410
414
  });
411
- const getPostSchema = z.object({
412
- id: ghostIdSchema.optional().describe('The ID of the post to retrieve.'),
413
- slug: z.string().optional().describe('The slug of the post to retrieve.'),
414
- include: z
415
- .string()
416
- .optional()
417
- .describe('Comma-separated list of relations to include (e.g., "tags,authors").'),
418
- });
415
+ const getPostSchema = z
416
+ .object({
417
+ id: ghostIdSchema.optional().describe('The ID of the post to retrieve.'),
418
+ slug: z.string().optional().describe('The slug of the post to retrieve.'),
419
+ include: z
420
+ .string()
421
+ .optional()
422
+ .describe('Comma-separated list of relations to include (e.g., "tags,authors").'),
423
+ })
424
+ .refine((data) => data.id || data.slug, {
425
+ message: 'Either id or slug is required to retrieve a post',
426
+ });
419
427
  const searchPostsSchema = z.object({
420
428
  query: z.string().min(1).describe('Search query to find in post titles.'),
421
429
  status: z
@@ -533,11 +541,6 @@ server.tool(
533
541
 
534
542
  console.error(`Executing tool: ghost_get_post`);
535
543
  try {
536
- // Validate that at least one of id or slug is provided
537
- if (!input.id && !input.slug) {
538
- throw new Error('Either id or slug is required to retrieve a post');
539
- }
540
-
541
544
  await loadServices();
542
545
 
543
546
  // Build options object
@@ -591,9 +594,7 @@ server.tool(
591
594
  if (input.status !== undefined) options.status = input.status;
592
595
  if (input.limit !== undefined) options.limit = input.limit;
593
596
 
594
- // Search posts using ghostServiceImproved
595
- const ghostServiceImproved = await import('./services/ghostServiceImproved.js');
596
- const posts = await ghostServiceImproved.searchPosts(input.query, options);
597
+ const posts = await ghostService.searchPosts(input.query, options);
597
598
  console.error(`Found ${posts.length} posts matching "${input.query}".`);
598
599
 
599
600
  return {
@@ -635,9 +636,7 @@ server.tool(
635
636
  // Extract ID from input and build update data
636
637
  const { id, ...updateData } = input;
637
638
 
638
- // Update the post using ghostServiceImproved
639
- const ghostServiceImproved = await import('./services/ghostServiceImproved.js');
640
- const updatedPost = await ghostServiceImproved.updatePost(id, updateData);
639
+ const updatedPost = await ghostService.updatePost(id, updateData);
641
640
  console.error(`Post updated successfully. Post ID: ${updatedPost.id}`);
642
641
 
643
642
  return {
@@ -676,9 +675,7 @@ server.tool(
676
675
  try {
677
676
  await loadServices();
678
677
 
679
- // Delete the post using ghostServiceImproved
680
- const ghostServiceImproved = await import('./services/ghostServiceImproved.js');
681
- await ghostServiceImproved.deletePost(id);
678
+ await ghostService.deletePost(id);
682
679
  console.error(`Post deleted successfully. Post ID: ${id}`);
683
680
 
684
681
  return {
@@ -767,8 +764,7 @@ server.tool(
767
764
  if (input.formats !== undefined) options.formats = input.formats;
768
765
  if (input.order !== undefined) options.order = input.order;
769
766
 
770
- const ghostServiceImproved = await import('./services/ghostServiceImproved.js');
771
- const pages = await ghostServiceImproved.getPages(options);
767
+ const pages = await ghostService.getPages(options);
772
768
  console.error(`Retrieved ${pages.length} pages from Ghost.`);
773
769
 
774
770
  return {
@@ -812,8 +808,7 @@ server.tool(
812
808
 
813
809
  const identifier = input.id || `slug/${input.slug}`;
814
810
 
815
- const ghostServiceImproved = await import('./services/ghostServiceImproved.js');
816
- const page = await ghostServiceImproved.getPage(identifier, options);
811
+ const page = await ghostService.getPage(identifier, options);
817
812
  console.error(`Retrieved page: ${page.title} (ID: ${page.id})`);
818
813
 
819
814
  return {
@@ -852,7 +847,6 @@ server.tool(
852
847
  try {
853
848
  await loadServices();
854
849
 
855
- const pageService = await import('./services/pageService.js');
856
850
  const createdPage = await pageService.createPageService(input);
857
851
  console.error(`Page created successfully. Page ID: ${createdPage.id}`);
858
852
 
@@ -894,8 +888,7 @@ server.tool(
894
888
 
895
889
  const { id, ...updateData } = input;
896
890
 
897
- const ghostServiceImproved = await import('./services/ghostServiceImproved.js');
898
- const updatedPage = await ghostServiceImproved.updatePage(id, updateData);
891
+ const updatedPage = await ghostService.updatePage(id, updateData);
899
892
  console.error(`Page updated successfully. Page ID: ${updatedPage.id}`);
900
893
 
901
894
  return {
@@ -934,8 +927,7 @@ server.tool(
934
927
  try {
935
928
  await loadServices();
936
929
 
937
- const ghostServiceImproved = await import('./services/ghostServiceImproved.js');
938
- await ghostServiceImproved.deletePage(id);
930
+ await ghostService.deletePage(id);
939
931
  console.error(`Page deleted successfully. Page ID: ${id}`);
940
932
 
941
933
  return {
@@ -978,8 +970,7 @@ server.tool(
978
970
  if (input.status !== undefined) options.status = input.status;
979
971
  if (input.limit !== undefined) options.limit = input.limit;
980
972
 
981
- const ghostServiceImproved = await import('./services/ghostServiceImproved.js');
982
- const pages = await ghostServiceImproved.searchPages(input.query, options);
973
+ const pages = await ghostService.searchPages(input.query, options);
983
974
  console.error(`Found ${pages.length} pages matching "${input.query}".`);
984
975
 
985
976
  return {
@@ -1046,8 +1037,7 @@ server.tool(
1046
1037
  try {
1047
1038
  await loadServices();
1048
1039
 
1049
- const ghostServiceImproved = await import('./services/ghostServiceImproved.js');
1050
- const createdMember = await ghostServiceImproved.createMember(input);
1040
+ const createdMember = await ghostService.createMember(input);
1051
1041
  console.error(`Member created successfully. Member ID: ${createdMember.id}`);
1052
1042
 
1053
1043
  return {
@@ -1088,8 +1078,7 @@ server.tool(
1088
1078
 
1089
1079
  const { id, ...updateData } = input;
1090
1080
 
1091
- const ghostServiceImproved = await import('./services/ghostServiceImproved.js');
1092
- const updatedMember = await ghostServiceImproved.updateMember(id, updateData);
1081
+ const updatedMember = await ghostService.updateMember(id, updateData);
1093
1082
  console.error(`Member updated successfully. Member ID: ${updatedMember.id}`);
1094
1083
 
1095
1084
  return {
@@ -1128,8 +1117,7 @@ server.tool(
1128
1117
  try {
1129
1118
  await loadServices();
1130
1119
 
1131
- const ghostServiceImproved = await import('./services/ghostServiceImproved.js');
1132
- await ghostServiceImproved.deleteMember(id);
1120
+ await ghostService.deleteMember(id);
1133
1121
  console.error(`Member deleted successfully. Member ID: ${id}`);
1134
1122
 
1135
1123
  return {
@@ -1175,8 +1163,7 @@ server.tool(
1175
1163
  if (input.order !== undefined) options.order = input.order;
1176
1164
  if (input.include !== undefined) options.include = input.include;
1177
1165
 
1178
- const ghostServiceImproved = await import('./services/ghostServiceImproved.js');
1179
- const members = await ghostServiceImproved.getMembers(options);
1166
+ const members = await ghostService.getMembers(options);
1180
1167
  console.error(`Retrieved ${members.length} members from Ghost.`);
1181
1168
 
1182
1169
  return {
@@ -1215,8 +1202,7 @@ server.tool(
1215
1202
  try {
1216
1203
  await loadServices();
1217
1204
 
1218
- const ghostServiceImproved = await import('./services/ghostServiceImproved.js');
1219
- const member = await ghostServiceImproved.getMember({ id, email });
1205
+ const member = await ghostService.getMember({ id, email });
1220
1206
  console.error(`Retrieved member: ${member.email} (ID: ${member.id})`);
1221
1207
 
1222
1208
  return {
@@ -1258,8 +1244,7 @@ server.tool(
1258
1244
  const options = {};
1259
1245
  if (limit !== undefined) options.limit = limit;
1260
1246
 
1261
- const ghostServiceImproved = await import('./services/ghostServiceImproved.js');
1262
- const members = await ghostServiceImproved.searchMembers(query, options);
1247
+ const members = await ghostService.searchMembers(query, options);
1263
1248
  console.error(`Found ${members.length} members matching "${query}".`);
1264
1249
 
1265
1250
  return {
@@ -1313,8 +1298,7 @@ server.tool(
1313
1298
  if (input.filter !== undefined) options.filter = input.filter;
1314
1299
  if (input.order !== undefined) options.order = input.order;
1315
1300
 
1316
- const ghostServiceImproved = await import('./services/ghostServiceImproved.js');
1317
- const newsletters = await ghostServiceImproved.getNewsletters(options);
1301
+ const newsletters = await ghostService.getNewsletters(options);
1318
1302
  console.error(`Retrieved ${newsletters.length} newsletters from Ghost.`);
1319
1303
 
1320
1304
  return {
@@ -1353,8 +1337,7 @@ server.tool(
1353
1337
  try {
1354
1338
  await loadServices();
1355
1339
 
1356
- const ghostServiceImproved = await import('./services/ghostServiceImproved.js');
1357
- const newsletter = await ghostServiceImproved.getNewsletter(id);
1340
+ const newsletter = await ghostService.getNewsletter(id);
1358
1341
  console.error(`Retrieved newsletter: ${newsletter.name} (ID: ${newsletter.id})`);
1359
1342
 
1360
1343
  return {
@@ -1397,7 +1380,6 @@ server.tool(
1397
1380
  try {
1398
1381
  await loadServices();
1399
1382
 
1400
- const newsletterService = await import('./services/newsletterService.js');
1401
1383
  const createdNewsletter = await newsletterService.createNewsletterService(input);
1402
1384
  console.error(`Newsletter created successfully. Newsletter ID: ${createdNewsletter.id}`);
1403
1385
 
@@ -1443,8 +1425,7 @@ server.tool(
1443
1425
 
1444
1426
  const { id, ...updateData } = input;
1445
1427
 
1446
- const ghostServiceImproved = await import('./services/ghostServiceImproved.js');
1447
- const updatedNewsletter = await ghostServiceImproved.updateNewsletter(id, updateData);
1428
+ const updatedNewsletter = await ghostService.updateNewsletter(id, updateData);
1448
1429
  console.error(`Newsletter updated successfully. Newsletter ID: ${updatedNewsletter.id}`);
1449
1430
 
1450
1431
  return {
@@ -1487,8 +1468,7 @@ server.tool(
1487
1468
  try {
1488
1469
  await loadServices();
1489
1470
 
1490
- const ghostServiceImproved = await import('./services/ghostServiceImproved.js');
1491
- await ghostServiceImproved.deleteNewsletter(id);
1471
+ await ghostService.deleteNewsletter(id);
1492
1472
  console.error(`Newsletter deleted successfully. Newsletter ID: ${id}`);
1493
1473
 
1494
1474
  return {
@@ -1534,8 +1514,7 @@ server.tool(
1534
1514
  try {
1535
1515
  await loadServices();
1536
1516
 
1537
- const ghostServiceImproved = await import('./services/ghostServiceImproved.js');
1538
- const tiers = await ghostServiceImproved.getTiers(input);
1517
+ const tiers = await ghostService.getTiers(input);
1539
1518
  console.error(`Retrieved ${tiers.length} tiers`);
1540
1519
 
1541
1520
  return {
@@ -1574,8 +1553,7 @@ server.tool(
1574
1553
  try {
1575
1554
  await loadServices();
1576
1555
 
1577
- const ghostServiceImproved = await import('./services/ghostServiceImproved.js');
1578
- const tier = await ghostServiceImproved.getTier(id);
1556
+ const tier = await ghostService.getTier(id);
1579
1557
  console.error(`Tier retrieved successfully. Tier ID: ${tier.id}`);
1580
1558
 
1581
1559
  return {
@@ -1614,8 +1592,7 @@ server.tool(
1614
1592
  try {
1615
1593
  await loadServices();
1616
1594
 
1617
- const ghostServiceImproved = await import('./services/ghostServiceImproved.js');
1618
- const tier = await ghostServiceImproved.createTier(input);
1595
+ const tier = await ghostService.createTier(input);
1619
1596
  console.error(`Tier created successfully. Tier ID: ${tier.id}`);
1620
1597
 
1621
1598
  return {
@@ -1656,8 +1633,7 @@ server.tool(
1656
1633
 
1657
1634
  const { id, ...updateData } = input;
1658
1635
 
1659
- const ghostServiceImproved = await import('./services/ghostServiceImproved.js');
1660
- const updatedTier = await ghostServiceImproved.updateTier(id, updateData);
1636
+ const updatedTier = await ghostService.updateTier(id, updateData);
1661
1637
  console.error(`Tier updated successfully. Tier ID: ${updatedTier.id}`);
1662
1638
 
1663
1639
  return {
@@ -1696,8 +1672,7 @@ server.tool(
1696
1672
  try {
1697
1673
  await loadServices();
1698
1674
 
1699
- const ghostServiceImproved = await import('./services/ghostServiceImproved.js');
1700
- await ghostServiceImproved.deleteTier(id);
1675
+ await ghostService.deleteTier(id);
1701
1676
  console.error(`Tier deleted successfully. Tier ID: ${id}`);
1702
1677
 
1703
1678
  return {