@contentful/mcp-server 1.0.0 → 1.0.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.
Files changed (72) hide show
  1. package/README.md +1 -1
  2. package/package.json +11 -11
  3. package/build/config/contentful.js +0 -19
  4. package/build/config/env.js +0 -25
  5. package/build/config/version.js +0 -2
  6. package/build/index.js +0 -33
  7. package/build/prompts/register.js +0 -1
  8. package/build/resources/register.js +0 -1
  9. package/build/tools/ai-actions/createAiAction.js +0 -55
  10. package/build/tools/ai-actions/deleteAiAction.js +0 -20
  11. package/build/tools/ai-actions/getAiAction.js +0 -20
  12. package/build/tools/ai-actions/getAiActionInvocation.js +0 -21
  13. package/build/tools/ai-actions/invokeAiAction.js +0 -74
  14. package/build/tools/ai-actions/listAiActions.js +0 -65
  15. package/build/tools/ai-actions/publishAiAction.js +0 -34
  16. package/build/tools/ai-actions/register.js +0 -20
  17. package/build/tools/ai-actions/unpublishAiAction.js +0 -28
  18. package/build/tools/ai-actions/updateAiAction.js +0 -64
  19. package/build/tools/assets/deleteAsset.js +0 -20
  20. package/build/tools/assets/getAsset.js +0 -18
  21. package/build/tools/assets/listAssets.js +0 -68
  22. package/build/tools/assets/publishAsset.js +0 -58
  23. package/build/tools/assets/register.js +0 -16
  24. package/build/tools/assets/unpublishAsset.js +0 -58
  25. package/build/tools/assets/updateAsset.js +0 -42
  26. package/build/tools/assets/uploadAsset.js +0 -51
  27. package/build/tools/context/getInitialContextTool.js +0 -41
  28. package/build/tools/context/instructions.js +0 -111
  29. package/build/tools/context/middleware.js +0 -8
  30. package/build/tools/context/register.js +0 -4
  31. package/build/tools/context/store.js +0 -15
  32. package/build/tools/entries/createEntry.js +0 -39
  33. package/build/tools/entries/deleteEntry.js +0 -21
  34. package/build/tools/entries/getEntry.js +0 -18
  35. package/build/tools/entries/publishEntry.js +0 -58
  36. package/build/tools/entries/register.js +0 -16
  37. package/build/tools/entries/searchEntries.js +0 -50
  38. package/build/tools/entries/unpublishEntry.js +0 -58
  39. package/build/tools/entries/updateEntry.js +0 -50
  40. package/build/tools/environments/createEnvironment.js +0 -21
  41. package/build/tools/environments/deleteEnvironment.js +0 -19
  42. package/build/tools/environments/listEnvironments.js +0 -62
  43. package/build/tools/environments/register.js +0 -8
  44. package/build/tools/locales/createLocale.js +0 -49
  45. package/build/tools/locales/deleteLocale.js +0 -21
  46. package/build/tools/locales/getLocale.js +0 -18
  47. package/build/tools/locales/listLocales.js +0 -61
  48. package/build/tools/locales/register.js +0 -12
  49. package/build/tools/locales/updateLocale.js +0 -47
  50. package/build/tools/register.js +0 -20
  51. package/build/tools/spaces/getSpace.js +0 -20
  52. package/build/tools/spaces/listSpaces.js +0 -53
  53. package/build/tools/spaces/register.js +0 -6
  54. package/build/tools/tags/createTag.js +0 -24
  55. package/build/tools/tags/listTags.js +0 -50
  56. package/build/tools/tags/register.js +0 -6
  57. package/build/tools/types/createContentType.js +0 -33
  58. package/build/tools/types/deleteContentType.js +0 -20
  59. package/build/tools/types/getContentType.js +0 -24
  60. package/build/tools/types/listContentTypes.js +0 -59
  61. package/build/tools/types/publishContentType.js +0 -22
  62. package/build/tools/types/register.js +0 -16
  63. package/build/tools/types/unpublishContentType.js +0 -20
  64. package/build/tools/types/updateContentType.js +0 -78
  65. package/build/types/fieldSchema.js +0 -29
  66. package/build/utils/ai-actions.js +0 -46
  67. package/build/utils/bulkOperations.js +0 -94
  68. package/build/utils/formatters.js +0 -39
  69. package/build/utils/getVersion.js +0 -11
  70. package/build/utils/response.js +0 -37
  71. package/build/utils/summarizer.js +0 -39
  72. package/build/utils/tools.js +0 -20
@@ -1,50 +0,0 @@
1
- import { z } from 'zod';
2
- import { createSuccessResponse, withErrorHandling, } from '../../utils/response.js';
3
- import { BaseToolSchema, createToolClient } from '../../utils/tools.js';
4
- import { summarizeData } from '../../utils/summarizer.js';
5
- export const ListTagsToolParams = BaseToolSchema.extend({
6
- limit: z.number().optional().describe('Maximum number of tags to return'),
7
- skip: z.number().optional().describe('Skip this many tags for pagination'),
8
- select: z
9
- .string()
10
- .optional()
11
- .describe('Comma-separated list of fields to return'),
12
- order: z.string().optional().describe('Order tags by this field'),
13
- });
14
- async function tool(args) {
15
- const params = {
16
- spaceId: args.spaceId,
17
- environmentId: args.environmentId,
18
- };
19
- const contentfulClient = createToolClient(args);
20
- const tags = await contentfulClient.tag.getMany({
21
- ...params,
22
- query: {
23
- limit: args.limit || 100,
24
- skip: args.skip || 0,
25
- ...(args.select && { select: args.select }),
26
- ...(args.order && { order: args.order }),
27
- },
28
- });
29
- const summarizedTags = tags.items.map((tag) => ({
30
- id: tag.sys.id,
31
- name: tag.name,
32
- visibility: tag.sys.visibility,
33
- createdAt: tag.sys.createdAt,
34
- updatedAt: tag.sys.updatedAt,
35
- }));
36
- const summarized = summarizeData({
37
- ...tags,
38
- items: summarizedTags,
39
- }, {
40
- maxItems: 100,
41
- remainingMessage: 'To see more tags, please ask me to retrieve the next page using the skip parameter.',
42
- });
43
- return createSuccessResponse('Tags retrieved successfully', {
44
- tags: summarized,
45
- total: tags.total,
46
- limit: tags.limit,
47
- skip: tags.skip,
48
- });
49
- }
50
- export const listTagsTool = withErrorHandling(tool, 'Error listing tags');
@@ -1,6 +0,0 @@
1
- import { listTagsTool, ListTagsToolParams } from './listTags.js';
2
- import { createTagTool, CreateTagToolParams } from './createTag.js';
3
- export function registerTagsTools(server) {
4
- server.tool('list_tags', 'List all tags in a space. Returns all tags that exist in a given environment.', ListTagsToolParams.shape, listTagsTool);
5
- server.tool('create_tag', 'Creates a new tag and returns it. Both name and ID must be unique to each environment. Tag names can be modified after creation, but the tag ID cannot. The tag visibility can be set to public or private, defaulting to private if not specified.', CreateTagToolParams.shape, createTagTool);
6
- }
@@ -1,33 +0,0 @@
1
- import { z } from 'zod';
2
- import { createSuccessResponse, withErrorHandling, } from '../../utils/response.js';
3
- import { BaseToolSchema, createToolClient } from '../../utils/tools.js';
4
- import { FieldSchema } from '../../types/fieldSchema.js';
5
- export const CreateContentTypeToolParams = BaseToolSchema.extend({
6
- name: z.string().describe('The name of the content type'),
7
- displayField: z.string().describe('The field ID to use as the display field'),
8
- description: z
9
- .string()
10
- .optional()
11
- .describe('Description of the content type'),
12
- fields: z
13
- .array(FieldSchema)
14
- .describe('Array of field definitions for the content type'),
15
- });
16
- async function tool(args) {
17
- const params = {
18
- spaceId: args.spaceId,
19
- environmentId: args.environmentId,
20
- };
21
- const contentfulClient = createToolClient(args);
22
- // Create the content type
23
- const contentType = await contentfulClient.contentType.create(params, {
24
- name: args.name,
25
- displayField: args.displayField,
26
- description: args.description,
27
- fields: args.fields,
28
- });
29
- return createSuccessResponse('Content type created successfully', {
30
- contentType,
31
- });
32
- }
33
- export const createContentTypeTool = withErrorHandling(tool, 'Error creating content type');
@@ -1,20 +0,0 @@
1
- import { z } from 'zod';
2
- import { createSuccessResponse, withErrorHandling, } from '../../utils/response.js';
3
- import { BaseToolSchema, createToolClient } from '../../utils/tools.js';
4
- export const DeleteContentTypeToolParams = BaseToolSchema.extend({
5
- contentTypeId: z.string().describe('The ID of the content type to delete'),
6
- });
7
- async function tool(args) {
8
- const params = {
9
- spaceId: args.spaceId,
10
- environmentId: args.environmentId,
11
- contentTypeId: args.contentTypeId,
12
- };
13
- const contentfulClient = createToolClient(args);
14
- // Delete the content type
15
- await contentfulClient.contentType.delete(params);
16
- return createSuccessResponse('Content type deleted successfully', {
17
- contentTypeId: args.contentTypeId,
18
- });
19
- }
20
- export const deleteContentTypeTool = withErrorHandling(tool, 'Error deleting content type');
@@ -1,24 +0,0 @@
1
- import { z } from 'zod';
2
- import { createSuccessResponse, withErrorHandling, } from '../../utils/response.js';
3
- import { BaseToolSchema, createToolClient } from '../../utils/tools.js';
4
- export const GetContentTypeToolParams = BaseToolSchema.extend({
5
- contentTypeId: z
6
- .string()
7
- .describe('The ID of the content type to retrieve details for'),
8
- });
9
- async function tool(args) {
10
- const params = {
11
- spaceId: args.spaceId,
12
- environmentId: args.environmentId,
13
- };
14
- const contentfulClient = createToolClient(args);
15
- // Get the content type details
16
- const contentType = await contentfulClient.contentType.get({
17
- ...params,
18
- contentTypeId: args.contentTypeId,
19
- });
20
- return createSuccessResponse('Content type retrieved successfully', {
21
- contentType,
22
- });
23
- }
24
- export const getContentTypeTool = withErrorHandling(tool, 'Error retrieving content type');
@@ -1,59 +0,0 @@
1
- import { z } from 'zod';
2
- import { createSuccessResponse, withErrorHandling, } from '../../utils/response.js';
3
- import { BaseToolSchema, createToolClient } from '../../utils/tools.js';
4
- import { summarizeData } from '../../utils/summarizer.js';
5
- export const ListContentTypesToolParams = BaseToolSchema.extend({
6
- limit: z
7
- .number()
8
- .optional()
9
- .describe('Maximum number of content types to return (max 10)'),
10
- skip: z
11
- .number()
12
- .optional()
13
- .describe('Skip this many content types for pagination'),
14
- select: z
15
- .string()
16
- .optional()
17
- .describe('Comma-separated list of fields to return'),
18
- include: z
19
- .number()
20
- .optional()
21
- .describe('Include this many levels of linked entries'),
22
- order: z.string().optional().describe('Order content types by this field'),
23
- });
24
- async function tool(args) {
25
- const params = {
26
- spaceId: args.spaceId,
27
- environmentId: args.environmentId,
28
- };
29
- const contentfulClient = createToolClient(args);
30
- const contentTypes = await contentfulClient.contentType.getMany({
31
- ...params,
32
- query: {
33
- limit: Math.min(args.limit || 10, 10),
34
- skip: args.skip || 0,
35
- ...(args.select && { select: args.select }),
36
- ...(args.include && { include: args.include }),
37
- ...(args.order && { order: args.order }),
38
- },
39
- });
40
- const summarizedContentTypes = contentTypes.items.map((contentType) => ({
41
- ...contentType,
42
- id: contentType.sys.id,
43
- fieldsCount: contentType.fields.length,
44
- }));
45
- const summarized = summarizeData({
46
- ...contentTypes,
47
- items: summarizedContentTypes,
48
- }, {
49
- maxItems: 10,
50
- remainingMessage: 'To see more content types, please ask me to retrieve the next page using the skip parameter.',
51
- });
52
- return createSuccessResponse('Content types retrieved successfully', {
53
- contentTypes: summarized,
54
- total: contentTypes.total,
55
- limit: contentTypes.limit,
56
- skip: contentTypes.skip,
57
- });
58
- }
59
- export const listContentTypesTool = withErrorHandling(tool, 'Error listing content types');
@@ -1,22 +0,0 @@
1
- import { z } from 'zod';
2
- import { createSuccessResponse, withErrorHandling, } from '../../utils/response.js';
3
- import { BaseToolSchema, createToolClient } from '../../utils/tools.js';
4
- export const PublishContentTypeToolParams = BaseToolSchema.extend({
5
- contentTypeId: z.string().describe('The ID of the content type to publish'),
6
- });
7
- async function tool(args) {
8
- const params = {
9
- spaceId: args.spaceId,
10
- environmentId: args.environmentId,
11
- contentTypeId: args.contentTypeId,
12
- };
13
- const contentfulClient = createToolClient(args);
14
- // Get the content type first
15
- const currentContentType = await contentfulClient.contentType.get(params);
16
- // Publish the content type
17
- const contentType = await contentfulClient.contentType.publish(params, currentContentType);
18
- return createSuccessResponse('Content type published successfully', {
19
- contentType,
20
- });
21
- }
22
- export const publishContentTypeTool = withErrorHandling(tool, 'Error publishing content type');
@@ -1,16 +0,0 @@
1
- import { getContentTypeTool, GetContentTypeToolParams, } from './getContentType.js';
2
- import { listContentTypesTool, ListContentTypesToolParams, } from './listContentTypes.js';
3
- import { createContentTypeTool, CreateContentTypeToolParams, } from './createContentType.js';
4
- import { updateContentTypeTool, UpdateContentTypeToolParams, } from './updateContentType.js';
5
- import { deleteContentTypeTool, DeleteContentTypeToolParams, } from './deleteContentType.js';
6
- import { publishContentTypeTool, PublishContentTypeToolParams, } from './publishContentType.js';
7
- import { unpublishContentTypeTool, UnpublishContentTypeToolParams, } from './unpublishContentType.js';
8
- export function registerContentTypesTools(server) {
9
- server.tool('get_content_type', 'Get details about a specific Contentful content type', GetContentTypeToolParams.shape, getContentTypeTool);
10
- server.tool('list_content_types', 'List content types in a space. Returns a maximum of 10 items per request. Use skip parameter to paginate through results.', ListContentTypesToolParams.shape, listContentTypesTool);
11
- server.tool('create_content_type', 'Create a new content type', CreateContentTypeToolParams.shape, createContentTypeTool);
12
- server.tool('update_content_type', 'Update an existing content type. The handler will merge your field updates with existing content type data, so you only need to provide the fields and properties you want to change.', UpdateContentTypeToolParams.shape, updateContentTypeTool);
13
- server.tool('delete_content_type', 'Delete a content type', DeleteContentTypeToolParams.shape, deleteContentTypeTool);
14
- server.tool('publish_content_type', 'Publish a content type', PublishContentTypeToolParams.shape, publishContentTypeTool);
15
- server.tool('unpublish_content_type', 'Unpublish a content type', UnpublishContentTypeToolParams.shape, unpublishContentTypeTool);
16
- }
@@ -1,20 +0,0 @@
1
- import { z } from 'zod';
2
- import { createSuccessResponse, withErrorHandling, } from '../../utils/response.js';
3
- import { BaseToolSchema, createToolClient } from '../../utils/tools.js';
4
- export const UnpublishContentTypeToolParams = BaseToolSchema.extend({
5
- contentTypeId: z.string().describe('The ID of the content type to unpublish'),
6
- });
7
- async function tool(args) {
8
- const params = {
9
- spaceId: args.spaceId,
10
- environmentId: args.environmentId,
11
- contentTypeId: args.contentTypeId,
12
- };
13
- const contentfulClient = createToolClient(args);
14
- // Unpublish the content type
15
- const contentType = await contentfulClient.contentType.unpublish(params);
16
- return createSuccessResponse('Content type unpublished successfully', {
17
- contentType,
18
- });
19
- }
20
- export const unpublishContentTypeTool = withErrorHandling(tool, 'Error unpublishing content type');
@@ -1,78 +0,0 @@
1
- import { z } from 'zod';
2
- import { createSuccessResponse, withErrorHandling, } from '../../utils/response.js';
3
- import { BaseToolSchema, createToolClient } from '../../utils/tools.js';
4
- import { FieldSchema } from '../../types/fieldSchema.js';
5
- export const UpdateContentTypeToolParams = BaseToolSchema.extend({
6
- contentTypeId: z.string().describe('The ID of the content type to update'),
7
- name: z.string().optional().describe('The name of the content type'),
8
- displayField: z
9
- .string()
10
- .optional()
11
- .describe('The field ID to use as the display field'),
12
- description: z
13
- .string()
14
- .optional()
15
- .describe('Description of the content type'),
16
- fields: z
17
- .array(FieldSchema)
18
- .optional()
19
- .describe('Array of field definitions for the content type. Will be merged with existing fields.'),
20
- });
21
- async function tool(args) {
22
- const params = {
23
- spaceId: args.spaceId,
24
- environmentId: args.environmentId,
25
- contentTypeId: args.contentTypeId,
26
- };
27
- const contentfulClient = createToolClient(args);
28
- // Get the current content type
29
- const currentContentType = await contentfulClient.contentType.get(params);
30
- // Use the new fields if provided, otherwise keep existing fields
31
- const fields = args.fields || currentContentType.fields;
32
- // If fields are provided, ensure we're not removing any required field metadata
33
- if (args.fields) {
34
- const existingFieldsMap = currentContentType.fields.reduce((acc, field) => {
35
- acc[field.id] = field;
36
- return acc;
37
- }, {});
38
- // Ensure each field has all required metadata
39
- fields.forEach((field) => {
40
- const existingField = existingFieldsMap[field.id];
41
- if (existingField) {
42
- // Preserve validations if not explicitly changed
43
- field.validations = field.validations || existingField.validations;
44
- // Preserve required flag if not explicitly set, default to false
45
- field.required =
46
- field.required !== undefined
47
- ? field.required
48
- : existingField.required || false;
49
- // Preserve link type for Link fields
50
- if (field.type === 'Link' &&
51
- !field.linkType &&
52
- existingField.linkType) {
53
- field.linkType = existingField.linkType;
54
- }
55
- // Preserve items for Array fields
56
- if (field.type === 'Array' && !field.items && existingField.items) {
57
- field.items = existingField.items;
58
- }
59
- }
60
- else {
61
- // For new fields, ensure required is a boolean
62
- field.required = field.required || false;
63
- }
64
- });
65
- }
66
- // Update the content type
67
- const contentType = await contentfulClient.contentType.update(params, {
68
- ...currentContentType,
69
- name: args.name || currentContentType.name,
70
- description: args.description || currentContentType.description,
71
- displayField: args.displayField || currentContentType.displayField,
72
- fields: fields,
73
- });
74
- return createSuccessResponse('Content type updated successfully', {
75
- contentType,
76
- });
77
- }
78
- export const updateContentTypeTool = withErrorHandling(tool, 'Error updating content type');
@@ -1,29 +0,0 @@
1
- import { z } from 'zod';
2
- export const FieldSchema = z.object({
3
- id: z.string().describe('The field ID'),
4
- name: z.string().describe('The field name'),
5
- type: z
6
- .string()
7
- .describe('The field type (e.g., "Symbol", "Text", "Integer", "Boolean", "Date", "Location", "Link", "Array", "Object")'),
8
- required: z.boolean().optional().describe('Whether the field is required'),
9
- localized: z.boolean().optional().describe('Whether the field is localized'),
10
- disabled: z.boolean().optional().describe('Whether the field is disabled'),
11
- omitted: z
12
- .boolean()
13
- .optional()
14
- .describe('Whether the field is omitted from the API response'),
15
- validations: z.array(z.any()).optional().describe('Field validations'),
16
- settings: z.record(z.any()).optional().describe('Field-specific settings'),
17
- linkType: z
18
- .string()
19
- .optional()
20
- .describe('Link type for Link fields (e.g., "Entry", "Asset")'),
21
- items: z
22
- .object({
23
- type: z.string(),
24
- linkType: z.string().optional(),
25
- validations: z.array(z.any()).optional(),
26
- })
27
- .optional()
28
- .describe('Items configuration for Array fields'),
29
- });
@@ -1,46 +0,0 @@
1
- import { z } from 'zod';
2
- export var VariableType;
3
- (function (VariableType) {
4
- VariableType["RESOURCE_LINK"] = "ResourceLink";
5
- VariableType["TEXT"] = "Text";
6
- VariableType["STANDARD_INPUT"] = "StandardInput";
7
- VariableType["LOCALE"] = "Locale";
8
- VariableType["MEDIA_REFERENCE"] = "MediaReference";
9
- VariableType["REFERENCE"] = "Reference";
10
- VariableType["SMART_CONTEXT"] = "SmartContext";
11
- })(VariableType || (VariableType = {}));
12
- export var EntityType;
13
- (function (EntityType) {
14
- EntityType["ENTRY"] = "Entry";
15
- EntityType["ASSET"] = "Asset";
16
- EntityType["RESOURCE_LINK"] = "ResourceLink";
17
- })(EntityType || (EntityType = {}));
18
- // Create Zod schema for VariableValue
19
- export const VariableValue = z.union([
20
- z.object({
21
- id: z.string(),
22
- value: z.string(),
23
- }),
24
- z.object({
25
- id: z.string(),
26
- value: z.object({
27
- entityType: z.nativeEnum(EntityType),
28
- entityId: z.string(),
29
- entityPath: z.string(),
30
- }),
31
- }),
32
- z.object({
33
- id: z.string(),
34
- value: z.object({
35
- entityType: z.literal(EntityType.ENTRY),
36
- entityId: z.string(),
37
- entityPaths: z.array(z.string()),
38
- }),
39
- }),
40
- ]);
41
- export var OutputFormat;
42
- (function (OutputFormat) {
43
- OutputFormat["RICH_TEXT"] = "RichText";
44
- OutputFormat["MARKDOWN"] = "Markdown";
45
- OutputFormat["PLAIN_TEXT"] = "PlainText";
46
- })(OutputFormat || (OutputFormat = {}));
@@ -1,94 +0,0 @@
1
- // Helper function to wait for bulk action completion
2
- export async function waitForBulkActionCompletion(contentfulClient, baseParams, bulkActionId) {
3
- let action = (await contentfulClient.bulkAction.get({
4
- ...baseParams,
5
- bulkActionId,
6
- }));
7
- while (action.sys.status === 'inProgress' ||
8
- action.sys.status === 'created') {
9
- await new Promise((resolve) => setTimeout(resolve, 1000));
10
- action = (await contentfulClient.bulkAction.get({
11
- ...baseParams,
12
- bulkActionId,
13
- }));
14
- }
15
- return action;
16
- }
17
- // Helper function to create versioned links for entries
18
- export async function createEntryVersionedLinks(contentfulClient, baseParams, entryIds) {
19
- return Promise.all(entryIds.map(async (entryId) => {
20
- const currentEntry = await contentfulClient.entry.get({
21
- ...baseParams,
22
- entryId,
23
- });
24
- return {
25
- sys: {
26
- type: 'Link',
27
- linkType: 'Entry',
28
- id: entryId,
29
- version: currentEntry.sys.version,
30
- },
31
- };
32
- }));
33
- }
34
- // Helper function to create unversioned links for entries (used for unpublish operations)
35
- export async function createEntryUnversionedLinks(contentfulClient, baseParams, entryIds) {
36
- // For unpublish operations, we don't need to fetch entries since we only need IDs
37
- // But we should validate they exist first
38
- await Promise.all(entryIds.map(async (entryId) => {
39
- await contentfulClient.entry.get({
40
- ...baseParams,
41
- entryId,
42
- });
43
- }));
44
- return entryIds.map((entryId) => ({
45
- sys: {
46
- type: 'Link',
47
- linkType: 'Entry',
48
- id: entryId,
49
- },
50
- }));
51
- }
52
- // Helper function to create versioned links for assets
53
- export async function createAssetVersionedLinks(contentfulClient, baseParams, assetIds) {
54
- return Promise.all(assetIds.map(async (assetId) => {
55
- const currentAsset = await contentfulClient.asset.get({
56
- ...baseParams,
57
- assetId,
58
- });
59
- return {
60
- sys: {
61
- type: 'Link',
62
- linkType: 'Asset',
63
- id: assetId,
64
- version: currentAsset.sys.version,
65
- },
66
- };
67
- }));
68
- }
69
- // Helper function to create unversioned links for assets (used for unpublish operations)
70
- export async function createAssetUnversionedLinks(contentfulClient, baseParams, assetIds) {
71
- // For unpublish operations, we don't need to fetch assets since we only need IDs
72
- // But we should validate they exist first
73
- await Promise.all(assetIds.map(async (assetId) => {
74
- await contentfulClient.asset.get({
75
- ...baseParams,
76
- assetId,
77
- });
78
- }));
79
- return assetIds.map((assetId) => ({
80
- sys: {
81
- type: 'Link',
82
- linkType: 'Asset',
83
- id: assetId,
84
- },
85
- }));
86
- }
87
- export function createEntitiesCollection(entities) {
88
- return {
89
- sys: {
90
- type: 'Array',
91
- },
92
- items: entities,
93
- };
94
- }
@@ -1,39 +0,0 @@
1
- import { XMLBuilder } from 'fast-xml-parser';
2
- /**
3
- * Formats a response by combining a message with structured data.
4
- * Converts the provided object to XML format and appends the message.
5
- */
6
- export function formatResponse(message, object = {}) {
7
- const formattedObject = {};
8
- for (const [key, value] of Object.entries(object)) {
9
- if (!value)
10
- continue;
11
- formattedObject[key] = value;
12
- }
13
- const builder = new XMLBuilder({
14
- format: true,
15
- indentBy: ' ',
16
- suppressEmptyNode: true,
17
- ignoreAttributes: false,
18
- processEntities: false,
19
- });
20
- const contextString = builder.build(formattedObject);
21
- return `${message}: \n${contextString}\n`;
22
- }
23
- /**
24
- * Ensures that a value is an array.
25
- */
26
- export function ensureArray(value) {
27
- if (value === null || value === undefined) {
28
- return [];
29
- }
30
- return Array.isArray(value) ? value : [value];
31
- }
32
- /**
33
- * Pluralizes a string based on a count.
34
- * Returns singular form for count of 1, plural form otherwise.
35
- */
36
- export function pluralize(n, singular, plural) {
37
- const num = Array.isArray(n) ? n.length : n;
38
- return num === 1 ? singular : plural || `${singular}s`;
39
- }
@@ -1,11 +0,0 @@
1
- import { readFileSync } from 'node:fs';
2
- import { join } from 'node:path';
3
- import { fileURLToPath } from 'node:url';
4
- import { dirname } from 'node:path';
5
- export const getVersion = () => {
6
- const __filename = fileURLToPath(import.meta.url);
7
- const __dirname = dirname(__filename);
8
- const packageJsonPath = join(__dirname, '../../package.json');
9
- const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
10
- return packageJson.version;
11
- };
@@ -1,37 +0,0 @@
1
- import { formatResponse } from './formatters.js';
2
- /**
3
- * Creates a standardized success response
4
- */
5
- export function createSuccessResponse(message, data) {
6
- const text = data ? formatResponse(message, data) : message;
7
- return {
8
- content: [
9
- {
10
- type: 'text',
11
- text,
12
- },
13
- ],
14
- };
15
- }
16
- /**
17
- * Higher-order function that wraps tool handlers with standardized error handling
18
- */
19
- export function withErrorHandling(handler, errorPrefix = 'Error') {
20
- return async (params, extra) => {
21
- try {
22
- return await handler(params, extra);
23
- }
24
- catch (error) {
25
- const errorMessage = error instanceof Error ? error.message : String(error);
26
- return {
27
- isError: true,
28
- content: [
29
- {
30
- type: 'text',
31
- text: `${errorPrefix}: ${errorMessage}`,
32
- },
33
- ],
34
- };
35
- }
36
- };
37
- }
@@ -1,39 +0,0 @@
1
- export const summarizeData = (data, options = {}) => {
2
- const { maxItems = 3, remainingMessage = 'To see more items, please ask me to retrieve the next page.', } = options;
3
- // Handle Contentful-style responses with items and total
4
- if (data && typeof data === 'object' && 'items' in data && 'total' in data) {
5
- const items = data.items;
6
- const total = data.total;
7
- // Type guard to ensure items is an array and total is a number
8
- if (!Array.isArray(items) || typeof total !== 'number') {
9
- return data;
10
- }
11
- if (items.length <= maxItems) {
12
- return data;
13
- }
14
- return {
15
- items: items.slice(0, maxItems),
16
- total: total,
17
- showing: maxItems,
18
- remaining: total - maxItems,
19
- message: remainingMessage,
20
- skip: maxItems, // Add skip value for next page
21
- };
22
- }
23
- // Handle plain arrays
24
- if (Array.isArray(data)) {
25
- if (data.length <= maxItems) {
26
- return data;
27
- }
28
- return {
29
- items: data.slice(0, maxItems),
30
- total: data.length,
31
- showing: maxItems,
32
- remaining: data.length - maxItems,
33
- message: remainingMessage,
34
- skip: maxItems, // Add skip value for next page
35
- };
36
- }
37
- // Return non-array data as-is (cast to expected return type)
38
- return data;
39
- };
@@ -1,20 +0,0 @@
1
- import ctfl from 'contentful-management';
2
- import { getDefaultClientConfig } from '../config/contentful.js';
3
- import { z } from 'zod';
4
- export const BaseToolSchema = z.object({
5
- spaceId: z.string().describe('The ID of the Contentful space'),
6
- environmentId: z.string().describe('The ID of the Contentful environment'),
7
- });
8
- /**
9
- * Creates a Contentful client with the correct configuration based on resource parameters
10
- *
11
- * @param params - Tool parameters that may include a resource
12
- * @returns Configured Contentful client
13
- */
14
- export function createToolClient(params) {
15
- const clientConfig = getDefaultClientConfig();
16
- if (params.spaceId) {
17
- clientConfig.space = params.spaceId;
18
- }
19
- return ctfl.createClient(clientConfig, { type: 'plain' });
20
- }