@jgardner04/ghost-mcp-server 1.13.0 → 1.13.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.
@@ -180,27 +180,30 @@ const createTag = async (tagData) => {
180
180
  };
181
181
 
182
182
  /**
183
- * Retrieves tags from Ghost, optionally filtering by name.
184
- * @param {string} [name] - Optional tag name to filter by.
183
+ * Retrieves tags from Ghost with optional filtering.
184
+ * @param {object} [options={}] - Query options for filtering and pagination.
185
+ * @param {number} [options.limit] - Maximum number of tags to return (default: 15).
186
+ * @param {string} [options.filter] - NQL filter string for advanced filtering.
187
+ * @param {string} [options.order] - Order string for sorting results.
188
+ * @param {string} [options.include] - Include string for related data.
185
189
  * @returns {Promise<Array<object>>} An array of tag objects.
186
190
  */
187
- const getTags = async (name) => {
188
- const options = {
189
- limit: 'all', // Get all tags
190
- };
191
-
192
- // Safely construct filter to prevent injection
193
- if (name) {
194
- // Additional validation: only allow alphanumeric, spaces, hyphens, underscores
195
- if (!/^[a-zA-Z0-9\s\-_]+$/.test(name)) {
196
- throw new Error('Tag name contains invalid characters');
197
- }
198
- // Escape single quotes and backslashes to prevent injection
199
- const safeName = name.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
200
- options.filter = `name:'${safeName}'`;
191
+ const getTags = async (options = {}) => {
192
+ try {
193
+ const tags = await handleApiRequest(
194
+ 'tags',
195
+ 'browse',
196
+ {},
197
+ {
198
+ limit: 15,
199
+ ...options,
200
+ }
201
+ );
202
+ return tags || [];
203
+ } catch (error) {
204
+ logger.error('Failed to get tags', { error: error.message });
205
+ throw error;
201
206
  }
202
-
203
- return handleApiRequest('tags', 'browse', {}, options);
204
207
  };
205
208
 
206
209
  // Add other content management functions here (createTag, etc.)
@@ -11,9 +11,12 @@ import {
11
11
  CircuitBreaker,
12
12
  retryWithBackoff,
13
13
  } from '../errors/index.js';
14
+ import { createContextLogger } from '../utils/logger.js';
14
15
 
15
16
  dotenv.config();
16
17
 
18
+ const logger = createContextLogger('ghost-service-improved');
19
+
17
20
  const { GHOST_ADMIN_API_URL, GHOST_ADMIN_API_KEY } = process.env;
18
21
 
19
22
  // Validate configuration at startup
@@ -685,8 +688,8 @@ export async function createTag(tagData) {
685
688
  if (error instanceof GhostAPIError && error.ghostStatusCode === 422) {
686
689
  // Check if it's a duplicate tag error
687
690
  if (error.originalError.includes('already exists')) {
688
- // Try to fetch the existing tag
689
- const existingTags = await getTags(tagData.name);
691
+ // Try to fetch the existing tag by name filter
692
+ const existingTags = await getTags({ filter: `name:'${tagData.name}'` });
690
693
  if (existingTags.length > 0) {
691
694
  return existingTags[0]; // Return existing tag instead of failing
692
695
  }
@@ -699,17 +702,20 @@ export async function createTag(tagData) {
699
702
  }
700
703
  }
701
704
 
702
- export async function getTags(name) {
703
- const options = {
704
- limit: 'all',
705
- ...(name && { filter: `name:'${name}'` }),
706
- };
707
-
705
+ export async function getTags(options = {}) {
708
706
  try {
709
- const tags = await handleApiRequest('tags', 'browse', {}, options);
707
+ const tags = await handleApiRequest(
708
+ 'tags',
709
+ 'browse',
710
+ {},
711
+ {
712
+ limit: 15,
713
+ ...options,
714
+ }
715
+ );
710
716
  return tags || [];
711
717
  } catch (error) {
712
- console.error('Failed to get tags:', error);
718
+ logger.error('Failed to get tags', { error: error.message });
713
719
  throw error;
714
720
  }
715
721
  }