@jgardner04/ghost-mcp-server 1.12.5 → 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.
- package/package.json +3 -3
- package/src/__tests__/mcp_server.test.js +258 -0
- package/src/__tests__/mcp_server_pages.test.js +21 -6
- package/src/controllers/__tests__/tagController.test.js +118 -3
- package/src/controllers/tagController.js +32 -6
- package/src/mcp_server.js +225 -112
- package/src/resources/ResourceManager.js +6 -2
- package/src/resources/__tests__/ResourceManager.test.js +2 -2
- package/src/schemas/__tests__/tagSchemas.test.js +100 -0
- package/src/schemas/tagSchemas.js +33 -5
- package/src/services/__tests__/ghostService.test.js +30 -23
- package/src/services/__tests__/ghostServiceImproved.tags.test.js +475 -0
- package/src/services/ghostService.js +21 -18
- package/src/services/ghostServiceImproved.js +16 -10
|
@@ -180,27 +180,30 @@ const createTag = async (tagData) => {
|
|
|
180
180
|
};
|
|
181
181
|
|
|
182
182
|
/**
|
|
183
|
-
* Retrieves tags from Ghost
|
|
184
|
-
* @param {
|
|
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 (
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
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(
|
|
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(
|
|
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
|
-
|
|
718
|
+
logger.error('Failed to get tags', { error: error.message });
|
|
713
719
|
throw error;
|
|
714
720
|
}
|
|
715
721
|
}
|