@jgardner04/ghost-mcp-server 1.11.0 → 1.12.1

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.
@@ -54,25 +54,87 @@ const mockUpdatePost = vi.fn();
54
54
  const mockDeletePost = vi.fn();
55
55
  const mockSearchPosts = vi.fn();
56
56
 
57
- vi.mock('../services/ghostService.js', () => ({
58
- getPosts: (...args) => mockGetPosts(...args),
59
- getPost: (...args) => mockGetPost(...args),
60
- getTags: (...args) => mockGetTags(...args),
61
- createTag: (...args) => mockCreateTag(...args),
62
- uploadImage: (...args) => mockUploadImage(...args),
63
- }));
57
+ // Page mocks
58
+ const mockGetPages = vi.fn();
59
+ const mockGetPage = vi.fn();
60
+ const mockCreatePageService = vi.fn();
61
+ const mockUpdatePage = vi.fn();
62
+ const mockDeletePage = vi.fn();
63
+ const mockSearchPages = vi.fn();
64
+
65
+ // Member mocks
66
+ const mockCreateMember = vi.fn();
67
+ const mockUpdateMember = vi.fn();
68
+ const mockDeleteMember = vi.fn();
69
+ const mockGetMembers = vi.fn();
70
+ const mockGetMember = vi.fn();
71
+ const mockSearchMembers = vi.fn();
72
+
73
+ // Newsletter mocks
74
+ const mockGetNewsletters = vi.fn();
75
+ const mockGetNewsletter = vi.fn();
76
+ const mockCreateNewsletterService = vi.fn();
77
+ const mockUpdateNewsletter = vi.fn();
78
+ const mockDeleteNewsletter = vi.fn();
79
+
80
+ // Tier mocks
81
+ const mockGetTiers = vi.fn();
82
+ const mockGetTier = vi.fn();
83
+ const mockCreateTier = vi.fn();
84
+ const mockUpdateTier = vi.fn();
85
+ const mockDeleteTier = vi.fn();
64
86
 
65
87
  vi.mock('../services/postService.js', () => ({
66
88
  createPostService: (...args) => mockCreatePostService(...args),
67
89
  }));
68
90
 
91
+ vi.mock('../services/pageService.js', () => ({
92
+ createPageService: (...args) => mockCreatePageService(...args),
93
+ }));
94
+
95
+ vi.mock('../services/newsletterService.js', () => ({
96
+ createNewsletterService: (...args) => mockCreateNewsletterService(...args),
97
+ }));
98
+
69
99
  vi.mock('../services/ghostServiceImproved.js', () => ({
100
+ // Posts
101
+ getPosts: (...args) => mockGetPosts(...args),
102
+ getPost: (...args) => mockGetPost(...args),
70
103
  updatePost: (...args) => mockUpdatePost(...args),
71
104
  deletePost: (...args) => mockDeletePost(...args),
72
105
  searchPosts: (...args) => mockSearchPosts(...args),
106
+ // Tags
107
+ getTags: (...args) => mockGetTags(...args),
73
108
  getTag: (...args) => mockGetTag(...args),
109
+ createTag: (...args) => mockCreateTag(...args),
74
110
  updateTag: (...args) => mockUpdateTag(...args),
75
111
  deleteTag: (...args) => mockDeleteTag(...args),
112
+ // Images
113
+ uploadImage: (...args) => mockUploadImage(...args),
114
+ // Pages
115
+ getPages: (...args) => mockGetPages(...args),
116
+ getPage: (...args) => mockGetPage(...args),
117
+ updatePage: (...args) => mockUpdatePage(...args),
118
+ deletePage: (...args) => mockDeletePage(...args),
119
+ searchPages: (...args) => mockSearchPages(...args),
120
+ // Members
121
+ createMember: (...args) => mockCreateMember(...args),
122
+ updateMember: (...args) => mockUpdateMember(...args),
123
+ deleteMember: (...args) => mockDeleteMember(...args),
124
+ getMembers: (...args) => mockGetMembers(...args),
125
+ getMember: (...args) => mockGetMember(...args),
126
+ searchMembers: (...args) => mockSearchMembers(...args),
127
+ // Newsletters
128
+ getNewsletters: (...args) => mockGetNewsletters(...args),
129
+ getNewsletter: (...args) => mockGetNewsletter(...args),
130
+ updateNewsletter: (...args) => mockUpdateNewsletter(...args),
131
+ deleteNewsletter: (...args) => mockDeleteNewsletter(...args),
132
+ // Tiers
133
+ getTiers: (...args) => mockGetTiers(...args),
134
+ getTier: (...args) => mockGetTier(...args),
135
+ createTier: (...args) => mockCreateTier(...args),
136
+ updateTier: (...args) => mockUpdateTier(...args),
137
+ deleteTier: (...args) => mockDeleteTier(...args),
76
138
  }));
77
139
 
78
140
  vi.mock('../services/imageProcessingService.js', () => ({
@@ -91,15 +153,21 @@ vi.mock('axios', () => ({
91
153
  }));
92
154
 
93
155
  // Mock fs
94
- const mockUnlink = vi.fn((path, cb) => cb(null));
95
156
  const mockCreateWriteStream = vi.fn();
96
157
  vi.mock('fs', () => ({
97
158
  default: {
98
- unlink: (...args) => mockUnlink(...args),
99
159
  createWriteStream: (...args) => mockCreateWriteStream(...args),
100
160
  },
101
161
  }));
102
162
 
163
+ // Mock tempFileManager
164
+ const mockTrackTempFile = vi.fn();
165
+ const mockCleanupTempFiles = vi.fn().mockResolvedValue(undefined);
166
+ vi.mock('../utils/tempFileManager.js', () => ({
167
+ trackTempFile: (...args) => mockTrackTempFile(...args),
168
+ cleanupTempFiles: (...args) => mockCleanupTempFiles(...args),
169
+ }));
170
+
103
171
  // Mock os
104
172
  vi.mock('os', () => ({
105
173
  default: { tmpdir: vi.fn().mockReturnValue('/tmp') },
@@ -133,12 +201,13 @@ describe('mcp_server_improved - ghost_get_posts tool', () => {
133
201
  expect(tool).toBeDefined();
134
202
  expect(tool.description).toContain('posts');
135
203
  expect(tool.schema).toBeDefined();
136
- expect(tool.schema.limit).toBeDefined();
137
- expect(tool.schema.page).toBeDefined();
138
- expect(tool.schema.status).toBeDefined();
139
- expect(tool.schema.include).toBeDefined();
140
- expect(tool.schema.filter).toBeDefined();
141
- expect(tool.schema.order).toBeDefined();
204
+ // Zod schemas store field definitions in schema.shape
205
+ expect(tool.schema.shape.limit).toBeDefined();
206
+ expect(tool.schema.shape.page).toBeDefined();
207
+ expect(tool.schema.shape.status).toBeDefined();
208
+ expect(tool.schema.shape.include).toBeDefined();
209
+ expect(tool.schema.shape.filter).toBeDefined();
210
+ expect(tool.schema.shape.order).toBeDefined();
142
211
  });
143
212
 
144
213
  it('should retrieve posts with default options', async () => {
@@ -168,22 +237,24 @@ describe('mcp_server_improved - ghost_get_posts tool', () => {
168
237
 
169
238
  it('should validate limit is between 1 and 100', () => {
170
239
  const tool = mockTools.get('ghost_get_posts');
171
- const schema = tool.schema;
240
+ // Zod schemas store field definitions in schema.shape
241
+ const shape = tool.schema.shape;
172
242
 
173
243
  // Test that limit schema exists and has proper validation
174
- expect(schema.limit).toBeDefined();
175
- expect(() => schema.limit.parse(0)).toThrow();
176
- expect(() => schema.limit.parse(101)).toThrow();
177
- expect(schema.limit.parse(50)).toBe(50);
244
+ expect(shape.limit).toBeDefined();
245
+ expect(() => shape.limit.parse(0)).toThrow();
246
+ expect(() => shape.limit.parse(101)).toThrow();
247
+ expect(shape.limit.parse(50)).toBe(50);
178
248
  });
179
249
 
180
250
  it('should validate page is at least 1', () => {
181
251
  const tool = mockTools.get('ghost_get_posts');
182
- const schema = tool.schema;
252
+ // Zod schemas store field definitions in schema.shape
253
+ const shape = tool.schema.shape;
183
254
 
184
- expect(schema.page).toBeDefined();
185
- expect(() => schema.page.parse(0)).toThrow();
186
- expect(schema.page.parse(1)).toBe(1);
255
+ expect(shape.page).toBeDefined();
256
+ expect(() => shape.page.parse(0)).toThrow();
257
+ expect(shape.page.parse(1)).toBe(1);
187
258
  });
188
259
 
189
260
  it('should pass status filter', async () => {
@@ -198,14 +269,15 @@ describe('mcp_server_improved - ghost_get_posts tool', () => {
198
269
 
199
270
  it('should validate status enum values', () => {
200
271
  const tool = mockTools.get('ghost_get_posts');
201
- const schema = tool.schema;
272
+ // Zod schemas store field definitions in schema.shape
273
+ const shape = tool.schema.shape;
202
274
 
203
- expect(schema.status).toBeDefined();
204
- expect(() => schema.status.parse('invalid')).toThrow();
205
- expect(schema.status.parse('published')).toBe('published');
206
- expect(schema.status.parse('draft')).toBe('draft');
207
- expect(schema.status.parse('scheduled')).toBe('scheduled');
208
- expect(schema.status.parse('all')).toBe('all');
275
+ expect(shape.status).toBeDefined();
276
+ expect(() => shape.status.parse('invalid')).toThrow();
277
+ expect(shape.status.parse('published')).toBe('published');
278
+ expect(shape.status.parse('draft')).toBe('draft');
279
+ expect(shape.status.parse('scheduled')).toBe('scheduled');
280
+ expect(shape.status.parse('all')).toBe('all');
209
281
  });
210
282
 
211
283
  it('should pass include parameter', async () => {
@@ -322,14 +394,15 @@ describe('mcp_server_improved - ghost_get_post tool', () => {
322
394
  expect(tool).toBeDefined();
323
395
  expect(tool.description).toContain('post');
324
396
  expect(tool.schema).toBeDefined();
325
- expect(tool.schema.id).toBeDefined();
326
- expect(tool.schema.slug).toBeDefined();
327
- expect(tool.schema.include).toBeDefined();
397
+ // Zod schemas store field definitions in schema.shape
398
+ expect(tool.schema.shape.id).toBeDefined();
399
+ expect(tool.schema.shape.slug).toBeDefined();
400
+ expect(tool.schema.shape.include).toBeDefined();
328
401
  });
329
402
 
330
403
  it('should retrieve post by ID', async () => {
331
404
  const mockPost = {
332
- id: '123',
405
+ id: '507f1f77bcf86cd799439011',
333
406
  title: 'Test Post',
334
407
  slug: 'test-post',
335
408
  html: '<p>Content</p>',
@@ -338,16 +411,16 @@ describe('mcp_server_improved - ghost_get_post tool', () => {
338
411
  mockGetPost.mockResolvedValue(mockPost);
339
412
 
340
413
  const tool = mockTools.get('ghost_get_post');
341
- const result = await tool.handler({ id: '123' });
414
+ const result = await tool.handler({ id: '507f1f77bcf86cd799439011' });
342
415
 
343
- expect(mockGetPost).toHaveBeenCalledWith('123', {});
344
- expect(result.content[0].text).toContain('"id": "123"');
416
+ expect(mockGetPost).toHaveBeenCalledWith('507f1f77bcf86cd799439011', {});
417
+ expect(result.content[0].text).toContain('"id": "507f1f77bcf86cd799439011"');
345
418
  expect(result.content[0].text).toContain('"title": "Test Post"');
346
419
  });
347
420
 
348
421
  it('should retrieve post by slug', async () => {
349
422
  const mockPost = {
350
- id: '123',
423
+ id: '507f1f77bcf86cd799439011',
351
424
  title: 'Test Post',
352
425
  slug: 'test-post',
353
426
  html: '<p>Content</p>',
@@ -364,7 +437,7 @@ describe('mcp_server_improved - ghost_get_post tool', () => {
364
437
 
365
438
  it('should pass include parameter with ID', async () => {
366
439
  const mockPost = {
367
- id: '123',
440
+ id: '507f1f77bcf86cd799439011',
368
441
  title: 'Post with relations',
369
442
  tags: [{ name: 'tech' }],
370
443
  authors: [{ name: 'John' }],
@@ -372,14 +445,16 @@ describe('mcp_server_improved - ghost_get_post tool', () => {
372
445
  mockGetPost.mockResolvedValue(mockPost);
373
446
 
374
447
  const tool = mockTools.get('ghost_get_post');
375
- await tool.handler({ id: '123', include: 'tags,authors' });
448
+ await tool.handler({ id: '507f1f77bcf86cd799439011', include: 'tags,authors' });
376
449
 
377
- expect(mockGetPost).toHaveBeenCalledWith('123', { include: 'tags,authors' });
450
+ expect(mockGetPost).toHaveBeenCalledWith('507f1f77bcf86cd799439011', {
451
+ include: 'tags,authors',
452
+ });
378
453
  });
379
454
 
380
455
  it('should pass include parameter with slug', async () => {
381
456
  const mockPost = {
382
- id: '123',
457
+ id: '507f1f77bcf86cd799439011',
383
458
  title: 'Post with relations',
384
459
  slug: 'test-post',
385
460
  tags: [{ name: 'tech' }],
@@ -393,20 +468,20 @@ describe('mcp_server_improved - ghost_get_post tool', () => {
393
468
  });
394
469
 
395
470
  it('should prefer ID over slug when both provided', async () => {
396
- const mockPost = { id: '123', title: 'Test Post', slug: 'test-post' };
471
+ const mockPost = { id: '507f1f77bcf86cd799439011', title: 'Test Post', slug: 'test-post' };
397
472
  mockGetPost.mockResolvedValue(mockPost);
398
473
 
399
474
  const tool = mockTools.get('ghost_get_post');
400
- await tool.handler({ id: '123', slug: 'wrong-slug' });
475
+ await tool.handler({ id: '507f1f77bcf86cd799439011', slug: 'wrong-slug' });
401
476
 
402
- expect(mockGetPost).toHaveBeenCalledWith('123', {});
477
+ expect(mockGetPost).toHaveBeenCalledWith('507f1f77bcf86cd799439011', {});
403
478
  });
404
479
 
405
480
  it('should handle not found errors', async () => {
406
481
  mockGetPost.mockRejectedValue(new Error('Post not found'));
407
482
 
408
483
  const tool = mockTools.get('ghost_get_post');
409
- const result = await tool.handler({ id: 'nonexistent' });
484
+ const result = await tool.handler({ id: '507f1f77bcf86cd799439099' });
410
485
 
411
486
  expect(result.isError).toBe(true);
412
487
  expect(result.content[0].text).toContain('Post not found');
@@ -424,7 +499,7 @@ describe('mcp_server_improved - ghost_get_post tool', () => {
424
499
 
425
500
  it('should return formatted JSON response', async () => {
426
501
  const mockPost = {
427
- id: '1',
502
+ id: '507f1f77bcf86cd799439011',
428
503
  uuid: 'uuid-123',
429
504
  title: 'Test Post',
430
505
  slug: 'test-post',
@@ -436,11 +511,11 @@ describe('mcp_server_improved - ghost_get_post tool', () => {
436
511
  mockGetPost.mockResolvedValue(mockPost);
437
512
 
438
513
  const tool = mockTools.get('ghost_get_post');
439
- const result = await tool.handler({ id: '1' });
514
+ const result = await tool.handler({ id: '507f1f77bcf86cd799439011' });
440
515
 
441
516
  expect(result.content).toBeDefined();
442
517
  expect(result.content[0].type).toBe('text');
443
- expect(result.content[0].text).toContain('"id": "1"');
518
+ expect(result.content[0].text).toContain('"id": "507f1f77bcf86cd799439011"');
444
519
  expect(result.content[0].text).toContain('"title": "Test Post"');
445
520
  expect(result.content[0].text).toContain('"status": "published"');
446
521
  });
@@ -472,23 +547,24 @@ describe('mcp_server_improved - ghost_update_post tool', () => {
472
547
  expect(tool).toBeDefined();
473
548
  expect(tool.description).toContain('Updates an existing post');
474
549
  expect(tool.schema).toBeDefined();
475
- expect(tool.schema.id).toBeDefined();
476
- expect(tool.schema.title).toBeDefined();
477
- expect(tool.schema.html).toBeDefined();
478
- expect(tool.schema.status).toBeDefined();
479
- expect(tool.schema.tags).toBeDefined();
480
- expect(tool.schema.feature_image).toBeDefined();
481
- expect(tool.schema.feature_image_alt).toBeDefined();
482
- expect(tool.schema.feature_image_caption).toBeDefined();
483
- expect(tool.schema.meta_title).toBeDefined();
484
- expect(tool.schema.meta_description).toBeDefined();
485
- expect(tool.schema.published_at).toBeDefined();
486
- expect(tool.schema.custom_excerpt).toBeDefined();
550
+ // Zod schemas store field definitions in schema.shape
551
+ expect(tool.schema.shape.id).toBeDefined();
552
+ expect(tool.schema.shape.title).toBeDefined();
553
+ expect(tool.schema.shape.html).toBeDefined();
554
+ expect(tool.schema.shape.status).toBeDefined();
555
+ expect(tool.schema.shape.tags).toBeDefined();
556
+ expect(tool.schema.shape.feature_image).toBeDefined();
557
+ expect(tool.schema.shape.feature_image_alt).toBeDefined();
558
+ expect(tool.schema.shape.feature_image_caption).toBeDefined();
559
+ expect(tool.schema.shape.meta_title).toBeDefined();
560
+ expect(tool.schema.shape.meta_description).toBeDefined();
561
+ expect(tool.schema.shape.published_at).toBeDefined();
562
+ expect(tool.schema.shape.custom_excerpt).toBeDefined();
487
563
  });
488
564
 
489
565
  it('should update post title', async () => {
490
566
  const mockUpdatedPost = {
491
- id: '123',
567
+ id: '507f1f77bcf86cd799439011',
492
568
  title: 'Updated Title',
493
569
  slug: 'test-post',
494
570
  html: '<p>Content</p>',
@@ -498,15 +574,17 @@ describe('mcp_server_improved - ghost_update_post tool', () => {
498
574
  mockUpdatePost.mockResolvedValue(mockUpdatedPost);
499
575
 
500
576
  const tool = mockTools.get('ghost_update_post');
501
- const result = await tool.handler({ id: '123', title: 'Updated Title' });
577
+ const result = await tool.handler({ id: '507f1f77bcf86cd799439011', title: 'Updated Title' });
502
578
 
503
- expect(mockUpdatePost).toHaveBeenCalledWith('123', { title: 'Updated Title' });
579
+ expect(mockUpdatePost).toHaveBeenCalledWith('507f1f77bcf86cd799439011', {
580
+ title: 'Updated Title',
581
+ });
504
582
  expect(result.content[0].text).toContain('"title": "Updated Title"');
505
583
  });
506
584
 
507
585
  it('should update post content', async () => {
508
586
  const mockUpdatedPost = {
509
- id: '123',
587
+ id: '507f1f77bcf86cd799439011',
510
588
  title: 'Test Post',
511
589
  html: '<p>Updated content</p>',
512
590
  status: 'published',
@@ -515,15 +593,20 @@ describe('mcp_server_improved - ghost_update_post tool', () => {
515
593
  mockUpdatePost.mockResolvedValue(mockUpdatedPost);
516
594
 
517
595
  const tool = mockTools.get('ghost_update_post');
518
- const result = await tool.handler({ id: '123', html: '<p>Updated content</p>' });
596
+ const result = await tool.handler({
597
+ id: '507f1f77bcf86cd799439011',
598
+ html: '<p>Updated content</p>',
599
+ });
519
600
 
520
- expect(mockUpdatePost).toHaveBeenCalledWith('123', { html: '<p>Updated content</p>' });
601
+ expect(mockUpdatePost).toHaveBeenCalledWith('507f1f77bcf86cd799439011', {
602
+ html: '<p>Updated content</p>',
603
+ });
521
604
  expect(result.content[0].text).toContain('Updated content');
522
605
  });
523
606
 
524
607
  it('should update post status', async () => {
525
608
  const mockUpdatedPost = {
526
- id: '123',
609
+ id: '507f1f77bcf86cd799439011',
527
610
  title: 'Test Post',
528
611
  html: '<p>Content</p>',
529
612
  status: 'published',
@@ -532,15 +615,17 @@ describe('mcp_server_improved - ghost_update_post tool', () => {
532
615
  mockUpdatePost.mockResolvedValue(mockUpdatedPost);
533
616
 
534
617
  const tool = mockTools.get('ghost_update_post');
535
- const result = await tool.handler({ id: '123', status: 'published' });
618
+ const result = await tool.handler({ id: '507f1f77bcf86cd799439011', status: 'published' });
536
619
 
537
- expect(mockUpdatePost).toHaveBeenCalledWith('123', { status: 'published' });
620
+ expect(mockUpdatePost).toHaveBeenCalledWith('507f1f77bcf86cd799439011', {
621
+ status: 'published',
622
+ });
538
623
  expect(result.content[0].text).toContain('"status": "published"');
539
624
  });
540
625
 
541
626
  it('should update post tags', async () => {
542
627
  const mockUpdatedPost = {
543
- id: '123',
628
+ id: '507f1f77bcf86cd799439011',
544
629
  title: 'Test Post',
545
630
  html: '<p>Content</p>',
546
631
  tags: [{ name: 'tech' }, { name: 'javascript' }],
@@ -549,16 +634,21 @@ describe('mcp_server_improved - ghost_update_post tool', () => {
549
634
  mockUpdatePost.mockResolvedValue(mockUpdatedPost);
550
635
 
551
636
  const tool = mockTools.get('ghost_update_post');
552
- const result = await tool.handler({ id: '123', tags: ['tech', 'javascript'] });
637
+ const result = await tool.handler({
638
+ id: '507f1f77bcf86cd799439011',
639
+ tags: ['tech', 'javascript'],
640
+ });
553
641
 
554
- expect(mockUpdatePost).toHaveBeenCalledWith('123', { tags: ['tech', 'javascript'] });
642
+ expect(mockUpdatePost).toHaveBeenCalledWith('507f1f77bcf86cd799439011', {
643
+ tags: ['tech', 'javascript'],
644
+ });
555
645
  expect(result.content[0].text).toContain('tech');
556
646
  expect(result.content[0].text).toContain('javascript');
557
647
  });
558
648
 
559
649
  it('should update post featured image', async () => {
560
650
  const mockUpdatedPost = {
561
- id: '123',
651
+ id: '507f1f77bcf86cd799439011',
562
652
  title: 'Test Post',
563
653
  feature_image: 'https://example.com/new-image.jpg',
564
654
  feature_image_alt: 'New image',
@@ -568,12 +658,12 @@ describe('mcp_server_improved - ghost_update_post tool', () => {
568
658
 
569
659
  const tool = mockTools.get('ghost_update_post');
570
660
  const result = await tool.handler({
571
- id: '123',
661
+ id: '507f1f77bcf86cd799439011',
572
662
  feature_image: 'https://example.com/new-image.jpg',
573
663
  feature_image_alt: 'New image',
574
664
  });
575
665
 
576
- expect(mockUpdatePost).toHaveBeenCalledWith('123', {
666
+ expect(mockUpdatePost).toHaveBeenCalledWith('507f1f77bcf86cd799439011', {
577
667
  feature_image: 'https://example.com/new-image.jpg',
578
668
  feature_image_alt: 'New image',
579
669
  });
@@ -582,7 +672,7 @@ describe('mcp_server_improved - ghost_update_post tool', () => {
582
672
 
583
673
  it('should update SEO meta fields', async () => {
584
674
  const mockUpdatedPost = {
585
- id: '123',
675
+ id: '507f1f77bcf86cd799439011',
586
676
  title: 'Test Post',
587
677
  meta_title: 'SEO Title',
588
678
  meta_description: 'SEO Description',
@@ -592,12 +682,12 @@ describe('mcp_server_improved - ghost_update_post tool', () => {
592
682
 
593
683
  const tool = mockTools.get('ghost_update_post');
594
684
  const result = await tool.handler({
595
- id: '123',
685
+ id: '507f1f77bcf86cd799439011',
596
686
  meta_title: 'SEO Title',
597
687
  meta_description: 'SEO Description',
598
688
  });
599
689
 
600
- expect(mockUpdatePost).toHaveBeenCalledWith('123', {
690
+ expect(mockUpdatePost).toHaveBeenCalledWith('507f1f77bcf86cd799439011', {
601
691
  meta_title: 'SEO Title',
602
692
  meta_description: 'SEO Description',
603
693
  });
@@ -607,7 +697,7 @@ describe('mcp_server_improved - ghost_update_post tool', () => {
607
697
 
608
698
  it('should update multiple fields at once', async () => {
609
699
  const mockUpdatedPost = {
610
- id: '123',
700
+ id: '507f1f77bcf86cd799439011',
611
701
  title: 'Updated Title',
612
702
  html: '<p>Updated content</p>',
613
703
  status: 'published',
@@ -618,14 +708,14 @@ describe('mcp_server_improved - ghost_update_post tool', () => {
618
708
 
619
709
  const tool = mockTools.get('ghost_update_post');
620
710
  const result = await tool.handler({
621
- id: '123',
711
+ id: '507f1f77bcf86cd799439011',
622
712
  title: 'Updated Title',
623
713
  html: '<p>Updated content</p>',
624
714
  status: 'published',
625
715
  tags: ['tech'],
626
716
  });
627
717
 
628
- expect(mockUpdatePost).toHaveBeenCalledWith('123', {
718
+ expect(mockUpdatePost).toHaveBeenCalledWith('507f1f77bcf86cd799439011', {
629
719
  title: 'Updated Title',
630
720
  html: '<p>Updated content</p>',
631
721
  status: 'published',
@@ -638,7 +728,7 @@ describe('mcp_server_improved - ghost_update_post tool', () => {
638
728
  mockUpdatePost.mockRejectedValue(new Error('Post not found'));
639
729
 
640
730
  const tool = mockTools.get('ghost_update_post');
641
- const result = await tool.handler({ id: 'nonexistent', title: 'New Title' });
731
+ const result = await tool.handler({ id: '507f1f77bcf86cd799439099', title: 'New Title' });
642
732
 
643
733
  expect(result.isError).toBe(true);
644
734
  expect(result.content[0].text).toContain('Post not found');
@@ -648,7 +738,7 @@ describe('mcp_server_improved - ghost_update_post tool', () => {
648
738
  mockUpdatePost.mockRejectedValue(new Error('Validation failed: Title is required'));
649
739
 
650
740
  const tool = mockTools.get('ghost_update_post');
651
- const result = await tool.handler({ id: '123', title: '' });
741
+ const result = await tool.handler({ id: '507f1f77bcf86cd799439011', title: '' });
652
742
 
653
743
  expect(result.isError).toBe(true);
654
744
  expect(result.content[0].text).toContain('Validation failed');
@@ -658,7 +748,7 @@ describe('mcp_server_improved - ghost_update_post tool', () => {
658
748
  mockUpdatePost.mockRejectedValue(new Error('Ghost API error: Server timeout'));
659
749
 
660
750
  const tool = mockTools.get('ghost_update_post');
661
- const result = await tool.handler({ id: '123', title: 'Updated' });
751
+ const result = await tool.handler({ id: '507f1f77bcf86cd799439011', title: 'Updated' });
662
752
 
663
753
  expect(result.isError).toBe(true);
664
754
  expect(result.content[0].text).toContain('Ghost API error');
@@ -666,7 +756,7 @@ describe('mcp_server_improved - ghost_update_post tool', () => {
666
756
 
667
757
  it('should return formatted JSON response', async () => {
668
758
  const mockUpdatedPost = {
669
- id: '123',
759
+ id: '507f1f77bcf86cd799439011',
670
760
  uuid: 'uuid-123',
671
761
  title: 'Updated Post',
672
762
  slug: 'updated-post',
@@ -678,11 +768,11 @@ describe('mcp_server_improved - ghost_update_post tool', () => {
678
768
  mockUpdatePost.mockResolvedValue(mockUpdatedPost);
679
769
 
680
770
  const tool = mockTools.get('ghost_update_post');
681
- const result = await tool.handler({ id: '123', title: 'Updated Post' });
771
+ const result = await tool.handler({ id: '507f1f77bcf86cd799439011', title: 'Updated Post' });
682
772
 
683
773
  expect(result.content).toBeDefined();
684
774
  expect(result.content[0].type).toBe('text');
685
- expect(result.content[0].text).toContain('"id": "123"');
775
+ expect(result.content[0].text).toContain('"id": "507f1f77bcf86cd799439011"');
686
776
  expect(result.content[0].text).toContain('"title": "Updated Post"');
687
777
  expect(result.content[0].text).toContain('"status": "published"');
688
778
  });
@@ -707,17 +797,20 @@ describe('mcp_server_improved - ghost_delete_post tool', () => {
707
797
  expect(tool.description).toContain('Deletes a post');
708
798
  expect(tool.description).toContain('permanent');
709
799
  expect(tool.schema).toBeDefined();
710
- expect(tool.schema.id).toBeDefined();
800
+ // Zod schemas store field definitions in schema.shape
801
+ expect(tool.schema.shape.id).toBeDefined();
711
802
  });
712
803
 
713
804
  it('should delete post by ID', async () => {
714
805
  mockDeletePost.mockResolvedValue({ deleted: true });
715
806
 
716
807
  const tool = mockTools.get('ghost_delete_post');
717
- const result = await tool.handler({ id: '123' });
808
+ const result = await tool.handler({ id: '507f1f77bcf86cd799439011' });
718
809
 
719
- expect(mockDeletePost).toHaveBeenCalledWith('123');
720
- expect(result.content[0].text).toContain('Post 123 has been successfully deleted');
810
+ expect(mockDeletePost).toHaveBeenCalledWith('507f1f77bcf86cd799439011');
811
+ expect(result.content[0].text).toContain(
812
+ 'Post 507f1f77bcf86cd799439011 has been successfully deleted'
813
+ );
721
814
  expect(result.isError).toBeUndefined();
722
815
  });
723
816
 
@@ -725,7 +818,7 @@ describe('mcp_server_improved - ghost_delete_post tool', () => {
725
818
  mockDeletePost.mockRejectedValue(new Error('Post not found'));
726
819
 
727
820
  const tool = mockTools.get('ghost_delete_post');
728
- const result = await tool.handler({ id: 'nonexistent' });
821
+ const result = await tool.handler({ id: '507f1f77bcf86cd799439099' });
729
822
 
730
823
  expect(result.isError).toBe(true);
731
824
  expect(result.content[0].text).toContain('Post not found');
@@ -735,7 +828,7 @@ describe('mcp_server_improved - ghost_delete_post tool', () => {
735
828
  mockDeletePost.mockRejectedValue(new Error('Ghost API error: Permission denied'));
736
829
 
737
830
  const tool = mockTools.get('ghost_delete_post');
738
- const result = await tool.handler({ id: '123' });
831
+ const result = await tool.handler({ id: '507f1f77bcf86cd799439011' });
739
832
 
740
833
  expect(result.isError).toBe(true);
741
834
  expect(result.content[0].text).toContain('Ghost API error');
@@ -745,18 +838,20 @@ describe('mcp_server_improved - ghost_delete_post tool', () => {
745
838
  mockDeletePost.mockResolvedValue({ deleted: true });
746
839
 
747
840
  const tool = mockTools.get('ghost_delete_post');
748
- const result = await tool.handler({ id: 'test-post-id' });
841
+ const result = await tool.handler({ id: '507f1f77bcf86cd799439011' });
749
842
 
750
843
  expect(result.content).toBeDefined();
751
844
  expect(result.content[0].type).toBe('text');
752
- expect(result.content[0].text).toBe('Post test-post-id has been successfully deleted.');
845
+ expect(result.content[0].text).toBe(
846
+ 'Post 507f1f77bcf86cd799439011 has been successfully deleted.'
847
+ );
753
848
  });
754
849
 
755
850
  it('should handle network errors', async () => {
756
851
  mockDeletePost.mockRejectedValue(new Error('Network error: Connection refused'));
757
852
 
758
853
  const tool = mockTools.get('ghost_delete_post');
759
- const result = await tool.handler({ id: '123' });
854
+ const result = await tool.handler({ id: '507f1f77bcf86cd799439012' });
760
855
 
761
856
  expect(result.isError).toBe(true);
762
857
  expect(result.content[0].text).toContain('Network error');
@@ -781,9 +876,10 @@ describe('mcp_server_improved - ghost_search_posts tool', () => {
781
876
  expect(tool).toBeDefined();
782
877
  expect(tool.description).toContain('Search');
783
878
  expect(tool.schema).toBeDefined();
784
- expect(tool.schema.query).toBeDefined();
785
- expect(tool.schema.status).toBeDefined();
786
- expect(tool.schema.limit).toBeDefined();
879
+ // Zod schemas store field definitions in schema.shape
880
+ expect(tool.schema.shape.query).toBeDefined();
881
+ expect(tool.schema.shape.status).toBeDefined();
882
+ expect(tool.schema.shape.limit).toBeDefined();
787
883
  });
788
884
 
789
885
  it('should search posts with query only', async () => {
@@ -825,24 +921,26 @@ describe('mcp_server_improved - ghost_search_posts tool', () => {
825
921
 
826
922
  it('should validate limit is between 1 and 50', () => {
827
923
  const tool = mockTools.get('ghost_search_posts');
828
- const schema = tool.schema;
924
+ // Zod schemas store field definitions in schema.shape
925
+ const shape = tool.schema.shape;
829
926
 
830
- expect(schema.limit).toBeDefined();
831
- expect(() => schema.limit.parse(0)).toThrow();
832
- expect(() => schema.limit.parse(51)).toThrow();
833
- expect(schema.limit.parse(25)).toBe(25);
927
+ expect(shape.limit).toBeDefined();
928
+ expect(() => shape.limit.parse(0)).toThrow();
929
+ expect(() => shape.limit.parse(51)).toThrow();
930
+ expect(shape.limit.parse(25)).toBe(25);
834
931
  });
835
932
 
836
933
  it('should validate status enum values', () => {
837
934
  const tool = mockTools.get('ghost_search_posts');
838
- const schema = tool.schema;
935
+ // Zod schemas store field definitions in schema.shape
936
+ const shape = tool.schema.shape;
839
937
 
840
- expect(schema.status).toBeDefined();
841
- expect(() => schema.status.parse('invalid')).toThrow();
842
- expect(schema.status.parse('published')).toBe('published');
843
- expect(schema.status.parse('draft')).toBe('draft');
844
- expect(schema.status.parse('scheduled')).toBe('scheduled');
845
- expect(schema.status.parse('all')).toBe('all');
938
+ expect(shape.status).toBeDefined();
939
+ expect(() => shape.status.parse('invalid')).toThrow();
940
+ expect(shape.status.parse('published')).toBe('published');
941
+ expect(shape.status.parse('draft')).toBe('draft');
942
+ expect(shape.status.parse('scheduled')).toBe('scheduled');
943
+ expect(shape.status.parse('all')).toBe('all');
846
944
  });
847
945
 
848
946
  it('should pass all parameters combined', async () => {
@@ -863,13 +961,12 @@ describe('mcp_server_improved - ghost_search_posts tool', () => {
863
961
  });
864
962
 
865
963
  it('should handle errors from searchPosts', async () => {
866
- mockSearchPosts.mockRejectedValue(new Error('Search query is required'));
867
-
964
+ // Empty query is now caught by Zod validation
868
965
  const tool = mockTools.get('ghost_search_posts');
869
966
  const result = await tool.handler({ query: '' });
870
967
 
871
968
  expect(result.isError).toBe(true);
872
- expect(result.content[0].text).toContain('Search query is required');
969
+ expect(result.content[0].text).toContain('VALIDATION_ERROR');
873
970
  });
874
971
 
875
972
  it('should handle Ghost API errors', async () => {
@@ -930,14 +1027,15 @@ describe('ghost_get_tag', () => {
930
1027
 
931
1028
  it('should have correct schema with id and slug as optional', () => {
932
1029
  const tool = mockTools.get('ghost_get_tag');
933
- expect(tool.schema.id).toBeDefined();
934
- expect(tool.schema.slug).toBeDefined();
935
- expect(tool.schema.include).toBeDefined();
1030
+ // Zod schemas store field definitions in schema.shape
1031
+ expect(tool.schema.shape.id).toBeDefined();
1032
+ expect(tool.schema.shape.slug).toBeDefined();
1033
+ expect(tool.schema.shape.include).toBeDefined();
936
1034
  });
937
1035
 
938
1036
  it('should retrieve tag by ID', async () => {
939
1037
  const mockTag = {
940
- id: '123',
1038
+ id: '507f1f77bcf86cd799439011',
941
1039
  name: 'Test Tag',
942
1040
  slug: 'test-tag',
943
1041
  description: 'A test tag',
@@ -945,18 +1043,18 @@ describe('ghost_get_tag', () => {
945
1043
  mockGetTag.mockResolvedValue(mockTag);
946
1044
 
947
1045
  const tool = mockTools.get('ghost_get_tag');
948
- const result = await tool.handler({ id: '123' });
1046
+ const result = await tool.handler({ id: '507f1f77bcf86cd799439011' });
949
1047
 
950
- expect(mockGetTag).toHaveBeenCalledWith('123', {});
1048
+ expect(mockGetTag).toHaveBeenCalledWith('507f1f77bcf86cd799439011', {});
951
1049
  expect(result.content).toBeDefined();
952
1050
  expect(result.content[0].type).toBe('text');
953
- expect(result.content[0].text).toContain('"id": "123"');
1051
+ expect(result.content[0].text).toContain('"id": "507f1f77bcf86cd799439011"');
954
1052
  expect(result.content[0].text).toContain('"name": "Test Tag"');
955
1053
  });
956
1054
 
957
1055
  it('should retrieve tag by slug', async () => {
958
1056
  const mockTag = {
959
- id: '123',
1057
+ id: '507f1f77bcf86cd799439011',
960
1058
  name: 'Test Tag',
961
1059
  slug: 'test-tag',
962
1060
  description: 'A test tag',
@@ -972,7 +1070,7 @@ describe('ghost_get_tag', () => {
972
1070
 
973
1071
  it('should support include parameter for post count', async () => {
974
1072
  const mockTag = {
975
- id: '123',
1073
+ id: '507f1f77bcf86cd799439011',
976
1074
  name: 'Test Tag',
977
1075
  slug: 'test-tag',
978
1076
  count: { posts: 5 },
@@ -980,9 +1078,9 @@ describe('ghost_get_tag', () => {
980
1078
  mockGetTag.mockResolvedValue(mockTag);
981
1079
 
982
1080
  const tool = mockTools.get('ghost_get_tag');
983
- const result = await tool.handler({ id: '123', include: 'count.posts' });
1081
+ const result = await tool.handler({ id: '507f1f77bcf86cd799439011', include: 'count.posts' });
984
1082
 
985
- expect(mockGetTag).toHaveBeenCalledWith('123', { include: 'count.posts' });
1083
+ expect(mockGetTag).toHaveBeenCalledWith('507f1f77bcf86cd799439011', { include: 'count.posts' });
986
1084
  expect(result.content[0].text).toContain('"count"');
987
1085
  });
988
1086
 
@@ -999,7 +1097,7 @@ describe('ghost_get_tag', () => {
999
1097
  mockGetTag.mockRejectedValue(new Error('Tag not found'));
1000
1098
 
1001
1099
  const tool = mockTools.get('ghost_get_tag');
1002
- const result = await tool.handler({ id: '999' });
1100
+ const result = await tool.handler({ id: '507f1f77bcf86cd799439099' });
1003
1101
 
1004
1102
  expect(result.isError).toBe(true);
1005
1103
  expect(result.content[0].text).toContain('Tag not found');
@@ -1022,48 +1120,54 @@ describe('ghost_update_tag', () => {
1022
1120
 
1023
1121
  it('should have correct schema with all update fields', () => {
1024
1122
  const tool = mockTools.get('ghost_update_tag');
1025
- expect(tool.schema.id).toBeDefined();
1026
- expect(tool.schema.name).toBeDefined();
1027
- expect(tool.schema.slug).toBeDefined();
1028
- expect(tool.schema.description).toBeDefined();
1029
- expect(tool.schema.feature_image).toBeDefined();
1030
- expect(tool.schema.meta_title).toBeDefined();
1031
- expect(tool.schema.meta_description).toBeDefined();
1123
+ // Zod schemas store field definitions in schema.shape
1124
+ expect(tool.schema.shape.id).toBeDefined();
1125
+ expect(tool.schema.shape.name).toBeDefined();
1126
+ expect(tool.schema.shape.slug).toBeDefined();
1127
+ expect(tool.schema.shape.description).toBeDefined();
1128
+ expect(tool.schema.shape.feature_image).toBeDefined();
1129
+ expect(tool.schema.shape.meta_title).toBeDefined();
1130
+ expect(tool.schema.shape.meta_description).toBeDefined();
1032
1131
  });
1033
1132
 
1034
1133
  it('should update tag name', async () => {
1035
1134
  const mockUpdatedTag = {
1036
- id: '123',
1135
+ id: '507f1f77bcf86cd799439011',
1037
1136
  name: 'Updated Tag',
1038
1137
  slug: 'updated-tag',
1039
1138
  };
1040
1139
  mockUpdateTag.mockResolvedValue(mockUpdatedTag);
1041
1140
 
1042
1141
  const tool = mockTools.get('ghost_update_tag');
1043
- const result = await tool.handler({ id: '123', name: 'Updated Tag' });
1142
+ const result = await tool.handler({ id: '507f1f77bcf86cd799439011', name: 'Updated Tag' });
1044
1143
 
1045
- expect(mockUpdateTag).toHaveBeenCalledWith('123', { name: 'Updated Tag' });
1144
+ expect(mockUpdateTag).toHaveBeenCalledWith('507f1f77bcf86cd799439011', { name: 'Updated Tag' });
1046
1145
  expect(result.content[0].text).toContain('"name": "Updated Tag"');
1047
1146
  });
1048
1147
 
1049
1148
  it('should update tag description', async () => {
1050
1149
  const mockUpdatedTag = {
1051
- id: '123',
1150
+ id: '507f1f77bcf86cd799439011',
1052
1151
  name: 'Test Tag',
1053
1152
  description: 'New description',
1054
1153
  };
1055
1154
  mockUpdateTag.mockResolvedValue(mockUpdatedTag);
1056
1155
 
1057
1156
  const tool = mockTools.get('ghost_update_tag');
1058
- const result = await tool.handler({ id: '123', description: 'New description' });
1157
+ const result = await tool.handler({
1158
+ id: '507f1f77bcf86cd799439011',
1159
+ description: 'New description',
1160
+ });
1059
1161
 
1060
- expect(mockUpdateTag).toHaveBeenCalledWith('123', { description: 'New description' });
1162
+ expect(mockUpdateTag).toHaveBeenCalledWith('507f1f77bcf86cd799439011', {
1163
+ description: 'New description',
1164
+ });
1061
1165
  expect(result.content[0].text).toContain('"description": "New description"');
1062
1166
  });
1063
1167
 
1064
1168
  it('should update multiple fields at once', async () => {
1065
1169
  const mockUpdatedTag = {
1066
- id: '123',
1170
+ id: '507f1f77bcf86cd799439011',
1067
1171
  name: 'Updated Tag',
1068
1172
  slug: 'updated-tag',
1069
1173
  description: 'Updated description',
@@ -1073,13 +1177,13 @@ describe('ghost_update_tag', () => {
1073
1177
 
1074
1178
  const tool = mockTools.get('ghost_update_tag');
1075
1179
  await tool.handler({
1076
- id: '123',
1180
+ id: '507f1f77bcf86cd799439011',
1077
1181
  name: 'Updated Tag',
1078
1182
  description: 'Updated description',
1079
1183
  meta_title: 'Updated Meta',
1080
1184
  });
1081
1185
 
1082
- expect(mockUpdateTag).toHaveBeenCalledWith('123', {
1186
+ expect(mockUpdateTag).toHaveBeenCalledWith('507f1f77bcf86cd799439011', {
1083
1187
  name: 'Updated Tag',
1084
1188
  description: 'Updated description',
1085
1189
  meta_title: 'Updated Meta',
@@ -1088,7 +1192,7 @@ describe('ghost_update_tag', () => {
1088
1192
 
1089
1193
  it('should update tag feature image', async () => {
1090
1194
  const mockUpdatedTag = {
1091
- id: '123',
1195
+ id: '507f1f77bcf86cd799439011',
1092
1196
  name: 'Test Tag',
1093
1197
  feature_image: 'https://example.com/image.jpg',
1094
1198
  };
@@ -1096,11 +1200,11 @@ describe('ghost_update_tag', () => {
1096
1200
 
1097
1201
  const tool = mockTools.get('ghost_update_tag');
1098
1202
  await tool.handler({
1099
- id: '123',
1203
+ id: '507f1f77bcf86cd799439011',
1100
1204
  feature_image: 'https://example.com/image.jpg',
1101
1205
  });
1102
1206
 
1103
- expect(mockUpdateTag).toHaveBeenCalledWith('123', {
1207
+ expect(mockUpdateTag).toHaveBeenCalledWith('507f1f77bcf86cd799439011', {
1104
1208
  feature_image: 'https://example.com/image.jpg',
1105
1209
  });
1106
1210
  });
@@ -1110,14 +1214,14 @@ describe('ghost_update_tag', () => {
1110
1214
  const result = await tool.handler({ name: 'Test' });
1111
1215
 
1112
1216
  expect(result.isError).toBe(true);
1113
- expect(result.content[0].text).toContain('Tag ID is required');
1217
+ expect(result.content[0].text).toContain('VALIDATION_ERROR');
1114
1218
  });
1115
1219
 
1116
1220
  it('should handle validation error', async () => {
1117
1221
  mockUpdateTag.mockRejectedValue(new Error('Validation failed'));
1118
1222
 
1119
1223
  const tool = mockTools.get('ghost_update_tag');
1120
- const result = await tool.handler({ id: '123', name: '' });
1224
+ const result = await tool.handler({ id: '507f1f77bcf86cd799439011', name: '' });
1121
1225
 
1122
1226
  expect(result.isError).toBe(true);
1123
1227
  expect(result.content[0].text).toContain('Validation failed');
@@ -1127,7 +1231,7 @@ describe('ghost_update_tag', () => {
1127
1231
  mockUpdateTag.mockRejectedValue(new Error('Tag not found'));
1128
1232
 
1129
1233
  const tool = mockTools.get('ghost_update_tag');
1130
- const result = await tool.handler({ id: '999', name: 'Test' });
1234
+ const result = await tool.handler({ id: '507f1f77bcf86cd799439099', name: 'Test' });
1131
1235
 
1132
1236
  expect(result.isError).toBe(true);
1133
1237
  expect(result.content[0].text).toContain('Tag not found');
@@ -1150,16 +1254,17 @@ describe('ghost_delete_tag', () => {
1150
1254
 
1151
1255
  it('should have correct schema with id field', () => {
1152
1256
  const tool = mockTools.get('ghost_delete_tag');
1153
- expect(tool.schema.id).toBeDefined();
1257
+ // Zod schemas store field definitions in schema.shape
1258
+ expect(tool.schema.shape.id).toBeDefined();
1154
1259
  });
1155
1260
 
1156
1261
  it('should delete tag successfully', async () => {
1157
1262
  mockDeleteTag.mockResolvedValue({ success: true });
1158
1263
 
1159
1264
  const tool = mockTools.get('ghost_delete_tag');
1160
- const result = await tool.handler({ id: '123' });
1265
+ const result = await tool.handler({ id: '507f1f77bcf86cd799439011' });
1161
1266
 
1162
- expect(mockDeleteTag).toHaveBeenCalledWith('123');
1267
+ expect(mockDeleteTag).toHaveBeenCalledWith('507f1f77bcf86cd799439011');
1163
1268
  expect(result.content[0].text).toContain('successfully deleted');
1164
1269
  expect(result.isError).toBeUndefined();
1165
1270
  });
@@ -1169,14 +1274,14 @@ describe('ghost_delete_tag', () => {
1169
1274
  const result = await tool.handler({});
1170
1275
 
1171
1276
  expect(result.isError).toBe(true);
1172
- expect(result.content[0].text).toContain('Tag ID is required');
1277
+ expect(result.content[0].text).toContain('VALIDATION_ERROR');
1173
1278
  });
1174
1279
 
1175
1280
  it('should handle not found error', async () => {
1176
1281
  mockDeleteTag.mockRejectedValue(new Error('Tag not found'));
1177
1282
 
1178
1283
  const tool = mockTools.get('ghost_delete_tag');
1179
- const result = await tool.handler({ id: '999' });
1284
+ const result = await tool.handler({ id: '507f1f77bcf86cd799439099' });
1180
1285
 
1181
1286
  expect(result.isError).toBe(true);
1182
1287
  expect(result.content[0].text).toContain('Tag not found');
@@ -1186,7 +1291,7 @@ describe('ghost_delete_tag', () => {
1186
1291
  mockDeleteTag.mockRejectedValue(new Error('Failed to delete tag'));
1187
1292
 
1188
1293
  const tool = mockTools.get('ghost_delete_tag');
1189
- const result = await tool.handler({ id: '123' });
1294
+ const result = await tool.handler({ id: '507f1f77bcf86cd799439011' });
1190
1295
 
1191
1296
  expect(result.isError).toBe(true);
1192
1297
  expect(result.content[0].text).toContain('Failed to delete tag');