@directus/api 32.1.0 → 32.2.0

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 (175) hide show
  1. package/dist/ai/chat/constants/system-prompt.d.ts +1 -0
  2. package/dist/ai/chat/constants/system-prompt.js +51 -0
  3. package/dist/ai/chat/controllers/chat.post.d.ts +2 -0
  4. package/dist/ai/chat/controllers/chat.post.js +47 -0
  5. package/dist/ai/chat/lib/create-ui-stream.d.ts +15 -0
  6. package/dist/ai/chat/lib/create-ui-stream.js +42 -0
  7. package/dist/ai/chat/middleware/load-settings.d.ts +2 -0
  8. package/dist/ai/chat/middleware/load-settings.js +18 -0
  9. package/dist/ai/chat/models/chat-request.d.ts +34 -0
  10. package/dist/ai/chat/models/chat-request.js +26 -0
  11. package/dist/ai/chat/models/providers.d.ts +9 -0
  12. package/dist/ai/chat/models/providers.js +9 -0
  13. package/dist/ai/chat/router.d.ts +1 -0
  14. package/dist/ai/chat/router.js +5 -0
  15. package/dist/ai/chat/utils/chat-request-tool-to-ai-sdk-tool.d.ts +9 -0
  16. package/dist/ai/chat/utils/chat-request-tool-to-ai-sdk-tool.js +38 -0
  17. package/dist/ai/chat/utils/fix-error-tool-calls.d.ts +12 -0
  18. package/dist/ai/chat/utils/fix-error-tool-calls.js +30 -0
  19. package/dist/ai/chat/utils/parse-json-schema-7.d.ts +13 -0
  20. package/dist/ai/chat/utils/parse-json-schema-7.js +75 -0
  21. package/dist/{mcp → ai/mcp}/server.d.ts +13 -16
  22. package/dist/{mcp → ai/mcp}/server.js +4 -13
  23. package/dist/ai/mcp/types.d.ts +15 -0
  24. package/dist/{mcp/tools/assets.js → ai/tools/assets/index.js} +8 -5
  25. package/dist/{mcp/tools/collections.js → ai/tools/collections/index.js} +7 -4
  26. package/dist/{mcp/tools/fields.js → ai/tools/fields/index.js} +12 -9
  27. package/dist/{mcp/tools/files.js → ai/tools/files/index.js} +11 -5
  28. package/dist/{mcp/tools/flows.js → ai/tools/flows/index.js} +11 -5
  29. package/dist/{mcp/tools/folders.js → ai/tools/folders/index.js} +12 -5
  30. package/dist/ai/tools/index.d.ts +15 -0
  31. package/dist/ai/tools/index.js +29 -0
  32. package/dist/{mcp/tools/items.js → ai/tools/items/index.js} +13 -6
  33. package/dist/{mcp/tools/prompts/items.md → ai/tools/items/prompt.md} +19 -15
  34. package/dist/{mcp/tools/operations.d.ts → ai/tools/operations/index.d.ts} +46 -0
  35. package/dist/{mcp/tools/operations.js → ai/tools/operations/index.js} +12 -5
  36. package/dist/{mcp/tools/relations.js → ai/tools/relations/index.js} +7 -4
  37. package/dist/{mcp/tools/schema.d.ts → ai/tools/schema/index.d.ts} +1 -1
  38. package/dist/{mcp/tools/schema.js → ai/tools/schema/index.js} +9 -6
  39. package/dist/{mcp/tools/system.js → ai/tools/system/index.js} +7 -4
  40. package/dist/{mcp/tools/trigger-flow.js → ai/tools/trigger-flow/index.js} +8 -5
  41. package/dist/{mcp → ai/tools}/types.d.ts +1 -17
  42. package/dist/ai/tools/utils.d.ts +9 -0
  43. package/dist/ai/tools/utils.js +17 -0
  44. package/dist/app.js +5 -0
  45. package/dist/auth/drivers/oauth2.d.ts +2 -1
  46. package/dist/auth/drivers/oauth2.js +17 -22
  47. package/dist/auth/drivers/openid.d.ts +2 -1
  48. package/dist/auth/drivers/openid.js +13 -18
  49. package/dist/auth/drivers/saml.js +6 -3
  50. package/dist/controllers/assets.js +39 -2
  51. package/dist/controllers/mcp.js +1 -1
  52. package/dist/database/migrations/20240806A-permissions-policies.js +2 -2
  53. package/dist/database/migrations/20251103A-add-ai-settings.d.ts +3 -0
  54. package/dist/database/migrations/20251103A-add-ai-settings.js +14 -0
  55. package/dist/database/run-ast/run-ast.js +1 -1
  56. package/dist/extensions/lib/installation/manager.js +5 -9
  57. package/dist/extensions/lib/sync/status.d.ts +11 -0
  58. package/dist/extensions/lib/sync/status.js +34 -0
  59. package/dist/extensions/lib/sync/sync.d.ts +6 -0
  60. package/dist/extensions/lib/sync/sync.js +90 -0
  61. package/dist/extensions/lib/sync/tracker.d.ts +18 -0
  62. package/dist/extensions/lib/sync/tracker.js +71 -0
  63. package/dist/extensions/lib/sync/utils.d.ts +24 -0
  64. package/dist/extensions/lib/sync/utils.js +62 -0
  65. package/dist/extensions/manager.d.ts +8 -4
  66. package/dist/extensions/manager.js +30 -13
  67. package/dist/middleware/respond.js +2 -2
  68. package/dist/permissions/lib/fetch-policies.d.ts +1 -1
  69. package/dist/permissions/lib/fetch-roles-tree.d.ts +6 -3
  70. package/dist/permissions/lib/fetch-roles-tree.js +5 -27
  71. package/dist/permissions/modules/fetch-global-access/fetch-global-access.d.ts +9 -7
  72. package/dist/permissions/modules/fetch-global-access/fetch-global-access.js +17 -9
  73. package/dist/permissions/modules/fetch-policies-ip-access/fetch-policies-ip-access.d.ts +1 -1
  74. package/dist/permissions/utils/fetch-raw-permissions.d.ts +1 -1
  75. package/dist/permissions/utils/fetch-share-info.d.ts +1 -1
  76. package/dist/permissions/utils/fetch-share-info.js +1 -1
  77. package/dist/permissions/utils/filter-policies-by-ip.js +1 -1
  78. package/dist/permissions/utils/get-permissions-for-share.js +8 -8
  79. package/dist/permissions/utils/with-cache.d.ts +8 -6
  80. package/dist/permissions/utils/with-cache.js +12 -10
  81. package/dist/request/is-denied-ip.js +2 -2
  82. package/dist/services/assets/name-deduper.d.ts +7 -0
  83. package/dist/services/assets/name-deduper.js +23 -0
  84. package/dist/services/assets.d.ts +15 -2
  85. package/dist/services/assets.js +98 -5
  86. package/dist/services/authentication.js +4 -4
  87. package/dist/services/comments.js +2 -2
  88. package/dist/services/extensions.js +4 -0
  89. package/dist/services/folders.d.ts +27 -2
  90. package/dist/services/folders.js +75 -0
  91. package/dist/services/graphql/resolvers/query.js +1 -1
  92. package/dist/services/import-export.d.ts +1 -1
  93. package/dist/services/import-export.js +4 -5
  94. package/dist/services/notifications.js +2 -2
  95. package/dist/services/payload.js +20 -0
  96. package/dist/services/roles.js +2 -2
  97. package/dist/services/tus/server.js +3 -3
  98. package/dist/telemetry/utils/get-settings.d.ts +15 -0
  99. package/dist/telemetry/utils/get-settings.js +25 -9
  100. package/dist/test-utils/README.md +95 -24
  101. package/dist/test-utils/cache.d.ts +2 -2
  102. package/dist/test-utils/cache.js +2 -2
  103. package/dist/test-utils/{fields-service.d.ts → services/fields-service.d.ts} +1 -1
  104. package/dist/test-utils/{fields-service.js → services/fields-service.js} +3 -2
  105. package/dist/test-utils/services/files-service.d.ts +28 -0
  106. package/dist/test-utils/services/files-service.js +34 -0
  107. package/dist/test-utils/services/folders-service.d.ts +28 -0
  108. package/dist/test-utils/services/folders-service.js +33 -0
  109. package/dist/utils/encrypt.d.ts +2 -0
  110. package/dist/utils/encrypt.js +64 -0
  111. package/dist/utils/get-accountability-for-role.js +2 -2
  112. package/dist/utils/get-accountability-for-token.js +4 -4
  113. package/dist/utils/get-cache-key.js +2 -2
  114. package/dist/utils/is-login-redirect-allowed.d.ts +4 -0
  115. package/dist/{auth/utils → utils}/is-login-redirect-allowed.js +8 -16
  116. package/dist/utils/require-text.d.ts +1 -0
  117. package/dist/utils/require-text.js +4 -0
  118. package/dist/utils/require-yaml.js +2 -2
  119. package/package.json +31 -25
  120. package/dist/auth/utils/generate-callback-url.d.ts +0 -8
  121. package/dist/auth/utils/generate-callback-url.js +0 -11
  122. package/dist/auth/utils/is-login-redirect-allowed.d.ts +0 -8
  123. package/dist/extensions/lib/sync-extensions.d.ts +0 -3
  124. package/dist/extensions/lib/sync-extensions.js +0 -70
  125. package/dist/extensions/lib/sync-status.d.ts +0 -10
  126. package/dist/extensions/lib/sync-status.js +0 -27
  127. package/dist/mcp/tools/index.d.ts +0 -15
  128. package/dist/mcp/tools/index.js +0 -29
  129. package/dist/mcp/tools/prompts/index.d.ts +0 -16
  130. package/dist/mcp/tools/prompts/index.js +0 -19
  131. package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-roles.d.ts +0 -5
  132. package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-roles.js +0 -7
  133. package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-user.d.ts +0 -5
  134. package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-user.js +0 -10
  135. package/dist/permissions/modules/fetch-global-access/types.d.ts +0 -4
  136. package/dist/permissions/modules/fetch-global-access/utils/fetch-global-access-for-query.d.ts +0 -4
  137. package/dist/permissions/modules/fetch-global-access/utils/fetch-global-access-for-query.js +0 -27
  138. package/dist/utils/get-date-formatted.d.ts +0 -1
  139. package/dist/utils/get-date-formatted.js +0 -10
  140. package/dist/utils/ip-in-networks.d.ts +0 -6
  141. package/dist/utils/ip-in-networks.js +0 -13
  142. /package/dist/{mcp → ai/mcp}/index.d.ts +0 -0
  143. /package/dist/{mcp → ai/mcp}/index.js +0 -0
  144. /package/dist/{mcp → ai/mcp}/transport.d.ts +0 -0
  145. /package/dist/{mcp → ai/mcp}/transport.js +0 -0
  146. /package/dist/{mcp → ai/mcp}/types.js +0 -0
  147. /package/dist/{mcp/tools/assets.d.ts → ai/tools/assets/index.d.ts} +0 -0
  148. /package/dist/{mcp/tools/prompts/assets.md → ai/tools/assets/prompt.md} +0 -0
  149. /package/dist/{mcp/tools/collections.d.ts → ai/tools/collections/index.d.ts} +0 -0
  150. /package/dist/{mcp/tools/prompts/collections.md → ai/tools/collections/prompt.md} +0 -0
  151. /package/dist/{mcp/define.d.ts → ai/tools/define-tool.d.ts} +0 -0
  152. /package/dist/{mcp/define.js → ai/tools/define-tool.js} +0 -0
  153. /package/dist/{mcp/tools/fields.d.ts → ai/tools/fields/index.d.ts} +0 -0
  154. /package/dist/{mcp/tools/prompts/fields.md → ai/tools/fields/prompt.md} +0 -0
  155. /package/dist/{mcp/tools/files.d.ts → ai/tools/files/index.d.ts} +0 -0
  156. /package/dist/{mcp/tools/prompts/files.md → ai/tools/files/prompt.md} +0 -0
  157. /package/dist/{mcp/tools/flows.d.ts → ai/tools/flows/index.d.ts} +0 -0
  158. /package/dist/{mcp/tools/prompts/flows.md → ai/tools/flows/prompt.md} +0 -0
  159. /package/dist/{mcp/tools/folders.d.ts → ai/tools/folders/index.d.ts} +0 -0
  160. /package/dist/{mcp/tools/prompts/folders.md → ai/tools/folders/prompt.md} +0 -0
  161. /package/dist/{mcp/tools/items.d.ts → ai/tools/items/index.d.ts} +0 -0
  162. /package/dist/{mcp/tools/prompts/operations.md → ai/tools/operations/prompt.md} +0 -0
  163. /package/dist/{mcp/tools/relations.d.ts → ai/tools/relations/index.d.ts} +0 -0
  164. /package/dist/{mcp/tools/prompts/relations.md → ai/tools/relations/prompt.md} +0 -0
  165. /package/dist/{mcp/tools/prompts/schema.md → ai/tools/schema/prompt.md} +0 -0
  166. /package/dist/{mcp → ai/tools}/schema.d.ts +0 -0
  167. /package/dist/{mcp → ai/tools}/schema.js +0 -0
  168. /package/dist/{mcp/tools/system.d.ts → ai/tools/system/index.d.ts} +0 -0
  169. /package/dist/{mcp/tools/prompts/system-prompt-description.md → ai/tools/system/prompt-description.md} +0 -0
  170. /package/dist/{mcp/tools/prompts/system-prompt.md → ai/tools/system/prompt.md} +0 -0
  171. /package/dist/{mcp/tools/trigger-flow.d.ts → ai/tools/trigger-flow/index.d.ts} +0 -0
  172. /package/dist/{mcp/tools/prompts/trigger-flow.md → ai/tools/trigger-flow/prompt.md} +0 -0
  173. /package/dist/{permissions/modules/fetch-global-access → ai/tools}/types.js +0 -0
  174. /package/dist/test-utils/{items-service.d.ts → services/items-service.d.ts} +0 -0
  175. /package/dist/test-utils/{items-service.js → services/items-service.js} +0 -0
@@ -1,10 +1,13 @@
1
1
  import { InvalidPayloadError } from '@directus/errors';
2
2
  import { isObject, toArray } from '@directus/utils';
3
+ import { dirname, resolve } from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
3
5
  import { z } from 'zod';
4
- import { CollectionsService } from '../../services/collections.js';
5
- import { defineTool } from '../define.js';
6
+ import { CollectionsService } from '../../../services/collections.js';
7
+ import { requireText } from '../../../utils/require-text.js';
8
+ import { defineTool } from '../define-tool.js';
6
9
  import { CollectionItemInputSchema, CollectionItemValidateCreateSchema, CollectionItemValidateUpdateSchema, } from '../schema.js';
7
- import prompts from './prompts/index.js';
10
+ const __dirname = dirname(fileURLToPath(import.meta.url));
8
11
  export const CollectionsValidateSchema = z.discriminatedUnion('action', [
9
12
  z.strictObject({
10
13
  action: z.literal('create'),
@@ -31,7 +34,7 @@ export const CollectionsInputSchema = z.object({
31
34
  export const collections = defineTool({
32
35
  name: 'collections',
33
36
  admin: true,
34
- description: prompts.collections,
37
+ description: requireText(resolve(__dirname, './prompt.md')),
35
38
  annotations: {
36
39
  title: 'Directus - Collections',
37
40
  },
@@ -1,15 +1,18 @@
1
1
  import { InvalidPayloadError } from '@directus/errors';
2
2
  import { toArray } from '@directus/utils';
3
+ import { dirname, resolve } from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
3
5
  import { z } from 'zod';
4
- import { clearSystemCache } from '../../cache.js';
5
- import getDatabase from '../../database/index.js';
6
- import { FieldsService } from '../../services/fields.js';
7
- import { getSchema } from '../../utils/get-schema.js';
8
- import { shouldClearCache } from '../../utils/should-clear-cache.js';
9
- import { transaction } from '../../utils/transaction.js';
10
- import { defineTool } from '../define.js';
6
+ import { clearSystemCache } from '../../../cache.js';
7
+ import getDatabase from '../../../database/index.js';
8
+ import { FieldsService } from '../../../services/fields.js';
9
+ import { getSchema } from '../../../utils/get-schema.js';
10
+ import { requireText } from '../../../utils/require-text.js';
11
+ import { shouldClearCache } from '../../../utils/should-clear-cache.js';
12
+ import { transaction } from '../../../utils/transaction.js';
13
+ import { defineTool } from '../define-tool.js';
11
14
  import { FieldItemInputSchema, FieldItemValidateSchema, RawFieldItemInputSchema, RawFieldItemValidateSchema, } from '../schema.js';
12
- import prompts from './prompts/index.js';
15
+ const __dirname = dirname(fileURLToPath(import.meta.url));
13
16
  export const FieldsBaseValidateSchema = z.strictObject({
14
17
  collection: z.string(),
15
18
  });
@@ -45,7 +48,7 @@ export const FieldsInputSchema = z.object({
45
48
  export const fields = defineTool({
46
49
  name: 'fields',
47
50
  admin: true,
48
- description: prompts.fields,
51
+ description: requireText(resolve(__dirname, './prompt.md')),
49
52
  annotations: {
50
53
  title: 'Directus - Fields',
51
54
  },
@@ -1,9 +1,13 @@
1
1
  import { isObject } from '@directus/utils';
2
+ import { dirname, resolve } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
2
4
  import { z } from 'zod';
3
- import { FilesService } from '../../services/files.js';
4
- import { defineTool } from '../define.js';
5
+ import { FilesService } from '../../../services/files.js';
6
+ import { requireText } from '../../../utils/require-text.js';
7
+ import { defineTool } from '../define-tool.js';
5
8
  import { FileImportItemInputSchema, FileImportItemValidateSchema, FileItemInputSchema, FileItemValidateSchema, PrimaryKeyInputSchema, PrimaryKeyValidateSchema, QueryInputSchema, QueryValidateSchema, } from '../schema.js';
6
- import prompts from './prompts/index.js';
9
+ import { buildSanitizedQueryFromArgs } from '../utils.js';
10
+ const __dirname = dirname(fileURLToPath(import.meta.url));
7
11
  export const FilesValidateSchema = z.discriminatedUnion('action', [
8
12
  z.strictObject({
9
13
  action: z.literal('read'),
@@ -33,7 +37,7 @@ const FilesInputSchema = z.object({
33
37
  });
34
38
  export const files = defineTool({
35
39
  name: 'files',
36
- description: prompts.files,
40
+ description: requireText(resolve(__dirname, './prompt.md')),
37
41
  annotations: {
38
42
  title: 'Directus - Files',
39
43
  },
@@ -45,12 +49,13 @@ export const files = defineTool({
45
49
  }
46
50
  return ['files', data['id']];
47
51
  },
48
- async handler({ args, schema, accountability, sanitizedQuery }) {
52
+ async handler({ args, schema, accountability }) {
49
53
  const service = new FilesService({
50
54
  schema,
51
55
  accountability,
52
56
  });
53
57
  if (args.action === 'read') {
58
+ const sanitizedQuery = await buildSanitizedQueryFromArgs(args, schema, accountability);
54
59
  let result = null;
55
60
  if (args.keys) {
56
61
  result = await service.readMany(args.keys, sanitizedQuery);
@@ -64,6 +69,7 @@ export const files = defineTool({
64
69
  };
65
70
  }
66
71
  if (args.action === 'update') {
72
+ const sanitizedQuery = await buildSanitizedQueryFromArgs(args, schema, accountability);
67
73
  let updatedKeys = [];
68
74
  if (Array.isArray(args.data)) {
69
75
  updatedKeys = await service.updateBatch(args.data);
@@ -1,9 +1,13 @@
1
1
  import { isObject } from '@directus/utils';
2
+ import { dirname, resolve } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
2
4
  import { z } from 'zod';
3
- import { FlowsService } from '../../services/flows.js';
4
- import { defineTool } from '../define.js';
5
+ import { FlowsService } from '../../../services/flows.js';
6
+ import { requireText } from '../../../utils/require-text.js';
7
+ import { defineTool } from '../define-tool.js';
5
8
  import { FlowItemInputSchema, FlowItemValidateSchema, QueryInputSchema, QueryValidateSchema } from '../schema.js';
6
- import prompts from './prompts/index.js';
9
+ import { buildSanitizedQueryFromArgs } from '../utils.js';
10
+ const __dirname = dirname(fileURLToPath(import.meta.url));
7
11
  export const FlowsValidateSchema = z.discriminatedUnion('action', [
8
12
  z.strictObject({
9
13
  action: z.literal('create'),
@@ -33,7 +37,7 @@ export const FlowsInputSchema = z.object({
33
37
  export const flows = defineTool({
34
38
  name: 'flows',
35
39
  admin: true,
36
- description: prompts.flows,
40
+ description: requireText(resolve(__dirname, './prompt.md')),
37
41
  annotations: {
38
42
  title: 'Directus - Flows',
39
43
  },
@@ -45,7 +49,7 @@ export const flows = defineTool({
45
49
  }
46
50
  return ['settings', 'flows', data['id']];
47
51
  },
48
- async handler({ args, schema, accountability, sanitizedQuery }) {
52
+ async handler({ args, schema, accountability }) {
49
53
  const flowsService = new FlowsService({
50
54
  schema,
51
55
  accountability,
@@ -59,6 +63,7 @@ export const flows = defineTool({
59
63
  };
60
64
  }
61
65
  if (args.action === 'read') {
66
+ const sanitizedQuery = await buildSanitizedQueryFromArgs(args, schema, accountability);
62
67
  const result = await flowsService.readByQuery(sanitizedQuery);
63
68
  return {
64
69
  type: 'text',
@@ -66,6 +71,7 @@ export const flows = defineTool({
66
71
  };
67
72
  }
68
73
  if (args.action === 'update') {
74
+ const sanitizedQuery = await buildSanitizedQueryFromArgs(args, schema, accountability);
69
75
  const updatedKey = await flowsService.updateOne(args.key, args.data);
70
76
  const result = await flowsService.readOne(updatedKey, sanitizedQuery);
71
77
  return {
@@ -1,9 +1,13 @@
1
1
  import { toArray } from '@directus/utils';
2
+ import { dirname, resolve } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
2
4
  import { z } from 'zod';
3
- import { FoldersService } from '../../services/folders.js';
4
- import { defineTool } from '../define.js';
5
+ import { FoldersService } from '../../../services/folders.js';
6
+ import { requireText } from '../../../utils/require-text.js';
7
+ import { defineTool } from '../define-tool.js';
5
8
  import { FolderItemInputSchema, FolderItemValidateSchema, PrimaryKeyInputSchema, PrimaryKeyValidateSchema, QueryInputSchema, QueryValidateSchema, } from '../schema.js';
6
- import prompts from './prompts/index.js';
9
+ import { buildSanitizedQueryFromArgs } from '../utils.js';
10
+ const __dirname = dirname(fileURLToPath(import.meta.url));
7
11
  const FoldersValidateSchema = z.discriminatedUnion('action', [
8
12
  z.strictObject({
9
13
  action: z.literal('create'),
@@ -34,18 +38,19 @@ const FoldersInputSchema = z.object({
34
38
  });
35
39
  export const folders = defineTool({
36
40
  name: 'folders',
37
- description: prompts.folders,
41
+ description: requireText(resolve(__dirname, './prompt.md')),
38
42
  annotations: {
39
43
  title: 'Directus - Folders',
40
44
  },
41
45
  inputSchema: FoldersInputSchema,
42
46
  validateSchema: FoldersValidateSchema,
43
- async handler({ args, schema, accountability, sanitizedQuery }) {
47
+ async handler({ args, schema, accountability }) {
44
48
  const service = new FoldersService({
45
49
  schema,
46
50
  accountability,
47
51
  });
48
52
  if (args.action === 'create') {
53
+ const sanitizedQuery = await buildSanitizedQueryFromArgs(args, schema, accountability);
49
54
  const data = toArray(args.data);
50
55
  const savedKeys = await service.createMany(data);
51
56
  const result = await service.readMany(savedKeys, sanitizedQuery);
@@ -55,6 +60,7 @@ export const folders = defineTool({
55
60
  };
56
61
  }
57
62
  if (args.action === 'read') {
63
+ const sanitizedQuery = await buildSanitizedQueryFromArgs(args, schema, accountability);
58
64
  let result = null;
59
65
  if (args.keys) {
60
66
  result = await service.readMany(args.keys, sanitizedQuery);
@@ -68,6 +74,7 @@ export const folders = defineTool({
68
74
  };
69
75
  }
70
76
  if (args.action === 'update') {
77
+ const sanitizedQuery = await buildSanitizedQueryFromArgs(args, schema, accountability);
71
78
  let updatedKeys = [];
72
79
  if (Array.isArray(args.data)) {
73
80
  updatedKeys = await service.updateBatch(args.data);
@@ -0,0 +1,15 @@
1
+ import { collections } from './collections/index.js';
2
+ import { fields } from './fields/index.js';
3
+ import { files } from './files/index.js';
4
+ import { flows } from './flows/index.js';
5
+ import { items } from './items/index.js';
6
+ import { operations } from './operations/index.js';
7
+ import { relations } from './relations/index.js';
8
+ import { schema } from './schema/index.js';
9
+ import { system } from './system/index.js';
10
+ import { triggerFlow } from './trigger-flow/index.js';
11
+ import type { ToolConfig } from './types.js';
12
+ export declare const ALL_TOOLS: ToolConfig<any>[];
13
+ export declare const getAllMcpTools: () => ToolConfig<any>[];
14
+ export declare const findMcpTool: (name: string) => ToolConfig<any> | undefined;
15
+ export { collections, fields, files, flows, items, operations, relations, schema, system, triggerFlow };
@@ -0,0 +1,29 @@
1
+ import { assets } from './assets/index.js';
2
+ import { collections } from './collections/index.js';
3
+ import { fields } from './fields/index.js';
4
+ import { files } from './files/index.js';
5
+ import { flows } from './flows/index.js';
6
+ import { folders } from './folders/index.js';
7
+ import { items } from './items/index.js';
8
+ import { operations } from './operations/index.js';
9
+ import { relations } from './relations/index.js';
10
+ import { schema } from './schema/index.js';
11
+ import { system } from './system/index.js';
12
+ import { triggerFlow } from './trigger-flow/index.js';
13
+ export const ALL_TOOLS = [
14
+ system,
15
+ items,
16
+ files,
17
+ folders,
18
+ assets,
19
+ flows,
20
+ triggerFlow,
21
+ operations,
22
+ schema,
23
+ collections,
24
+ fields,
25
+ relations,
26
+ ];
27
+ export const getAllMcpTools = () => ALL_TOOLS;
28
+ export const findMcpTool = (name) => ALL_TOOLS.find((tool) => tool.name === name);
29
+ export { collections, fields, files, flows, items, operations, relations, schema, system, triggerFlow };
@@ -2,11 +2,15 @@ import { ForbiddenError, InvalidPayloadError } from '@directus/errors';
2
2
  import { isSystemCollection } from '@directus/system-data';
3
3
  import { toArray } from '@directus/utils';
4
4
  import { isObject } from 'graphql-compose';
5
+ import { dirname, resolve } from 'node:path';
6
+ import { fileURLToPath } from 'node:url';
5
7
  import { z } from 'zod';
6
- import { ItemsService } from '../../services/items.js';
7
- import { defineTool } from '../define.js';
8
+ import { ItemsService } from '../../../services/items.js';
9
+ import { requireText } from '../../../utils/require-text.js';
10
+ import { defineTool } from '../define-tool.js';
8
11
  import { ItemInputSchema, ItemValidateSchema, PrimaryKeyInputSchema, PrimaryKeyValidateSchema, QueryInputSchema, QueryValidateSchema, } from '../schema.js';
9
- import prompts from './prompts/index.js';
12
+ import { buildSanitizedQueryFromArgs } from '../utils.js';
13
+ const __dirname = dirname(fileURLToPath(import.meta.url));
10
14
  const PartialItemInputSchema = z.strictObject({
11
15
  collection: z.string(),
12
16
  });
@@ -37,11 +41,11 @@ const ItemsInputSchema = z.object({
37
41
  collection: z.string().describe('The name of the collection'),
38
42
  query: QueryInputSchema.optional(),
39
43
  keys: z.array(PrimaryKeyInputSchema).optional(),
40
- data: z.array(ItemInputSchema).optional(),
44
+ data: z.array(ItemInputSchema).optional().describe('Always an array of objects'),
41
45
  });
42
46
  export const items = defineTool({
43
47
  name: 'items',
44
- description: prompts.items,
48
+ description: requireText(resolve(__dirname, './prompt.md')),
45
49
  annotations: {
46
50
  title: 'Directus - Items',
47
51
  },
@@ -53,7 +57,7 @@ export const items = defineTool({
53
57
  }
54
58
  return ['content', input.collection, data['id']];
55
59
  },
56
- async handler({ args, schema, accountability, sanitizedQuery }) {
60
+ async handler({ args, schema, accountability }) {
57
61
  if (isSystemCollection(args.collection)) {
58
62
  throw new InvalidPayloadError({ reason: 'Cannot provide a core collection' });
59
63
  }
@@ -66,6 +70,7 @@ export const items = defineTool({
66
70
  accountability,
67
71
  });
68
72
  if (args.action === 'create') {
73
+ const sanitizedQuery = await buildSanitizedQueryFromArgs(args, schema, accountability);
69
74
  const data = toArray(args.data);
70
75
  if (isSingleton) {
71
76
  if (Array.isArray(args.data)) {
@@ -86,6 +91,7 @@ export const items = defineTool({
86
91
  };
87
92
  }
88
93
  if (args.action === 'read') {
94
+ const sanitizedQuery = await buildSanitizedQueryFromArgs(args, schema, accountability);
89
95
  let result = null;
90
96
  if (isSingleton) {
91
97
  result = await itemsService.readSingleton(sanitizedQuery);
@@ -102,6 +108,7 @@ export const items = defineTool({
102
108
  };
103
109
  }
104
110
  if (args.action === 'update') {
111
+ const sanitizedQuery = await buildSanitizedQueryFromArgs(args, schema, accountability);
105
112
  if (isSingleton) {
106
113
  if (Array.isArray(args.data)) {
107
114
  throw new InvalidPayloadError({ reason: 'Invalid data payload, object exptected' });
@@ -3,7 +3,7 @@ Perform CRUD operations on items within Directus collections
3
3
  ## Actions
4
4
 
5
5
  - `read`: Query items with filtering/pagination/field selection
6
- - `create`: Add items (single/batch) with nested relations
6
+ - `create`: Add items with nested relations
7
7
  - `update`: Modify items with partial data
8
8
  - `delete`: Remove items by primary keys
9
9
 
@@ -59,12 +59,14 @@ Core: `_eq`, `_neq`, `_in`, `_nin`, `_null`, `_nnull`, `_lt`, `_lte`, `_gt`, `_g
59
59
  {
60
60
  "action": "create",
61
61
  "collection": "posts",
62
- "data": {
63
- "title": "New Post",
64
- "author": { "name": "John Doe", "email": "john@example.com" }, // Creates nested
65
- "categories": [1, 2, { "name": "New Category" }], // Mix existing + new
66
- "status": "draft"
67
- }
62
+ "data": [
63
+ {
64
+ "title": "New Post",
65
+ "author": { "name": "John Doe", "email": "john@example.com" }, // Creates nested
66
+ "categories": [1, 2, { "name": "New Category" }], // Mix existing + new
67
+ "status": "draft"
68
+ }
69
+ ]
68
70
  }
69
71
  ```
70
72
 
@@ -97,7 +99,7 @@ Core: `_eq`, `_neq`, `_in`, `_nin`, `_null`, `_nnull`, `_lt`, `_lte`, `_gt`, `_g
97
99
  "action": "update",
98
100
  "collection": "posts",
99
101
  "keys": ["uuid-1", "uuid-2"],
100
- "data": { "status": "published" } // Partial update
102
+ "data": [{ "status": "published" }] // Partial update
101
103
  }
102
104
  ```
103
105
 
@@ -121,13 +123,15 @@ Core: `_eq`, `_neq`, `_in`, `_nin`, `_null`, `_nnull`, `_lt`, `_lte`, `_gt`, `_g
121
123
  "action": "update",
122
124
  "collection": "posts",
123
125
  "keys": ["uuid-1"],
124
- "data": {
125
- "categories": {
126
- "create": [{ "name": "New Category" }],
127
- "update": [{ "id": 3, "name": "Renamed" }],
128
- "delete": [5]
126
+ "data": [
127
+ {
128
+ "categories": {
129
+ "create": [{ "name": "New Category" }],
130
+ "update": [{ "id": 3, "name": "Renamed" }],
131
+ "delete": [5]
132
+ }
129
133
  }
130
- }
134
+ ]
131
135
  }
132
136
  ```
133
137
 
@@ -137,7 +141,7 @@ Core: `_eq`, `_neq`, `_in`, `_nin`, `_null`, `_nnull`, `_lt`, `_lte`, `_gt`, `_g
137
141
  // Don't update without specifying which items
138
142
  {
139
143
  "action": "update",
140
- "data": { "status": "published" } // Will fail - no keys provided
144
+ "data": [{ "status": "published" }] // Will fail - no keys provided
141
145
  }
142
146
  ```
143
147
 
@@ -57,6 +57,29 @@ export declare const OperationsValidationSchema: z.ZodDiscriminatedUnion<[z.ZodO
57
57
  user_created: z.ZodOptional<z.ZodString>;
58
58
  }, z.core.$strip>;
59
59
  key: z.ZodString;
60
+ query: z.ZodOptional<z.ZodObject<{
61
+ fields: z.ZodOptional<z.ZodArray<z.ZodString>>;
62
+ sort: z.ZodOptional<z.ZodArray<z.ZodString>>;
63
+ filter: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
64
+ limit: z.ZodOptional<z.ZodNumber>;
65
+ offset: z.ZodOptional<z.ZodNumber>;
66
+ page: z.ZodOptional<z.ZodNumber>;
67
+ search: z.ZodOptional<z.ZodString>;
68
+ deep: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
69
+ alias: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
70
+ aggregate: z.ZodOptional<z.ZodObject<{
71
+ count: z.ZodOptional<z.ZodArray<z.ZodString>>;
72
+ sum: z.ZodOptional<z.ZodArray<z.ZodString>>;
73
+ avg: z.ZodOptional<z.ZodArray<z.ZodString>>;
74
+ min: z.ZodOptional<z.ZodArray<z.ZodString>>;
75
+ max: z.ZodOptional<z.ZodArray<z.ZodString>>;
76
+ }, z.core.$strip>>;
77
+ backlink: z.ZodOptional<z.ZodBoolean>;
78
+ version: z.ZodOptional<z.ZodString>;
79
+ versionRaw: z.ZodOptional<z.ZodBoolean>;
80
+ export: z.ZodOptional<z.ZodString>;
81
+ groupBy: z.ZodOptional<z.ZodArray<z.ZodString>>;
82
+ }, z.core.$strip>>;
60
83
  }, z.core.$strict>, z.ZodObject<{
61
84
  action: z.ZodLiteral<"delete">;
62
85
  key: z.ZodString;
@@ -165,6 +188,29 @@ export declare const operations: import("../types.js").ToolConfig<{
165
188
  user_created?: string | undefined;
166
189
  };
167
190
  key: string;
191
+ query?: {
192
+ fields?: string[] | undefined;
193
+ sort?: string[] | undefined;
194
+ filter?: Record<string, any> | undefined;
195
+ limit?: number | undefined;
196
+ offset?: number | undefined;
197
+ page?: number | undefined;
198
+ search?: string | undefined;
199
+ deep?: Record<string, any> | undefined;
200
+ alias?: Record<string, string> | undefined;
201
+ aggregate?: {
202
+ count?: string[] | undefined;
203
+ sum?: string[] | undefined;
204
+ avg?: string[] | undefined;
205
+ min?: string[] | undefined;
206
+ max?: string[] | undefined;
207
+ } | undefined;
208
+ backlink?: boolean | undefined;
209
+ version?: string | undefined;
210
+ versionRaw?: boolean | undefined;
211
+ export?: string | undefined;
212
+ groupBy?: string[] | undefined;
213
+ } | undefined;
168
214
  } | {
169
215
  action: "delete";
170
216
  key: string;
@@ -1,8 +1,12 @@
1
+ import { dirname, resolve } from 'node:path';
2
+ import { fileURLToPath } from 'node:url';
1
3
  import { z } from 'zod';
2
- import { OperationsService } from '../../services/operations.js';
3
- import { defineTool } from '../define.js';
4
+ import { OperationsService } from '../../../services/operations.js';
5
+ import { requireText } from '../../../utils/require-text.js';
6
+ import { defineTool } from '../define-tool.js';
4
7
  import { OperationItemInputSchema, OperationItemValidateSchema, QueryInputSchema, QueryValidateSchema, } from '../schema.js';
5
- import prompts from './prompts/index.js';
8
+ import { buildSanitizedQueryFromArgs } from '../utils.js';
9
+ const __dirname = dirname(fileURLToPath(import.meta.url));
6
10
  export const OperationsValidationSchema = z.discriminatedUnion('action', [
7
11
  z.strictObject({
8
12
  action: z.literal('create'),
@@ -16,6 +20,7 @@ export const OperationsValidationSchema = z.discriminatedUnion('action', [
16
20
  action: z.literal('update'),
17
21
  data: OperationItemValidateSchema,
18
22
  key: z.string(),
23
+ query: QueryValidateSchema.optional(),
19
24
  }),
20
25
  z.strictObject({
21
26
  action: z.literal('delete'),
@@ -31,13 +36,13 @@ export const OperationsInputSchema = z.object({
31
36
  export const operations = defineTool({
32
37
  name: 'operations',
33
38
  admin: true,
34
- description: prompts.operations,
39
+ description: requireText(resolve(__dirname, './prompt.md')),
35
40
  annotations: {
36
41
  title: 'Directus - Operations',
37
42
  },
38
43
  inputSchema: OperationsInputSchema,
39
44
  validateSchema: OperationsValidationSchema,
40
- async handler({ args, schema, accountability, sanitizedQuery }) {
45
+ async handler({ args, schema, accountability }) {
41
46
  const operationService = new OperationsService({
42
47
  schema,
43
48
  accountability,
@@ -51,6 +56,7 @@ export const operations = defineTool({
51
56
  };
52
57
  }
53
58
  if (args.action === 'read') {
59
+ const sanitizedQuery = await buildSanitizedQueryFromArgs(args, schema, accountability);
54
60
  const result = await operationService.readByQuery(sanitizedQuery);
55
61
  return {
56
62
  type: 'text',
@@ -58,6 +64,7 @@ export const operations = defineTool({
58
64
  };
59
65
  }
60
66
  if (args.action === 'update') {
67
+ const sanitizedQuery = await buildSanitizedQueryFromArgs(args, schema, accountability);
61
68
  const updatedKey = await operationService.updateOne(args.key, args.data);
62
69
  const result = await operationService.readOne(updatedKey, sanitizedQuery);
63
70
  return {
@@ -1,9 +1,12 @@
1
1
  import { InvalidPayloadError } from '@directus/errors';
2
+ import { dirname, resolve } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
2
4
  import { z } from 'zod';
3
- import { RelationsService } from '../../services/relations.js';
4
- import { defineTool } from '../define.js';
5
+ import { RelationsService } from '../../../services/relations.js';
6
+ import { requireText } from '../../../utils/require-text.js';
7
+ import { defineTool } from '../define-tool.js';
5
8
  import { RelationItemInputSchema, RelationItemValidateCreateSchema, RelationItemValidateUpdateSchema, } from '../schema.js';
6
- import prompts from './prompts/index.js';
9
+ const __dirname = dirname(fileURLToPath(import.meta.url));
7
10
  const RelationsValidateSchema = z.discriminatedUnion('action', [
8
11
  z.object({
9
12
  action: z.literal('create'),
@@ -37,7 +40,7 @@ const RelationsInputSchema = z.object({
37
40
  export const relations = defineTool({
38
41
  name: 'relations',
39
42
  admin: true,
40
- description: prompts.relations,
43
+ description: requireText(resolve(__dirname, './prompt.md')),
41
44
  annotations: {
42
45
  title: 'Directus - Relations',
43
46
  },
@@ -1,6 +1,6 @@
1
1
  import type { Field, Relation } from '@directus/types';
2
2
  import { z } from 'zod';
3
- import type { Collection } from '../../types/collection.js';
3
+ import type { Collection } from '../../../types/collection.js';
4
4
  export interface fieldOverviewOutput {
5
5
  type: string;
6
6
  primary_key?: boolean;
@@ -1,9 +1,12 @@
1
+ import { dirname, resolve } from 'node:path';
2
+ import { fileURLToPath } from 'node:url';
1
3
  import { z } from 'zod';
2
- import { CollectionsService } from '../../services/collections.js';
3
- import { FieldsService } from '../../services/fields.js';
4
- import { RelationsService } from '../../services/relations.js';
5
- import { defineTool } from '../define.js';
6
- import prompts from './prompts/index.js';
4
+ import { FieldsService } from '../../..//services/fields.js';
5
+ import { CollectionsService } from '../../../services/collections.js';
6
+ import { RelationsService } from '../../../services/relations.js';
7
+ import { requireText } from '../../../utils/require-text.js';
8
+ import { defineTool } from '../define-tool.js';
9
+ const __dirname = dirname(fileURLToPath(import.meta.url));
7
10
  export const SchemaValidateSchema = z.strictObject({
8
11
  keys: z.array(z.string()).optional(),
9
12
  });
@@ -15,7 +18,7 @@ export const SchemaInputSchema = z.object({
15
18
  });
16
19
  export const schema = defineTool({
17
20
  name: 'schema',
18
- description: prompts.schema,
21
+ description: requireText(resolve(__dirname, './prompt.md')),
19
22
  annotations: {
20
23
  title: 'Directus - Schema',
21
24
  },
@@ -1,13 +1,16 @@
1
+ import { dirname, resolve } from 'node:path';
2
+ import { fileURLToPath } from 'node:url';
1
3
  import { z } from 'zod';
2
- import { defineTool } from '../define.js';
3
- import prompts from './prompts/index.js';
4
+ import { requireText } from '../../../utils/require-text.js';
5
+ import { defineTool } from '../define-tool.js';
6
+ const __dirname = dirname(fileURLToPath(import.meta.url));
4
7
  const SystemPromptInputSchema = z.object({});
5
8
  const SystemPromptValidateSchema = z.object({
6
9
  promptOverride: z.union([z.string(), z.null()]).optional(),
7
10
  });
8
11
  export const system = defineTool({
9
12
  name: 'system-prompt',
10
- description: prompts.systemPromptDescription,
13
+ description: requireText(resolve(__dirname, './prompt-description.md')),
11
14
  annotations: {
12
15
  title: 'Directus - System Prompt',
13
16
  },
@@ -16,7 +19,7 @@ export const system = defineTool({
16
19
  async handler({ args }) {
17
20
  return {
18
21
  type: 'text',
19
- data: args.promptOverride || prompts.systemPrompt,
22
+ data: args.promptOverride || requireText(resolve(__dirname, './prompt.md')),
20
23
  };
21
24
  },
22
25
  });
@@ -1,13 +1,16 @@
1
1
  import { InvalidPayloadError } from '@directus/errors';
2
+ import { dirname, resolve } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
2
4
  import { z } from 'zod';
3
- import { getFlowManager } from '../../flows.js';
4
- import { FlowsService } from '../../services/flows.js';
5
- import { defineTool } from '../define.js';
5
+ import { getFlowManager } from '../../../flows.js';
6
+ import { FlowsService } from '../../../services/flows.js';
7
+ import { requireText } from '../../../utils/require-text.js';
8
+ import { defineTool } from '../define-tool.js';
6
9
  import { TriggerFlowInputSchema, TriggerFlowValidateSchema } from '../schema.js';
7
- import prompts from './prompts/index.js';
10
+ const __dirname = dirname(fileURLToPath(import.meta.url));
8
11
  export const triggerFlow = defineTool({
9
12
  name: 'trigger-flow',
10
- description: prompts.triggerFlow,
13
+ description: requireText(resolve(__dirname, './prompt.md')),
11
14
  annotations: {
12
15
  title: 'Directus - Trigger Flow',
13
16
  },