@directus/api 30.0.0 → 31.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 (83) hide show
  1. package/dist/app.js +5 -0
  2. package/dist/auth/drivers/oauth2.js +17 -3
  3. package/dist/auth/drivers/openid.js +17 -3
  4. package/dist/controllers/mcp.d.ts +2 -0
  5. package/dist/controllers/mcp.js +33 -0
  6. package/dist/controllers/users.js +17 -7
  7. package/dist/controllers/versions.js +3 -2
  8. package/dist/database/errors/dialects/mssql.d.ts +1 -1
  9. package/dist/database/errors/dialects/mssql.js +18 -10
  10. package/dist/database/migrations/20250813A-add-mcp.d.ts +3 -0
  11. package/dist/database/migrations/20250813A-add-mcp.js +18 -0
  12. package/dist/database/run-ast/README.md +46 -0
  13. package/dist/mcp/define.d.ts +2 -0
  14. package/dist/mcp/define.js +3 -0
  15. package/dist/mcp/index.d.ts +1 -0
  16. package/dist/mcp/index.js +1 -0
  17. package/dist/mcp/schema.d.ts +485 -0
  18. package/dist/mcp/schema.js +219 -0
  19. package/dist/mcp/server.d.ts +97 -0
  20. package/dist/mcp/server.js +310 -0
  21. package/dist/mcp/tools/assets.d.ts +3 -0
  22. package/dist/mcp/tools/assets.js +54 -0
  23. package/dist/mcp/tools/collections.d.ts +84 -0
  24. package/dist/mcp/tools/collections.js +90 -0
  25. package/dist/mcp/tools/fields.d.ts +101 -0
  26. package/dist/mcp/tools/fields.js +157 -0
  27. package/dist/mcp/tools/files.d.ts +235 -0
  28. package/dist/mcp/tools/files.js +103 -0
  29. package/dist/mcp/tools/flows.d.ts +323 -0
  30. package/dist/mcp/tools/flows.js +85 -0
  31. package/dist/mcp/tools/folders.d.ts +95 -0
  32. package/dist/mcp/tools/folders.js +96 -0
  33. package/dist/mcp/tools/index.d.ts +15 -0
  34. package/dist/mcp/tools/index.js +29 -0
  35. package/dist/mcp/tools/items.d.ts +87 -0
  36. package/dist/mcp/tools/items.js +141 -0
  37. package/dist/mcp/tools/operations.d.ts +171 -0
  38. package/dist/mcp/tools/operations.js +77 -0
  39. package/dist/mcp/tools/prompts/assets.md +8 -0
  40. package/dist/mcp/tools/prompts/collections.md +336 -0
  41. package/dist/mcp/tools/prompts/fields.md +521 -0
  42. package/dist/mcp/tools/prompts/files.md +180 -0
  43. package/dist/mcp/tools/prompts/flows.md +495 -0
  44. package/dist/mcp/tools/prompts/folders.md +34 -0
  45. package/dist/mcp/tools/prompts/index.d.ts +16 -0
  46. package/dist/mcp/tools/prompts/index.js +19 -0
  47. package/dist/mcp/tools/prompts/items.md +317 -0
  48. package/dist/mcp/tools/prompts/operations.md +721 -0
  49. package/dist/mcp/tools/prompts/relations.md +386 -0
  50. package/dist/mcp/tools/prompts/schema.md +130 -0
  51. package/dist/mcp/tools/prompts/system-prompt-description.md +1 -0
  52. package/dist/mcp/tools/prompts/system-prompt.md +44 -0
  53. package/dist/mcp/tools/prompts/trigger-flow.md +214 -0
  54. package/dist/mcp/tools/relations.d.ts +73 -0
  55. package/dist/mcp/tools/relations.js +93 -0
  56. package/dist/mcp/tools/schema.d.ts +54 -0
  57. package/dist/mcp/tools/schema.js +317 -0
  58. package/dist/mcp/tools/system.d.ts +3 -0
  59. package/dist/mcp/tools/system.js +22 -0
  60. package/dist/mcp/tools/trigger-flow.d.ts +8 -0
  61. package/dist/mcp/tools/trigger-flow.js +48 -0
  62. package/dist/mcp/transport.d.ts +13 -0
  63. package/dist/mcp/transport.js +18 -0
  64. package/dist/mcp/types.d.ts +56 -0
  65. package/dist/mcp/types.js +1 -0
  66. package/dist/services/authentication.js +36 -0
  67. package/dist/services/fields.js +4 -4
  68. package/dist/services/items.js +14 -4
  69. package/dist/services/payload.d.ts +7 -3
  70. package/dist/services/payload.js +26 -12
  71. package/dist/services/server.js +1 -0
  72. package/dist/services/tfa.d.ts +1 -1
  73. package/dist/services/tfa.js +20 -5
  74. package/dist/services/versions.d.ts +6 -4
  75. package/dist/services/versions.js +84 -25
  76. package/dist/types/auth.d.ts +2 -1
  77. package/dist/utils/versioning/deep-map-with-schema.d.ts +23 -0
  78. package/dist/utils/versioning/deep-map-with-schema.js +81 -0
  79. package/dist/utils/versioning/handle-version.d.ts +2 -2
  80. package/dist/utils/versioning/handle-version.js +47 -43
  81. package/dist/utils/versioning/split-recursive.d.ts +4 -0
  82. package/dist/utils/versioning/split-recursive.js +27 -0
  83. package/package.json +30 -29
@@ -0,0 +1,214 @@
1
+ # Directus Trigger Flow Tool
2
+
3
+ Execute flows programmatically. This tool allows you to trigger manual flows, pass data to flows, and chain flows
4
+ together for complex automation.
5
+
6
+ ## 🔑 Key Concepts
7
+
8
+ - **Prerequisite**: ALWAYS read the flow first using `flows` tool to get the full definition
9
+ - **Manual Flows**: Flows with `trigger: "manual"` are designed to be triggered via UI or this tool
10
+ - **Flow Chaining**: Any flow can be triggered, receiving data in `$trigger.body`
11
+ - **Validation**: Tool validates collection support, required fields, and selection requirements
12
+
13
+ ## Required Parameters
14
+
15
+ ```json
16
+ {
17
+ "flowDefinition": {}, // FULL flow object from flows.read
18
+ "flowId": "uuid", // Flow ID to trigger
19
+ "collection": "name", // Collection context
20
+ "keys": ["id1"], // Item IDs (required if flow needs selection)
21
+ "method": "POST", // GET or POST (default: GET)
22
+ "data": {}, // Optional payload data
23
+ "query": {}, // Optional query parameters
24
+ "headers": {} // Optional headers
25
+ }
26
+ ```
27
+
28
+ ## 📋 Flow Types & Requirements
29
+
30
+ ### Manual Flow with Selection
31
+
32
+ For flows with `requireSelection: true` or undefined:
33
+
34
+ ```json
35
+ {
36
+ "flowDefinition": {
37
+ "id": "abc-123",
38
+ "trigger": "manual",
39
+ "options": {
40
+ "collections": ["products", "orders"],
41
+ "requireSelection": true,
42
+ "fields": [
43
+ {
44
+ "field": "reason",
45
+ "name": "Reason",
46
+ "meta": { "required": true }
47
+ }
48
+ ]
49
+ }
50
+ },
51
+ "flowId": "abc-123",
52
+ "collection": "products",
53
+ "keys": ["prod-1", "prod-2"], // REQUIRED
54
+ "data": {
55
+ "reason": "Bulk update" // Required field
56
+ }
57
+ }
58
+ ```
59
+
60
+ ### Manual Flow without Selection
61
+
62
+ For flows with `requireSelection: false`:
63
+
64
+ ```json
65
+ {
66
+ "flowDefinition": {
67
+ "id": "xyz-456",
68
+ "trigger": "manual",
69
+ "options": {
70
+ "collections": ["reports"],
71
+ "requireSelection": false
72
+ }
73
+ },
74
+ "flowId": "xyz-456",
75
+ "collection": "reports",
76
+ "keys": [], // Optional when requireSelection: false
77
+ "data": {
78
+ "type": "monthly"
79
+ }
80
+ }
81
+ ```
82
+
83
+ ### Webhook/Operation Flows
84
+
85
+ Flows with webhook or operation triggers:
86
+
87
+ ```json
88
+ {
89
+ "flowDefinition": {
90
+ "id": "webhook-flow",
91
+ "trigger": "webhook",
92
+ "options": {
93
+ "collections": ["*"] // or specific collections
94
+ }
95
+ },
96
+ "flowId": "webhook-flow",
97
+ "collection": "any_collection",
98
+ "method": "POST",
99
+ "data": {
100
+ "custom": "payload"
101
+ },
102
+ "headers": {
103
+ "X-Custom-Header": "value"
104
+ }
105
+ }
106
+ ```
107
+
108
+ ## 🔄 Validation Rules
109
+
110
+ The tool validates:
111
+
112
+ 1. **Flow Definition**: Must provide complete flow object
113
+ 2. **Flow ID Match**: Definition ID must match flowId parameter
114
+ 3. **Collection Support**: Collection must be in flow's collections array
115
+ 4. **Selection Required**: Keys required when `requireSelection !== false`
116
+ 5. **Required Fields**: All required fields must be present in data
117
+
118
+ ## ⚡ Common Workflows
119
+
120
+ ### 1. Export Selected Items
121
+
122
+ ```json
123
+ // Step 1: Get flow definition
124
+ flows.read({ filter: { name: { _eq: "Export Items" }}})
125
+
126
+ // Step 2: Trigger with selection
127
+ {
128
+ "flowDefinition": { /* from step 1 */ },
129
+ "flowId": "export-flow-id",
130
+ "collection": "products",
131
+ "keys": ["1", "2", "3"],
132
+ "data": {
133
+ "format": "csv",
134
+ "email": "user@example.com"
135
+ }
136
+ }
137
+ ```
138
+
139
+ ### 2. Process Batch Without Selection
140
+
141
+ ```json
142
+ // For flows that process all items
143
+ {
144
+ "flowDefinition": {
145
+ /* flow with requireSelection: false */
146
+ },
147
+ "flowId": "batch-process",
148
+ "collection": "orders",
149
+ "keys": [], // Empty when not required
150
+ "data": {
151
+ "status": "pending",
152
+ "date_range": "last_30_days"
153
+ }
154
+ }
155
+ ```
156
+
157
+ ### 3. Chain Flows Together
158
+
159
+ ```json
160
+ // Trigger a flow from another flow
161
+ {
162
+ "flowDefinition": {
163
+ /* operation trigger flow */
164
+ },
165
+ "flowId": "child-flow",
166
+ "collection": "notifications",
167
+ "data": {
168
+ "parent_result": "{{ $last }}", // Data from parent flow
169
+ "step": 2
170
+ }
171
+ }
172
+ ```
173
+
174
+ ## 📊 Data Access in Triggered Flow
175
+
176
+ The triggered flow receives:
177
+
178
+ - `$trigger.body` - The `data` parameter you send
179
+ - `$trigger.query` - The `query` parameter
180
+ - `$trigger.headers` - The `headers` parameter
181
+ - `$trigger.collection` - The collection context
182
+ - `$trigger.keys` - The selected item IDs
183
+ - `$accountability` - User/permission context
184
+
185
+ ## ⚠️ Important Notes
186
+
187
+ - **Read First**: ALWAYS read the flow definition before triggering
188
+ - **Collection Wildcard**: `"*"` in collections means any collection is accepted
189
+ - **Required Fields**: Check `options.fields` for required inputs
190
+ - **For-Each**: If you pass an array, flow runs once per array item
191
+ - **Response**: Flow can return data via its trigger's `return` option
192
+ - **Permissions**: Respects flow's `accountability` setting
193
+
194
+ ## 🚨 Common Mistakes to Avoid
195
+
196
+ 1. **Don't** trigger without reading flow definition first
197
+ 2. **Don't** omit keys when flow requires selection
198
+ 3. **Don't** ignore required fields in flow configuration
199
+ 4. **Don't** use wrong collection not in flow's collections list
200
+ 5. **Don't** assume `requireSelection` - check explicitly
201
+ 6. **Don't** pass stringified JSON - use native objects
202
+
203
+ ## Decision Tree
204
+
205
+ ```
206
+ 1. Read flow definition using flows tool
207
+ 2. Check trigger type:
208
+ - manual → Check requireSelection
209
+ - webhook/operation → Keys optional
210
+ 3. Validate collection in flow.options.collections
211
+ 4. If requireSelection !== false → keys required
212
+ 5. Check flow.options.fields for required data fields
213
+ 6. Trigger with all validated parameters
214
+ ```
@@ -0,0 +1,73 @@
1
+ export declare const relations: import("../types.js").ToolConfig<{
2
+ action: "create";
3
+ collection: string;
4
+ data: {
5
+ collection: string;
6
+ field: string;
7
+ related_collection: string | null;
8
+ meta: {
9
+ id?: number | undefined;
10
+ many_collection?: string | undefined;
11
+ many_field?: string | undefined;
12
+ one_collection?: string | null | undefined;
13
+ one_field?: string | null | undefined;
14
+ one_collection_field?: string | null | undefined;
15
+ one_allowed_collections?: string[] | null | undefined;
16
+ one_deselect_action?: "nullify" | "delete" | undefined;
17
+ junction_field?: string | null | undefined;
18
+ sort_field?: string | null | undefined;
19
+ system?: boolean | undefined;
20
+ } | null;
21
+ schema?: {
22
+ table?: string | undefined;
23
+ column?: string | undefined;
24
+ foreign_key_table?: string | undefined;
25
+ foreign_key_column?: string | undefined;
26
+ foreign_key_schema?: string | undefined;
27
+ constraint_name?: string | null | undefined;
28
+ on_update?: "NO ACTION" | "RESTRICT" | "CASCADE" | "SET NULL" | "SET DEFAULT" | null | undefined;
29
+ on_delete?: "NO ACTION" | "RESTRICT" | "CASCADE" | "SET NULL" | "SET DEFAULT" | null | undefined;
30
+ } | null | undefined;
31
+ };
32
+ field?: string | undefined;
33
+ } | {
34
+ action: "read";
35
+ collection?: string | undefined;
36
+ field?: string | undefined;
37
+ } | {
38
+ action: "update";
39
+ collection: string;
40
+ field: string;
41
+ data?: {
42
+ collection: string;
43
+ field: string;
44
+ related_collection?: string | null | undefined;
45
+ schema?: {
46
+ table?: string | undefined;
47
+ column?: string | undefined;
48
+ foreign_key_table?: string | undefined;
49
+ foreign_key_column?: string | undefined;
50
+ foreign_key_schema?: string | undefined;
51
+ constraint_name?: string | null | undefined;
52
+ on_update?: "NO ACTION" | "RESTRICT" | "CASCADE" | "SET NULL" | "SET DEFAULT" | null | undefined;
53
+ on_delete?: "NO ACTION" | "RESTRICT" | "CASCADE" | "SET NULL" | "SET DEFAULT" | null | undefined;
54
+ } | null | undefined;
55
+ meta?: {
56
+ id?: number | undefined;
57
+ many_collection?: string | undefined;
58
+ many_field?: string | undefined;
59
+ one_collection?: string | null | undefined;
60
+ one_field?: string | null | undefined;
61
+ one_collection_field?: string | null | undefined;
62
+ one_allowed_collections?: string[] | null | undefined;
63
+ one_deselect_action?: "nullify" | "delete" | undefined;
64
+ junction_field?: string | null | undefined;
65
+ sort_field?: string | null | undefined;
66
+ system?: boolean | undefined;
67
+ } | null | undefined;
68
+ } | undefined;
69
+ } | {
70
+ action: "delete";
71
+ collection: string;
72
+ field: string;
73
+ }>;
@@ -0,0 +1,93 @@
1
+ import { InvalidPayloadError } from '@directus/errors';
2
+ import { z } from 'zod';
3
+ import { RelationsService } from '../../services/relations.js';
4
+ import { defineTool } from '../define.js';
5
+ import { RelationItemInputSchema, RelationItemValidateCreateSchema, RelationItemValidateUpdateSchema, } from '../schema.js';
6
+ import prompts from './prompts/index.js';
7
+ const RelationsValidateSchema = z.discriminatedUnion('action', [
8
+ z.object({
9
+ action: z.literal('create'),
10
+ collection: z.string(),
11
+ field: z.string().optional(),
12
+ data: RelationItemValidateCreateSchema,
13
+ }),
14
+ z.object({
15
+ action: z.literal('read'),
16
+ collection: z.string().optional(),
17
+ field: z.string().optional(),
18
+ }),
19
+ z.object({
20
+ action: z.literal('update'),
21
+ collection: z.string(),
22
+ field: z.string(),
23
+ data: RelationItemValidateUpdateSchema,
24
+ }),
25
+ z.object({
26
+ action: z.literal('delete'),
27
+ collection: z.string(),
28
+ field: z.string(),
29
+ }),
30
+ ]);
31
+ const RelationsInputSchema = z.object({
32
+ action: z.enum(['create', 'read', 'update', 'delete']).describe('The operation to perform'),
33
+ collection: z.string().describe('The name of the collection (required for create, update, delete)').optional(),
34
+ field: z.string().describe('The name of the field (required for create, update, delete)').optional(),
35
+ data: RelationItemInputSchema.optional().describe('The relation data. (required for create, update)'),
36
+ });
37
+ export const relations = defineTool({
38
+ name: 'relations',
39
+ admin: true,
40
+ description: prompts.relations,
41
+ annotations: {
42
+ title: 'Directus - Relations',
43
+ },
44
+ inputSchema: RelationsInputSchema,
45
+ validateSchema: RelationsValidateSchema,
46
+ async handler({ args, schema, accountability }) {
47
+ const service = new RelationsService({
48
+ schema,
49
+ accountability,
50
+ });
51
+ if (args.action === 'create') {
52
+ await service.createOne(args.data);
53
+ const result = await service.readOne(args.collection, args.field || args.data.field);
54
+ return {
55
+ type: 'text',
56
+ data: result || null,
57
+ };
58
+ }
59
+ if (args.action === 'read') {
60
+ let result = null;
61
+ if (args.field && args.collection) {
62
+ result = await service.readOne(args.collection, args.field);
63
+ }
64
+ else if (args.collection) {
65
+ result = await service.readAll(args.collection);
66
+ }
67
+ else {
68
+ result = await service.readAll();
69
+ }
70
+ return {
71
+ type: 'text',
72
+ data: result || null,
73
+ };
74
+ }
75
+ if (args.action === 'update') {
76
+ await service.updateOne(args.collection, args.field, args.data);
77
+ const result = await service.readOne(args.collection, args.field);
78
+ return {
79
+ type: 'text',
80
+ data: result || null,
81
+ };
82
+ }
83
+ if (args.action === 'delete') {
84
+ const { collection, field } = args;
85
+ await service.deleteOne(collection, field);
86
+ return {
87
+ type: 'text',
88
+ data: { collection, field },
89
+ };
90
+ }
91
+ throw new InvalidPayloadError({ reason: 'Invalid action' });
92
+ },
93
+ });
@@ -0,0 +1,54 @@
1
+ import type { Field, Relation } from '@directus/types';
2
+ import { z } from 'zod';
3
+ import type { Collection } from '../../types/collection.js';
4
+ export interface fieldOverviewOutput {
5
+ type: string;
6
+ primary_key?: boolean;
7
+ required?: boolean;
8
+ readonly?: boolean;
9
+ note?: string;
10
+ interface?: {
11
+ type: string;
12
+ choices?: Array<string | number>;
13
+ };
14
+ relation?: {
15
+ type: string;
16
+ related_collection?: string;
17
+ many_collection?: string;
18
+ many_field?: string;
19
+ one_allowed_collections?: string[];
20
+ junction?: {
21
+ collection: string;
22
+ many_field: string;
23
+ junction_field: string;
24
+ one_collection_field?: string;
25
+ sort_field?: string;
26
+ };
27
+ };
28
+ fields?: Record<string, fieldOverviewOutput>;
29
+ value?: string;
30
+ }
31
+ export interface OverviewOutput {
32
+ [collection: string]: {
33
+ [field: string]: fieldOverviewOutput;
34
+ };
35
+ }
36
+ export interface LightweightOverview {
37
+ collections: string[];
38
+ collection_folders: string[];
39
+ notes: Record<string, string>;
40
+ }
41
+ export interface SchemaToolSnapshot {
42
+ collections: Collection[];
43
+ fields: Field[];
44
+ relations: Relation[];
45
+ }
46
+ export declare const SchemaValidateSchema: z.ZodObject<{
47
+ keys: z.ZodOptional<z.ZodArray<z.ZodString>>;
48
+ }, z.core.$strict>;
49
+ export declare const SchemaInputSchema: z.ZodObject<{
50
+ keys: z.ZodOptional<z.ZodArray<z.ZodString>>;
51
+ }, z.core.$strip>;
52
+ export declare const schema: import("../types.js").ToolConfig<{
53
+ keys?: string[] | undefined;
54
+ }>;