@directus/api 30.0.0 → 32.0.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 (197) hide show
  1. package/dist/app.js +7 -0
  2. package/dist/auth/auth.d.ts +2 -1
  3. package/dist/auth/auth.js +7 -2
  4. package/dist/auth/drivers/ldap.d.ts +0 -2
  5. package/dist/auth/drivers/ldap.js +9 -7
  6. package/dist/auth/drivers/oauth2.d.ts +0 -2
  7. package/dist/auth/drivers/oauth2.js +28 -11
  8. package/dist/auth/drivers/openid.d.ts +0 -2
  9. package/dist/auth/drivers/openid.js +28 -11
  10. package/dist/auth/drivers/saml.d.ts +0 -2
  11. package/dist/auth/drivers/saml.js +5 -5
  12. package/dist/auth.js +1 -2
  13. package/dist/cli/commands/bootstrap/index.js +12 -33
  14. package/dist/cli/commands/init/index.js +1 -1
  15. package/dist/cli/commands/schema/apply.d.ts +4 -0
  16. package/dist/cli/commands/schema/apply.js +26 -3
  17. package/dist/controllers/collections.js +7 -2
  18. package/dist/controllers/fields.js +31 -8
  19. package/dist/controllers/mcp.d.ts +2 -0
  20. package/dist/controllers/mcp.js +33 -0
  21. package/dist/controllers/server.js +26 -1
  22. package/dist/controllers/settings.js +9 -2
  23. package/dist/controllers/users.js +17 -7
  24. package/dist/controllers/versions.js +3 -2
  25. package/dist/database/errors/dialects/mssql.d.ts +1 -1
  26. package/dist/database/errors/dialects/mssql.js +18 -10
  27. package/dist/database/helpers/fn/types.js +3 -3
  28. package/dist/database/helpers/schema/dialects/cockroachdb.d.ts +2 -1
  29. package/dist/database/helpers/schema/dialects/cockroachdb.js +13 -0
  30. package/dist/database/helpers/schema/dialects/mssql.d.ts +2 -1
  31. package/dist/database/helpers/schema/dialects/mssql.js +23 -0
  32. package/dist/database/helpers/schema/dialects/mysql.d.ts +2 -1
  33. package/dist/database/helpers/schema/dialects/mysql.js +25 -0
  34. package/dist/database/helpers/schema/dialects/oracle.d.ts +2 -1
  35. package/dist/database/helpers/schema/dialects/oracle.js +13 -0
  36. package/dist/database/helpers/schema/dialects/postgres.d.ts +2 -1
  37. package/dist/database/helpers/schema/dialects/postgres.js +13 -0
  38. package/dist/database/helpers/schema/types.d.ts +5 -0
  39. package/dist/database/helpers/schema/types.js +6 -0
  40. package/dist/database/migrations/20250813A-add-mcp.d.ts +3 -0
  41. package/dist/database/migrations/20250813A-add-mcp.js +18 -0
  42. package/dist/database/migrations/20251012A-add-field-searchable.d.ts +3 -0
  43. package/dist/database/migrations/20251012A-add-field-searchable.js +10 -0
  44. package/dist/database/migrations/20251014A-add-project-owner.d.ts +3 -0
  45. package/dist/database/migrations/20251014A-add-project-owner.js +37 -0
  46. package/dist/database/migrations/20251028A-add-retention-indexes.d.ts +3 -0
  47. package/dist/database/migrations/20251028A-add-retention-indexes.js +42 -0
  48. package/dist/database/run-ast/README.md +46 -0
  49. package/dist/database/run-ast/lib/apply-query/add-join.js +2 -2
  50. package/dist/database/run-ast/lib/apply-query/filter/get-filter-type.d.ts +2 -2
  51. package/dist/database/run-ast/lib/apply-query/index.d.ts +0 -1
  52. package/dist/database/run-ast/lib/apply-query/index.js +4 -6
  53. package/dist/database/run-ast/lib/apply-query/search.js +2 -0
  54. package/dist/database/run-ast/lib/get-db-query.js +7 -6
  55. package/dist/database/run-ast/utils/generate-alias.d.ts +6 -0
  56. package/dist/database/run-ast/utils/generate-alias.js +57 -0
  57. package/dist/flows.js +1 -0
  58. package/dist/mcp/define.d.ts +2 -0
  59. package/dist/mcp/define.js +3 -0
  60. package/dist/mcp/index.d.ts +1 -0
  61. package/dist/mcp/index.js +1 -0
  62. package/dist/mcp/schema.d.ts +485 -0
  63. package/dist/mcp/schema.js +219 -0
  64. package/dist/mcp/server.d.ts +103 -0
  65. package/dist/mcp/server.js +310 -0
  66. package/dist/mcp/tools/assets.d.ts +3 -0
  67. package/dist/mcp/tools/assets.js +54 -0
  68. package/dist/mcp/tools/collections.d.ts +84 -0
  69. package/dist/mcp/tools/collections.js +90 -0
  70. package/dist/mcp/tools/fields.d.ts +101 -0
  71. package/dist/mcp/tools/fields.js +157 -0
  72. package/dist/mcp/tools/files.d.ts +235 -0
  73. package/dist/mcp/tools/files.js +103 -0
  74. package/dist/mcp/tools/flows.d.ts +323 -0
  75. package/dist/mcp/tools/flows.js +85 -0
  76. package/dist/mcp/tools/folders.d.ts +95 -0
  77. package/dist/mcp/tools/folders.js +96 -0
  78. package/dist/mcp/tools/index.d.ts +15 -0
  79. package/dist/mcp/tools/index.js +29 -0
  80. package/dist/mcp/tools/items.d.ts +87 -0
  81. package/dist/mcp/tools/items.js +141 -0
  82. package/dist/mcp/tools/operations.d.ts +171 -0
  83. package/dist/mcp/tools/operations.js +77 -0
  84. package/dist/mcp/tools/prompts/assets.md +8 -0
  85. package/dist/mcp/tools/prompts/collections.md +336 -0
  86. package/dist/mcp/tools/prompts/fields.md +521 -0
  87. package/dist/mcp/tools/prompts/files.md +180 -0
  88. package/dist/mcp/tools/prompts/flows.md +495 -0
  89. package/dist/mcp/tools/prompts/folders.md +34 -0
  90. package/dist/mcp/tools/prompts/index.d.ts +16 -0
  91. package/dist/mcp/tools/prompts/index.js +19 -0
  92. package/dist/mcp/tools/prompts/items.md +317 -0
  93. package/dist/mcp/tools/prompts/operations.md +721 -0
  94. package/dist/mcp/tools/prompts/relations.md +386 -0
  95. package/dist/mcp/tools/prompts/schema.md +130 -0
  96. package/dist/mcp/tools/prompts/system-prompt-description.md +1 -0
  97. package/dist/mcp/tools/prompts/system-prompt.md +44 -0
  98. package/dist/mcp/tools/prompts/trigger-flow.md +214 -0
  99. package/dist/mcp/tools/relations.d.ts +73 -0
  100. package/dist/mcp/tools/relations.js +93 -0
  101. package/dist/mcp/tools/schema.d.ts +54 -0
  102. package/dist/mcp/tools/schema.js +317 -0
  103. package/dist/mcp/tools/system.d.ts +3 -0
  104. package/dist/mcp/tools/system.js +22 -0
  105. package/dist/mcp/tools/trigger-flow.d.ts +8 -0
  106. package/dist/mcp/tools/trigger-flow.js +48 -0
  107. package/dist/mcp/transport.d.ts +13 -0
  108. package/dist/mcp/transport.js +18 -0
  109. package/dist/mcp/types.d.ts +56 -0
  110. package/dist/mcp/types.js +1 -0
  111. package/dist/metrics/lib/create-metrics.js +16 -25
  112. package/dist/middleware/collection-exists.js +2 -2
  113. package/dist/operations/mail/index.js +3 -1
  114. package/dist/operations/mail/rate-limiter.d.ts +1 -0
  115. package/dist/operations/mail/rate-limiter.js +29 -0
  116. package/dist/permissions/modules/process-payload/process-payload.js +3 -10
  117. package/dist/permissions/modules/validate-access/validate-access.js +2 -3
  118. package/dist/schedules/metrics.js +6 -2
  119. package/dist/schedules/project.d.ts +4 -0
  120. package/dist/schedules/project.js +27 -0
  121. package/dist/services/authentication.js +36 -0
  122. package/dist/services/collections.d.ts +3 -3
  123. package/dist/services/collections.js +16 -1
  124. package/dist/services/fields.d.ts +21 -5
  125. package/dist/services/fields.js +109 -32
  126. package/dist/services/graphql/resolvers/query.js +1 -1
  127. package/dist/services/graphql/resolvers/system-admin.js +49 -5
  128. package/dist/services/graphql/schema/parse-query.js +8 -8
  129. package/dist/services/graphql/utils/aggregate-query.d.ts +1 -1
  130. package/dist/services/graphql/utils/aggregate-query.js +5 -1
  131. package/dist/services/graphql/utils/filter-replace-m2a.js +2 -1
  132. package/dist/services/import-export.d.ts +9 -1
  133. package/dist/services/import-export.js +287 -101
  134. package/dist/services/items.d.ts +1 -1
  135. package/dist/services/items.js +50 -24
  136. package/dist/services/mail/index.js +2 -0
  137. package/dist/services/mail/rate-limiter.d.ts +1 -0
  138. package/dist/services/mail/rate-limiter.js +29 -0
  139. package/dist/services/meta.js +28 -24
  140. package/dist/services/payload.d.ts +7 -3
  141. package/dist/services/payload.js +26 -12
  142. package/dist/services/schema.js +4 -1
  143. package/dist/services/server.d.ts +1 -0
  144. package/dist/services/server.js +15 -18
  145. package/dist/services/settings.d.ts +2 -1
  146. package/dist/services/settings.js +15 -0
  147. package/dist/services/tfa.d.ts +1 -1
  148. package/dist/services/tfa.js +20 -5
  149. package/dist/services/tus/server.js +14 -9
  150. package/dist/services/versions.d.ts +6 -4
  151. package/dist/services/versions.js +84 -25
  152. package/dist/telemetry/lib/get-report.js +4 -4
  153. package/dist/telemetry/lib/send-report.d.ts +6 -1
  154. package/dist/telemetry/lib/send-report.js +3 -1
  155. package/dist/telemetry/types/report.d.ts +17 -1
  156. package/dist/telemetry/utils/get-settings.d.ts +9 -0
  157. package/dist/telemetry/utils/get-settings.js +14 -0
  158. package/dist/test-utils/README.md +760 -0
  159. package/dist/test-utils/cache.d.ts +51 -0
  160. package/dist/test-utils/cache.js +59 -0
  161. package/dist/test-utils/database.d.ts +48 -0
  162. package/dist/test-utils/database.js +52 -0
  163. package/dist/test-utils/emitter.d.ts +35 -0
  164. package/dist/test-utils/emitter.js +38 -0
  165. package/dist/test-utils/fields-service.d.ts +28 -0
  166. package/dist/test-utils/fields-service.js +36 -0
  167. package/dist/test-utils/items-service.d.ts +23 -0
  168. package/dist/test-utils/items-service.js +37 -0
  169. package/dist/test-utils/knex.d.ts +164 -0
  170. package/dist/test-utils/knex.js +268 -0
  171. package/dist/test-utils/schema.d.ts +26 -0
  172. package/dist/test-utils/schema.js +35 -0
  173. package/dist/types/auth.d.ts +2 -3
  174. package/dist/utils/apply-diff.js +15 -0
  175. package/dist/utils/create-admin.d.ts +11 -0
  176. package/dist/utils/create-admin.js +50 -0
  177. package/dist/utils/get-schema.js +5 -3
  178. package/dist/utils/get-snapshot-diff.js +49 -5
  179. package/dist/utils/get-snapshot.js +13 -7
  180. package/dist/utils/sanitize-schema.d.ts +11 -4
  181. package/dist/utils/sanitize-schema.js +9 -6
  182. package/dist/utils/schedule.js +15 -19
  183. package/dist/utils/validate-diff.js +31 -0
  184. package/dist/utils/validate-snapshot.js +7 -0
  185. package/dist/utils/versioning/deep-map-with-schema.d.ts +23 -0
  186. package/dist/utils/versioning/deep-map-with-schema.js +81 -0
  187. package/dist/utils/versioning/handle-version.d.ts +2 -2
  188. package/dist/utils/versioning/handle-version.js +47 -43
  189. package/dist/utils/versioning/split-recursive.d.ts +4 -0
  190. package/dist/utils/versioning/split-recursive.js +27 -0
  191. package/dist/websocket/controllers/hooks.js +12 -20
  192. package/dist/websocket/messages.d.ts +3 -3
  193. package/package.json +65 -66
  194. package/dist/cli/utils/defaults.d.ts +0 -4
  195. package/dist/cli/utils/defaults.js +0 -17
  196. package/dist/telemetry/utils/get-project-id.d.ts +0 -2
  197. package/dist/telemetry/utils/get-project-id.js +0 -4
@@ -0,0 +1,96 @@
1
+ import { toArray } from '@directus/utils';
2
+ import { z } from 'zod';
3
+ import { FoldersService } from '../../services/folders.js';
4
+ import { defineTool } from '../define.js';
5
+ import { FolderItemInputSchema, FolderItemValidateSchema, PrimaryKeyInputSchema, PrimaryKeyValidateSchema, QueryInputSchema, QueryValidateSchema, } from '../schema.js';
6
+ import prompts from './prompts/index.js';
7
+ const FoldersValidateSchema = z.discriminatedUnion('action', [
8
+ z.strictObject({
9
+ action: z.literal('create'),
10
+ data: z.union([z.array(FolderItemValidateSchema), FolderItemValidateSchema]),
11
+ query: QueryValidateSchema.optional(),
12
+ }),
13
+ z.strictObject({
14
+ action: z.literal('read'),
15
+ keys: z.array(PrimaryKeyValidateSchema).optional(),
16
+ query: QueryValidateSchema.optional(),
17
+ }),
18
+ z.strictObject({
19
+ action: z.literal('update'),
20
+ data: FolderItemValidateSchema,
21
+ keys: z.array(PrimaryKeyValidateSchema).optional(),
22
+ query: QueryValidateSchema.optional(),
23
+ }),
24
+ z.strictObject({
25
+ action: z.literal('delete'),
26
+ keys: z.array(PrimaryKeyValidateSchema),
27
+ }),
28
+ ]);
29
+ const FoldersInputSchema = z.object({
30
+ action: z.enum(['create', 'read', 'update', 'delete']).describe('The operation to perform'),
31
+ query: QueryInputSchema.optional(),
32
+ keys: z.array(PrimaryKeyInputSchema).optional(),
33
+ data: z.array(FolderItemInputSchema).optional(),
34
+ });
35
+ export const folders = defineTool({
36
+ name: 'folders',
37
+ description: prompts.folders,
38
+ annotations: {
39
+ title: 'Directus - Folders',
40
+ },
41
+ inputSchema: FoldersInputSchema,
42
+ validateSchema: FoldersValidateSchema,
43
+ async handler({ args, schema, accountability, sanitizedQuery }) {
44
+ const service = new FoldersService({
45
+ schema,
46
+ accountability,
47
+ });
48
+ if (args.action === 'create') {
49
+ const data = toArray(args.data);
50
+ const savedKeys = await service.createMany(data);
51
+ const result = await service.readMany(savedKeys, sanitizedQuery);
52
+ return {
53
+ type: 'text',
54
+ data: result || null,
55
+ };
56
+ }
57
+ if (args.action === 'read') {
58
+ let result = null;
59
+ if (args.keys) {
60
+ result = await service.readMany(args.keys, sanitizedQuery);
61
+ }
62
+ else {
63
+ result = await service.readByQuery(sanitizedQuery);
64
+ }
65
+ return {
66
+ type: 'text',
67
+ data: result || null,
68
+ };
69
+ }
70
+ if (args.action === 'update') {
71
+ let updatedKeys = [];
72
+ if (Array.isArray(args.data)) {
73
+ updatedKeys = await service.updateBatch(args.data);
74
+ }
75
+ else if (args.keys) {
76
+ updatedKeys = await service.updateMany(args.keys, args.data);
77
+ }
78
+ else {
79
+ updatedKeys = await service.updateByQuery(sanitizedQuery, args.data);
80
+ }
81
+ const result = await service.readMany(updatedKeys, sanitizedQuery);
82
+ return {
83
+ type: 'text',
84
+ data: result,
85
+ };
86
+ }
87
+ if (args.action === 'delete') {
88
+ const deletedKeys = await service.deleteMany(args.keys);
89
+ return {
90
+ type: 'text',
91
+ data: deletedKeys,
92
+ };
93
+ }
94
+ throw new Error('Invalid action.');
95
+ },
96
+ });
@@ -0,0 +1,15 @@
1
+ import type { ToolConfig } from '../types.js';
2
+ import { collections } from './collections.js';
3
+ import { fields } from './fields.js';
4
+ import { files } from './files.js';
5
+ import { flows } from './flows.js';
6
+ import { items } from './items.js';
7
+ import { operations } from './operations.js';
8
+ import { relations } from './relations.js';
9
+ import { schema } from './schema.js';
10
+ import { system } from './system.js';
11
+ import { triggerFlow } from './trigger-flow.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.js';
2
+ import { collections } from './collections.js';
3
+ import { fields } from './fields.js';
4
+ import { files } from './files.js';
5
+ import { flows } from './flows.js';
6
+ import { folders } from './folders.js';
7
+ import { items } from './items.js';
8
+ import { operations } from './operations.js';
9
+ import { relations } from './relations.js';
10
+ import { schema } from './schema.js';
11
+ import { system } from './system.js';
12
+ import { triggerFlow } from './trigger-flow.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 };
@@ -0,0 +1,87 @@
1
+ export declare const items: import("../types.js").ToolConfig<{
2
+ collection: string;
3
+ action: "create";
4
+ data: Record<string, any> | Record<string, any>[];
5
+ query?: {
6
+ fields?: string[] | undefined;
7
+ sort?: string[] | undefined;
8
+ filter?: Record<string, any> | undefined;
9
+ limit?: number | undefined;
10
+ offset?: number | undefined;
11
+ page?: number | undefined;
12
+ search?: string | undefined;
13
+ deep?: Record<string, any> | undefined;
14
+ alias?: Record<string, string> | undefined;
15
+ aggregate?: {
16
+ count?: string[] | undefined;
17
+ sum?: string[] | undefined;
18
+ avg?: string[] | undefined;
19
+ min?: string[] | undefined;
20
+ max?: string[] | undefined;
21
+ } | undefined;
22
+ backlink?: boolean | undefined;
23
+ version?: string | undefined;
24
+ versionRaw?: boolean | undefined;
25
+ export?: string | undefined;
26
+ groupBy?: string[] | undefined;
27
+ } | undefined;
28
+ } | {
29
+ collection: string;
30
+ action: "read";
31
+ keys?: (string | number)[] | undefined;
32
+ query?: {
33
+ fields?: string[] | undefined;
34
+ sort?: string[] | undefined;
35
+ filter?: Record<string, any> | undefined;
36
+ limit?: number | undefined;
37
+ offset?: number | undefined;
38
+ page?: number | undefined;
39
+ search?: string | undefined;
40
+ deep?: Record<string, any> | undefined;
41
+ alias?: Record<string, string> | undefined;
42
+ aggregate?: {
43
+ count?: string[] | undefined;
44
+ sum?: string[] | undefined;
45
+ avg?: string[] | undefined;
46
+ min?: string[] | undefined;
47
+ max?: string[] | undefined;
48
+ } | undefined;
49
+ backlink?: boolean | undefined;
50
+ version?: string | undefined;
51
+ versionRaw?: boolean | undefined;
52
+ export?: string | undefined;
53
+ groupBy?: string[] | undefined;
54
+ } | undefined;
55
+ } | {
56
+ collection: string;
57
+ action: "update";
58
+ data: Record<string, any> | Record<string, any>[];
59
+ keys?: (string | number)[] | undefined;
60
+ query?: {
61
+ fields?: string[] | undefined;
62
+ sort?: string[] | undefined;
63
+ filter?: Record<string, any> | undefined;
64
+ limit?: number | undefined;
65
+ offset?: number | undefined;
66
+ page?: number | undefined;
67
+ search?: string | undefined;
68
+ deep?: Record<string, any> | undefined;
69
+ alias?: Record<string, string> | undefined;
70
+ aggregate?: {
71
+ count?: string[] | undefined;
72
+ sum?: string[] | undefined;
73
+ avg?: string[] | undefined;
74
+ min?: string[] | undefined;
75
+ max?: string[] | undefined;
76
+ } | undefined;
77
+ backlink?: boolean | undefined;
78
+ version?: string | undefined;
79
+ versionRaw?: boolean | undefined;
80
+ export?: string | undefined;
81
+ groupBy?: string[] | undefined;
82
+ } | undefined;
83
+ } | {
84
+ collection: string;
85
+ action: "delete";
86
+ keys: (string | number)[];
87
+ }>;
@@ -0,0 +1,141 @@
1
+ import { ForbiddenError, InvalidPayloadError } from '@directus/errors';
2
+ import { isSystemCollection } from '@directus/system-data';
3
+ import { toArray } from '@directus/utils';
4
+ import { isObject } from 'graphql-compose';
5
+ import { z } from 'zod';
6
+ import { ItemsService } from '../../services/items.js';
7
+ import { defineTool } from '../define.js';
8
+ import { ItemInputSchema, ItemValidateSchema, PrimaryKeyInputSchema, PrimaryKeyValidateSchema, QueryInputSchema, QueryValidateSchema, } from '../schema.js';
9
+ import prompts from './prompts/index.js';
10
+ const PartialItemInputSchema = z.strictObject({
11
+ collection: z.string(),
12
+ });
13
+ const ItemsValidateSchema = z.discriminatedUnion('action', [
14
+ PartialItemInputSchema.extend({
15
+ action: z.literal('create'),
16
+ data: z.union([z.array(ItemValidateSchema), ItemValidateSchema]),
17
+ query: QueryValidateSchema.optional(),
18
+ }),
19
+ PartialItemInputSchema.extend({
20
+ action: z.literal('read'),
21
+ keys: z.array(PrimaryKeyValidateSchema).optional(),
22
+ query: QueryValidateSchema.optional(),
23
+ }),
24
+ PartialItemInputSchema.extend({
25
+ action: z.literal('update'),
26
+ data: z.union([z.array(ItemValidateSchema), ItemValidateSchema]),
27
+ keys: z.array(PrimaryKeyValidateSchema).optional(),
28
+ query: QueryValidateSchema.optional(),
29
+ }),
30
+ PartialItemInputSchema.extend({
31
+ action: z.literal('delete'),
32
+ keys: z.array(PrimaryKeyValidateSchema),
33
+ }),
34
+ ]);
35
+ const ItemsInputSchema = z.object({
36
+ action: z.enum(['create', 'read', 'update', 'delete']).describe('The operation to perform'),
37
+ collection: z.string().describe('The name of the collection'),
38
+ query: QueryInputSchema.optional(),
39
+ keys: z.array(PrimaryKeyInputSchema).optional(),
40
+ data: z.array(ItemInputSchema).optional(),
41
+ });
42
+ export const items = defineTool({
43
+ name: 'items',
44
+ description: prompts.items,
45
+ annotations: {
46
+ title: 'Directus - Items',
47
+ },
48
+ inputSchema: ItemsInputSchema,
49
+ validateSchema: ItemsValidateSchema,
50
+ endpoint({ input, data }) {
51
+ if (!isObject(data) || !('id' in data)) {
52
+ return;
53
+ }
54
+ return ['content', input.collection, data['id']];
55
+ },
56
+ async handler({ args, schema, accountability, sanitizedQuery }) {
57
+ if (isSystemCollection(args.collection)) {
58
+ throw new InvalidPayloadError({ reason: 'Cannot provide a core collection' });
59
+ }
60
+ if (args.collection in schema.collections === false) {
61
+ throw new ForbiddenError();
62
+ }
63
+ const isSingleton = schema.collections[args.collection]?.singleton ?? false;
64
+ const itemsService = new ItemsService(args.collection, {
65
+ schema,
66
+ accountability,
67
+ });
68
+ if (args.action === 'create') {
69
+ const data = toArray(args.data);
70
+ if (isSingleton) {
71
+ if (Array.isArray(args.data)) {
72
+ throw new InvalidPayloadError({ reason: 'Invalid data payload, object exptected' });
73
+ }
74
+ await itemsService.upsertSingleton(args.data);
75
+ const item = await itemsService.readSingleton(sanitizedQuery);
76
+ return {
77
+ type: 'text',
78
+ data: item || null,
79
+ };
80
+ }
81
+ const savedKeys = await itemsService.createMany(data);
82
+ const result = await itemsService.readMany(savedKeys, sanitizedQuery);
83
+ return {
84
+ type: 'text',
85
+ data: result || null,
86
+ };
87
+ }
88
+ if (args.action === 'read') {
89
+ let result = null;
90
+ if (isSingleton) {
91
+ result = await itemsService.readSingleton(sanitizedQuery);
92
+ }
93
+ else if (args.keys) {
94
+ result = await itemsService.readMany(args.keys, sanitizedQuery);
95
+ }
96
+ else {
97
+ result = await itemsService.readByQuery(sanitizedQuery);
98
+ }
99
+ return {
100
+ type: 'text',
101
+ data: result,
102
+ };
103
+ }
104
+ if (args.action === 'update') {
105
+ if (isSingleton) {
106
+ if (Array.isArray(args.data)) {
107
+ throw new InvalidPayloadError({ reason: 'Invalid data payload, object exptected' });
108
+ }
109
+ await itemsService.upsertSingleton(args.data);
110
+ const item = await itemsService.readSingleton(sanitizedQuery);
111
+ return {
112
+ type: 'text',
113
+ data: item || null,
114
+ };
115
+ }
116
+ let updatedKeys = [];
117
+ if (Array.isArray(args.data)) {
118
+ updatedKeys = await itemsService.updateBatch(args.data);
119
+ }
120
+ else if (args.keys) {
121
+ updatedKeys = await itemsService.updateMany(args.keys, args.data);
122
+ }
123
+ else {
124
+ updatedKeys = await itemsService.updateByQuery(sanitizedQuery, args.data);
125
+ }
126
+ const result = await itemsService.readMany(updatedKeys, sanitizedQuery);
127
+ return {
128
+ type: 'text',
129
+ data: result,
130
+ };
131
+ }
132
+ if (args.action === 'delete') {
133
+ const deletedKeys = await itemsService.deleteMany(args.keys);
134
+ return {
135
+ type: 'text',
136
+ data: deletedKeys,
137
+ };
138
+ }
139
+ throw new Error('Invalid action.');
140
+ },
141
+ });
@@ -0,0 +1,171 @@
1
+ import { z } from 'zod';
2
+ export declare const OperationsValidationSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
3
+ action: z.ZodLiteral<"create">;
4
+ data: z.ZodObject<{
5
+ id: z.ZodOptional<z.ZodString>;
6
+ name: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNull]>>;
7
+ key: z.ZodOptional<z.ZodString>;
8
+ type: z.ZodOptional<z.ZodString>;
9
+ position_x: z.ZodOptional<z.ZodNumber>;
10
+ position_y: z.ZodOptional<z.ZodNumber>;
11
+ options: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
12
+ resolve: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNull]>>;
13
+ reject: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNull]>>;
14
+ flow: z.ZodOptional<z.ZodString>;
15
+ date_created: z.ZodOptional<z.ZodString>;
16
+ user_created: z.ZodOptional<z.ZodString>;
17
+ }, z.core.$strip>;
18
+ }, z.core.$strict>, z.ZodObject<{
19
+ action: z.ZodLiteral<"read">;
20
+ query: z.ZodOptional<z.ZodObject<{
21
+ fields: z.ZodOptional<z.ZodArray<z.ZodString>>;
22
+ sort: z.ZodOptional<z.ZodArray<z.ZodString>>;
23
+ filter: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
24
+ limit: z.ZodOptional<z.ZodNumber>;
25
+ offset: z.ZodOptional<z.ZodNumber>;
26
+ page: z.ZodOptional<z.ZodNumber>;
27
+ search: z.ZodOptional<z.ZodString>;
28
+ deep: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
29
+ alias: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
30
+ aggregate: z.ZodOptional<z.ZodObject<{
31
+ count: z.ZodOptional<z.ZodArray<z.ZodString>>;
32
+ sum: z.ZodOptional<z.ZodArray<z.ZodString>>;
33
+ avg: z.ZodOptional<z.ZodArray<z.ZodString>>;
34
+ min: z.ZodOptional<z.ZodArray<z.ZodString>>;
35
+ max: z.ZodOptional<z.ZodArray<z.ZodString>>;
36
+ }, z.core.$strip>>;
37
+ backlink: z.ZodOptional<z.ZodBoolean>;
38
+ version: z.ZodOptional<z.ZodString>;
39
+ versionRaw: z.ZodOptional<z.ZodBoolean>;
40
+ export: z.ZodOptional<z.ZodString>;
41
+ groupBy: z.ZodOptional<z.ZodArray<z.ZodString>>;
42
+ }, z.core.$strip>>;
43
+ }, z.core.$strict>, z.ZodObject<{
44
+ action: z.ZodLiteral<"update">;
45
+ data: z.ZodObject<{
46
+ id: z.ZodOptional<z.ZodString>;
47
+ name: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNull]>>;
48
+ key: z.ZodOptional<z.ZodString>;
49
+ type: z.ZodOptional<z.ZodString>;
50
+ position_x: z.ZodOptional<z.ZodNumber>;
51
+ position_y: z.ZodOptional<z.ZodNumber>;
52
+ options: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
53
+ resolve: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNull]>>;
54
+ reject: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNull]>>;
55
+ flow: z.ZodOptional<z.ZodString>;
56
+ date_created: z.ZodOptional<z.ZodString>;
57
+ user_created: z.ZodOptional<z.ZodString>;
58
+ }, z.core.$strip>;
59
+ key: z.ZodString;
60
+ }, z.core.$strict>, z.ZodObject<{
61
+ action: z.ZodLiteral<"delete">;
62
+ key: z.ZodString;
63
+ }, z.core.$strict>], "action">;
64
+ export declare const OperationsInputSchema: z.ZodObject<{
65
+ action: z.ZodEnum<{
66
+ delete: "delete";
67
+ update: "update";
68
+ create: "create";
69
+ read: "read";
70
+ }>;
71
+ query: z.ZodOptional<z.ZodObject<{
72
+ fields: z.ZodOptional<z.ZodArray<z.ZodString>>;
73
+ sort: z.ZodOptional<z.ZodArray<z.ZodString>>;
74
+ filter: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
75
+ limit: z.ZodOptional<z.ZodNumber>;
76
+ offset: z.ZodOptional<z.ZodNumber>;
77
+ page: z.ZodOptional<z.ZodNumber>;
78
+ search: z.ZodOptional<z.ZodString>;
79
+ deep: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
80
+ alias: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
81
+ aggregate: z.ZodOptional<z.ZodObject<{
82
+ count: z.ZodOptional<z.ZodArray<z.ZodString>>;
83
+ sum: z.ZodOptional<z.ZodArray<z.ZodString>>;
84
+ avg: z.ZodOptional<z.ZodArray<z.ZodString>>;
85
+ min: z.ZodOptional<z.ZodArray<z.ZodString>>;
86
+ max: z.ZodOptional<z.ZodArray<z.ZodString>>;
87
+ }, z.core.$strip>>;
88
+ backlink: z.ZodOptional<z.ZodBoolean>;
89
+ version: z.ZodOptional<z.ZodString>;
90
+ versionRaw: z.ZodOptional<z.ZodBoolean>;
91
+ export: z.ZodOptional<z.ZodString>;
92
+ groupBy: z.ZodOptional<z.ZodArray<z.ZodString>>;
93
+ }, z.core.$strip>>;
94
+ data: z.ZodOptional<z.ZodObject<{
95
+ id: z.ZodOptional<z.ZodString>;
96
+ name: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNull]>>;
97
+ key: z.ZodOptional<z.ZodString>;
98
+ type: z.ZodOptional<z.ZodString>;
99
+ position_x: z.ZodOptional<z.ZodNumber>;
100
+ position_y: z.ZodOptional<z.ZodNumber>;
101
+ options: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
102
+ resolve: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNull]>>;
103
+ reject: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNull]>>;
104
+ flow: z.ZodOptional<z.ZodString>;
105
+ date_created: z.ZodOptional<z.ZodString>;
106
+ user_created: z.ZodOptional<z.ZodString>;
107
+ }, z.core.$strip>>;
108
+ key: z.ZodOptional<z.ZodString>;
109
+ }, z.core.$strip>;
110
+ export declare const operations: import("../types.js").ToolConfig<{
111
+ action: "create";
112
+ data: {
113
+ id?: string | undefined;
114
+ name?: string | null | undefined;
115
+ key?: string | undefined;
116
+ type?: string | undefined;
117
+ position_x?: number | undefined;
118
+ position_y?: number | undefined;
119
+ options?: Record<string, any> | undefined;
120
+ resolve?: string | null | undefined;
121
+ reject?: string | null | undefined;
122
+ flow?: string | undefined;
123
+ date_created?: string | undefined;
124
+ user_created?: string | undefined;
125
+ };
126
+ } | {
127
+ action: "read";
128
+ query?: {
129
+ fields?: string[] | undefined;
130
+ sort?: string[] | undefined;
131
+ filter?: Record<string, any> | undefined;
132
+ limit?: number | undefined;
133
+ offset?: number | undefined;
134
+ page?: number | undefined;
135
+ search?: string | undefined;
136
+ deep?: Record<string, any> | undefined;
137
+ alias?: Record<string, string> | undefined;
138
+ aggregate?: {
139
+ count?: string[] | undefined;
140
+ sum?: string[] | undefined;
141
+ avg?: string[] | undefined;
142
+ min?: string[] | undefined;
143
+ max?: string[] | undefined;
144
+ } | undefined;
145
+ backlink?: boolean | undefined;
146
+ version?: string | undefined;
147
+ versionRaw?: boolean | undefined;
148
+ export?: string | undefined;
149
+ groupBy?: string[] | undefined;
150
+ } | undefined;
151
+ } | {
152
+ action: "update";
153
+ data: {
154
+ id?: string | undefined;
155
+ name?: string | null | undefined;
156
+ key?: string | undefined;
157
+ type?: string | undefined;
158
+ position_x?: number | undefined;
159
+ position_y?: number | undefined;
160
+ options?: Record<string, any> | undefined;
161
+ resolve?: string | null | undefined;
162
+ reject?: string | null | undefined;
163
+ flow?: string | undefined;
164
+ date_created?: string | undefined;
165
+ user_created?: string | undefined;
166
+ };
167
+ key: string;
168
+ } | {
169
+ action: "delete";
170
+ key: string;
171
+ }>;
@@ -0,0 +1,77 @@
1
+ import { z } from 'zod';
2
+ import { OperationsService } from '../../services/operations.js';
3
+ import { defineTool } from '../define.js';
4
+ import { OperationItemInputSchema, OperationItemValidateSchema, QueryInputSchema, QueryValidateSchema, } from '../schema.js';
5
+ import prompts from './prompts/index.js';
6
+ export const OperationsValidationSchema = z.discriminatedUnion('action', [
7
+ z.strictObject({
8
+ action: z.literal('create'),
9
+ data: OperationItemValidateSchema,
10
+ }),
11
+ z.strictObject({
12
+ action: z.literal('read'),
13
+ query: QueryValidateSchema.optional(),
14
+ }),
15
+ z.strictObject({
16
+ action: z.literal('update'),
17
+ data: OperationItemValidateSchema,
18
+ key: z.string(),
19
+ }),
20
+ z.strictObject({
21
+ action: z.literal('delete'),
22
+ key: z.string(),
23
+ }),
24
+ ]);
25
+ export const OperationsInputSchema = z.object({
26
+ action: z.enum(['create', 'read', 'update', 'delete']).describe('The operation to perform'),
27
+ query: QueryInputSchema.optional(),
28
+ data: OperationItemInputSchema.optional(),
29
+ key: z.string().optional(),
30
+ });
31
+ export const operations = defineTool({
32
+ name: 'operations',
33
+ admin: true,
34
+ description: prompts.operations,
35
+ annotations: {
36
+ title: 'Directus - Operations',
37
+ },
38
+ inputSchema: OperationsInputSchema,
39
+ validateSchema: OperationsValidationSchema,
40
+ async handler({ args, schema, accountability, sanitizedQuery }) {
41
+ const operationService = new OperationsService({
42
+ schema,
43
+ accountability,
44
+ });
45
+ if (args.action === 'create') {
46
+ const savedKey = await operationService.createOne(args.data);
47
+ const result = await operationService.readOne(savedKey);
48
+ return {
49
+ type: 'text',
50
+ data: result || null,
51
+ };
52
+ }
53
+ if (args.action === 'read') {
54
+ const result = await operationService.readByQuery(sanitizedQuery);
55
+ return {
56
+ type: 'text',
57
+ data: result || null,
58
+ };
59
+ }
60
+ if (args.action === 'update') {
61
+ const updatedKey = await operationService.updateOne(args.key, args.data);
62
+ const result = await operationService.readOne(updatedKey, sanitizedQuery);
63
+ return {
64
+ type: 'text',
65
+ data: result || null,
66
+ };
67
+ }
68
+ if (args.action === 'delete') {
69
+ const deletedKey = await operationService.deleteOne(args.key);
70
+ return {
71
+ type: 'text',
72
+ data: deletedKey,
73
+ };
74
+ }
75
+ throw new Error('Invalid action.');
76
+ },
77
+ });
@@ -0,0 +1,8 @@
1
+ Retrieve base64-encoded file content from Directus. Returns raw file data suitable for AI vision models, image analysis,
2
+ and file operations.
3
+
4
+ **Input**: `{"id": "file-uuid"}`
5
+
6
+ **Output**: `{"data": "base64-string", "mimeType": "image/jpeg"}`
7
+
8
+ **Note**: Supports images and audio files. Respects Directus permissions.