@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,521 @@
1
+ Perform CRUD operations on Directus Fields.
2
+
3
+ <actions>
4
+ - `create`: Add one or multiple fields to a collection
5
+ - `read`: View field configurations
6
+ - `update`: Update one or multiple fields
7
+ - `delete`: Remove fields
8
+ </actions>
9
+
10
+ <field_types>
11
+
12
+ - **Text**: `string` (max 255 chars), `text` (unlimited), `uuid` (relations/IDs), `hash` (passwords)
13
+ - **Numeric**: `integer`, `bigInteger`, `float`, `decimal` (for financial precision)
14
+ - **Date/Time**: `timestamp`, `datetime`, `date`, `time`
15
+ - **Boolean**: `boolean` for toggles/flags
16
+ - **Structured**: `json` (complex data), `csv` (tags/lists)
17
+ - **Alias**: Virtual fields for relations (`o2m`, `m2m`, `m2a`, `files`, `translations`)
18
+ - **Geospatial**: `point`, `lineString`, `polygon` for maps </field_types>
19
+
20
+ <adding_fields>
21
+
22
+ **Important**: When using the `fields` tool, `data` must always be an array of field objects, even for single fields.
23
+ Make sure you include `meta` and `schema` objects for each field.
24
+
25
+ Add fields to existing collections:
26
+
27
+ ```json
28
+ {
29
+ "action": "create",
30
+ "collection": "articles",
31
+ "data": [
32
+ {
33
+ "field": "excerpt",
34
+ "type": "text",
35
+ "meta": {
36
+ "interface": "input-rich-text-md",
37
+ "special": null,
38
+ "note": "Article excerpt for previews and SEO. Supports markdown formatting.",
39
+ "translations": [
40
+ {
41
+ "language": "en-US",
42
+ "translation": "Excerpt"
43
+ }
44
+ ],
45
+ "options": {
46
+ "placeholder": null,
47
+ "customSyntax": null
48
+ },
49
+ "display": "formatted-value",
50
+ "display_options": { "format": true }
51
+ },
52
+ "schema": {
53
+ "name": "test",
54
+ "table": "random_collection",
55
+ "data_type": "text"
56
+ }
57
+ }
58
+ ]
59
+ }
60
+ ```
61
+
62
+ **Multiple Fields Example:**
63
+
64
+ ```json
65
+ {
66
+ "action": "create",
67
+ "collection": "articles",
68
+ "data": [
69
+ {
70
+ "field": "title",
71
+ "type": "string"
72
+ // Rest of field data
73
+ },
74
+ {
75
+ "field": "content",
76
+ "type": "text"
77
+ // Rest of field data
78
+ }
79
+ ]
80
+ }
81
+ ```
82
+
83
+ **Note**: You can omit `null` or `false` values from the schema object. </adding_fields>
84
+
85
+ <relationship_fields>
86
+
87
+ **CRITICAL**: Field type and meta.special determine relationship behavior.
88
+
89
+ - **M2O**: `type: "uuid"`, `special: ["m2o"]`, interface: `select-dropdown-m2o` → then create relation
90
+ - **O2M**: `type: "alias"`, `special: ["o2m"]`, interface: `list-o2m` → auto-created with M2O
91
+ - **M2M**: `type: "alias"`, `special: ["m2m"]`, interface: `list-m2m` → needs junction collection
92
+ - **M2A**: `type: "alias"`, `special: ["m2a"]`, interface: `list-m2a` → polymorphic, needs junction
93
+ - **File**: `type: "uuid"`, `special: ["file"]`, interface: `file` or `file-image` → single file relation
94
+ - **Files**: `type: "alias"`, `special: ["files"]`, interface: `files` → multiple files via M2M
95
+ - **Translations**: `type: "alias"`, `special: ["translations"]`, interface: `translations` → special M2M
96
+
97
+ ### M2O Field Example
98
+
99
+ ```json
100
+ {
101
+ "collection": "posts",
102
+ "field": "author",
103
+ "type": "uuid",
104
+ "schema": {
105
+ "name": "author",
106
+ "table": "posts",
107
+ "data_type": "uuid",
108
+ "is_nullable": true,
109
+ "foreign_key_schema": "public",
110
+ "foreign_key_table": "team",
111
+ "foreign_key_column": "id"
112
+ },
113
+ "meta": {
114
+ "collection": "posts",
115
+ "field": "author",
116
+ "special": ["m2o"],
117
+ "interface": "select-dropdown-m2o",
118
+ "options": {
119
+ "template": "{{image.$thumbnail}} {{name}}"
120
+ },
121
+ "display": "related-values",
122
+ "display_options": {
123
+ "template": "{{image.$thumbnail}} {{name}}"
124
+ },
125
+ "sort": 15,
126
+ "width": "half"
127
+ }
128
+ }
129
+ ```
130
+
131
+ ### O2M Field Example
132
+
133
+ ```json
134
+ {
135
+ "collection": "posts",
136
+ "field": "comments",
137
+ "type": "alias",
138
+ "schema": null,
139
+ "meta": {
140
+ "collection": "posts",
141
+ "field": "comments",
142
+ "special": ["o2m"],
143
+ "interface": "list-o2m",
144
+ "options": {
145
+ "template": "{{author}} - {{content}} ({{status}})"
146
+ },
147
+ "display": "related-values",
148
+ "display_options": {
149
+ "template": "{{author}} - {{content}} ({{status}})"
150
+ },
151
+ "sort": 10,
152
+ "width": "full",
153
+ "required": false,
154
+ "group": null
155
+ }
156
+ }
157
+ ```
158
+
159
+ ### M2M Field Example
160
+
161
+ ```json
162
+ {
163
+ "collection": "posts",
164
+ "field": "categories",
165
+ "type": "alias",
166
+ "schema": null,
167
+ "meta": {
168
+ "collection": "posts",
169
+ "field": "categories",
170
+ "special": ["m2m"],
171
+ "interface": "list-m2m",
172
+ "options": {
173
+ "template": "{{categories_id.name}} ({{categories_id.slug}})"
174
+ },
175
+ "display": "related-values",
176
+ "display_options": {
177
+ "template": "{{categories_id.name}} ({{categories_id.slug}})"
178
+ },
179
+ "sort": 9,
180
+ "width": "full"
181
+ }
182
+ }
183
+ ```
184
+
185
+ ### M2A Field Example
186
+
187
+ ```json
188
+ {
189
+ "collection": "pages",
190
+ "field": "blocks",
191
+ "type": "alias",
192
+ "schema": null,
193
+ "meta": {
194
+ "collection": "pages",
195
+ "field": "blocks",
196
+ "special": ["m2a"],
197
+ "interface": "list-m2a",
198
+ "options": {},
199
+ "display": "related-values",
200
+ "display_options": {
201
+ "template": "{{collection}}"
202
+ },
203
+ "sort": 8,
204
+ "width": "full"
205
+ }
206
+ }
207
+ ```
208
+
209
+ ### File Field Example
210
+
211
+ ```json
212
+ {
213
+ "collection": "posts",
214
+ "field": "featured_image",
215
+ "type": "uuid",
216
+ "schema": {
217
+ "name": "featured_image",
218
+ "table": "posts",
219
+ "data_type": "uuid",
220
+ "is_nullable": true,
221
+ "foreign_key_schema": "public",
222
+ "foreign_key_table": "directus_files",
223
+ "foreign_key_column": "id"
224
+ },
225
+ "meta": {
226
+ "collection": "posts",
227
+ "field": "featured_image",
228
+ "special": ["file"],
229
+ "interface": "file-image",
230
+ "options": {
231
+ "folder": "post-images"
232
+ },
233
+ "display": "image",
234
+ "display_options": null,
235
+ "sort": 1,
236
+ "width": "half",
237
+ "required": false,
238
+ "group": "media"
239
+ }
240
+ }
241
+ ```
242
+
243
+ ### Files Field Example
244
+
245
+ ```json
246
+ {
247
+ "collection": "posts",
248
+ "field": "gallery",
249
+ "type": "alias",
250
+ "schema": null,
251
+ "meta": {
252
+ "collection": "posts",
253
+ "field": "gallery",
254
+ "special": ["files"],
255
+ "interface": "files",
256
+ "options": null,
257
+ "display": "related-values",
258
+ "display_options": null,
259
+ "sort": 4,
260
+ "width": "full"
261
+ }
262
+ }
263
+ ```
264
+
265
+ ### Translations Field Example
266
+
267
+ ```json
268
+ {
269
+ "collection": "posts",
270
+ "field": "translations",
271
+ "type": "alias",
272
+ "schema": null,
273
+ "meta": {
274
+ "collection": "posts",
275
+ "field": "translations",
276
+ "special": ["translations"],
277
+ "interface": "translations",
278
+ "options": {
279
+ "userLanguage": true,
280
+ "defaultOpenSplitView": true
281
+ },
282
+ "display": "translations",
283
+ "display_options": {
284
+ "template": "{{title}}", // Field to display from the translated collection (ie post title)
285
+ "languageField": "name" // Name of the language field from the languages collection
286
+ },
287
+ "sort": 22,
288
+ "width": "full"
289
+ }
290
+ }
291
+ ```
292
+
293
+ **Note**: Alias fields don't need a schema object since they're virtual. </relationship_fields>
294
+
295
+ <primary_keys> **🎯 ALWAYS use UUID as primary keys for new collections unless integers or manually entered strings ares
296
+ specifically requested by the user.**
297
+
298
+ **UUID Primary Key Template:**
299
+
300
+ ```json
301
+ {
302
+ "field": "id",
303
+ "type": "uuid",
304
+ "meta": { "hidden": true, "readonly": true, "interface": "input", "special": ["uuid"] },
305
+ "schema": { "is_primary_key": true, "length": 36, "has_auto_increment": false }
306
+ }
307
+ ```
308
+
309
+ </primary_keys>
310
+
311
+ <interfaces>
312
+ ## Common Interfaces
313
+
314
+ **Text**: `input`, `input-multiline`, `input-rich-text-md`, `input-rich-text-html`, `input-hash`, `translations`
315
+ **Selection**: `select-dropdown`, `select-multiple-dropdown`, `select-radio`, `select-multiple-checkbox`, `tags`,
316
+ `boolean`, `slider` **Date/Time**: `datetime`, `date`, `time` **Relational**: `select-dropdown-m2o`, `list-o2m`,
317
+ `list-m2m`, `list-m2a` **Files**: `file`, `files`, `file-image` **Advanced**: `input-code`, `map`, `group-raw`,
318
+ `group-detail` </interfaces>
319
+
320
+ <field_configuration>
321
+
322
+ ### Layout
323
+
324
+ - **width**: `"half"` (380px max), `"full"` (760px max, default), `"fill"` (no limit)
325
+ - **sort**: Field order in forms
326
+ - **group**: Group related fields into collapsible sections (must be used with `alias` group fields)
327
+
328
+ ### Schema Properties
329
+
330
+ - **default_value**: Default for new items
331
+ - **is_nullable**: Can be null
332
+ - **is_unique**: Must be unique
333
+ - **length**: Max length for strings
334
+
335
+ ### Meta Properties
336
+
337
+ - **required**: Must have value
338
+ - **readonly**: Cannot edit after creation
339
+ - **hidden**: Hidden from UI (still in API)
340
+ - **validation**: Custom validation rules
341
+ - **validation_message**: Custom error messages
342
+ - **note**: Context for non-obvious fields
343
+
344
+ ### Conditions
345
+
346
+ Dynamically control field behavior based on other field values:
347
+
348
+ ```json
349
+ {
350
+ "conditions": [
351
+ {
352
+ "name": "Hide If Author Is Null",
353
+ "rule": {
354
+ "_and": [
355
+ {
356
+ "author": {
357
+ "_null": true
358
+ }
359
+ }
360
+ ]
361
+ },
362
+ "hidden": true
363
+ },
364
+ {
365
+ "name": "Required If Published",
366
+ "rule": {
367
+ "status": {
368
+ "_eq": "published"
369
+ }
370
+ },
371
+ "required": true
372
+ }
373
+ ]
374
+ }
375
+ ```
376
+
377
+ **Condition Properties**:
378
+
379
+ - `name`: Description of the condition
380
+ - `rule`: Filter rules using Directus filter syntax
381
+ - Can set: `hidden`, `readonly`, `required`, or interface-specific options
382
+
383
+ **Common Rules**:
384
+
385
+ - `_null`: Check if field is null
386
+ - `_eq`: Equals specific value
387
+ - `_neq`: Not equals
388
+ - `_in`: Value in array
389
+ - `_and`/`_or`: Combine multiple conditions
390
+
391
+ ### Special Fields
392
+
393
+ - `special: ["uuid"]`: Auto-generate UUID
394
+ - `special: ["user-created"]`: Track creating user
395
+ - `special: ["date-created"]`: Track creation time
396
+ - `special: ["user-updated"]`: Track last editor
397
+ - `special: ["date-updated"]`: Track last edit time
398
+ - `special: ["cast-json"]`: Cast JSON strings to objects </field_configuration>
399
+
400
+ <translations>
401
+ Field names can (and should be) translated for editors using the app.
402
+ Check for `languages` collection first, then add field translations based on which languages are stored in DB. IF not 99% sure, confirm with user first.
403
+
404
+ ```json
405
+ "translations": [
406
+ {"language": "en-US", "translation": "Title"},
407
+ {"language": "es-ES", "translation": "Título"}
408
+ ]
409
+ ```
410
+
411
+ </translations>
412
+
413
+ <display_templates> Display templates can be customized used to enhance the UX for editors.
414
+
415
+ ```json
416
+ "display": "related-values",
417
+ "display_options": {
418
+ "template": "{{first_name}} {{last_name}}"
419
+ }
420
+ ```
421
+
422
+ **Display types**: `raw`, `formatted-value`, `labels`, `datetime`, `user`, `file`, `related-values` </display_templates>
423
+
424
+ <complete_example>
425
+
426
+ #### Complete Field Example with Advanced Features
427
+
428
+ This shows a real field configuration with validation, conditions, and all metadata (as returned from a read operation):
429
+
430
+ ```json
431
+ {
432
+ "collection": "block_button",
433
+ "field": "url",
434
+ "type": "string",
435
+ "schema": {
436
+ "name": "url",
437
+ "table": "block_button",
438
+ "data_type": "character varying", // Database-specific type
439
+ "default_value": null,
440
+ "generation_expression": null,
441
+ "max_length": 255, // String length limit
442
+ "numeric_precision": null,
443
+ "numeric_scale": null,
444
+ "is_generated": false,
445
+ "is_nullable": true,
446
+ "is_unique": false,
447
+ "is_indexed": false,
448
+ "is_primary_key": false,
449
+ "has_auto_increment": false,
450
+ "foreign_key_schema": null, // Would contain relation info for M2O fields
451
+ "foreign_key_table": null,
452
+ "foreign_key_column": null,
453
+ "comment": null
454
+ },
455
+ "meta": {
456
+ "id": 811, // Auto-generated field ID (not used in create)
457
+ "collection": "block_button",
458
+ "field": "url",
459
+ "special": null, // No special behavior for this field
460
+ "interface": "input",
461
+ "options": {
462
+ "iconLeft": "link", // Icon displayed in the input
463
+ "trim": true // Remove whitespace on save
464
+ },
465
+ "display": "formatted-value",
466
+ "display_options": {
467
+ "format": true // Apply auto formatting based on field type
468
+ },
469
+ "readonly": false,
470
+ "hidden": true, // Hidden by default, shown conditionally
471
+ "sort": 11, // Field order in forms
472
+ "width": "half",
473
+ "translations": null, // No field name translations
474
+ "note": "The URL to link to. Could be relative (ie `/my-page`) or a full external URL (ie `https://docs.directus.io`)",
475
+ "conditions": [
476
+ {
477
+ "hidden": false, // Show field when condition is met
478
+ "name": "If type = external",
479
+ "options": {
480
+ "clear": false,
481
+ "font": "sans-serif",
482
+ "masked": false,
483
+ "slug": false,
484
+ "trim": false
485
+ },
486
+ "rule": {
487
+ "_and": [
488
+ {
489
+ "type": {
490
+ // Show when 'type' field equals 'url'
491
+ "_eq": "url"
492
+ }
493
+ }
494
+ ]
495
+ }
496
+ }
497
+ ],
498
+ "required": false,
499
+ "group": null,
500
+ "validation": {
501
+ "_and": [
502
+ {
503
+ "url": {
504
+ "_regex": "^(?:\\/[A-Za-z0-9\\-._~%!$&'()*+,;=:@\\/]*|https?:\\/\\/[^\\s/$.?#].[^\\s]*)$"
505
+ }
506
+ }
507
+ ]
508
+ }, // Regex validation for URLs (relative or absolute)
509
+ "validation_message": "Invalid URL. Check your URL and try again. Properly formatted relative URLs (`/pages/test` ) and absolute URLs (`https://example.com`) are supported."
510
+ }
511
+ }
512
+ ```
513
+
514
+ </complete_example>
515
+
516
+ <related_tools>
517
+
518
+ ## Related Tools
519
+
520
+ - `collections`: Create containers for fields
521
+ - `relations`: Connect fields between collections </related_tools>
@@ -0,0 +1,180 @@
1
+ Perform CRUD operations on files in Directus.
2
+
3
+ ## Actions
4
+
5
+ - **`read`**: List/query metadata or get specific items by ID
6
+ - **`update`**: Modify existing metadata
7
+ - **`delete`**: Remove files by keys
8
+ - **`import`**: Import a file from a URL and create or update its file data
9
+
10
+ ## Example Operations
11
+
12
+ ### Reading File Metadata
13
+
14
+ ```json
15
+ {
16
+ "action": "read",
17
+ "query": {
18
+ "fields": ["id", "title", "type", "filesize", "width", "height"],
19
+ "filter": { "type": { "_starts_with": "image/" } },
20
+ "limit": 10
21
+ }
22
+ }
23
+ ```
24
+
25
+ ### Get Single File Metadata
26
+
27
+ ```json
28
+ {
29
+ "action": "read",
30
+ "keys": ["file-uuid-here"]
31
+ }
32
+ ```
33
+
34
+ ### Import a File via URL
35
+
36
+ ```json
37
+ {
38
+ "action": "import",
39
+ "data": [
40
+ {
41
+ "url": "file-url",
42
+ "file": {
43
+ "title": "New Title",
44
+ "description": "Updated description",
45
+ "tags": ["tag1", "tag2", "category"],
46
+ "folder": "folder-uuid"
47
+ }
48
+ }
49
+ ]
50
+ }
51
+ ```
52
+
53
+ ### Update File Metadata
54
+
55
+ **Single file:**
56
+
57
+ ```json
58
+ {
59
+ "action": "update",
60
+ "keys": ["file-uuid"],
61
+ "data": {
62
+ "title": "New Title",
63
+ "description": "Updated description",
64
+ "tags": ["tag1", "tag2", "category"],
65
+ "folder": "folder-uuid"
66
+ }
67
+ }
68
+ ```
69
+
70
+ **Batch update:**
71
+
72
+ ```json
73
+ {
74
+ "action": "update",
75
+ "data": [
76
+ { "id": "file-uuid-1", "title": "New Title 1" },
77
+ { "id": "file-uuid-2", "title": "New Title 2" }
78
+ ]
79
+ }
80
+ ```
81
+
82
+ ### Common Filters
83
+
84
+ ```json
85
+ {
86
+ "query": {
87
+ "filter": {
88
+ "_and": [
89
+ { "type": { "_icontains": "/png" } }, // PNG files only
90
+ { "folder": { "_eq": "folder-uuid" } }, // Specific folder
91
+ { "filesize": { "_lt": 5000000 } }, // Under 5MB
92
+ { "uploaded_on": { "_gte": "$NOW(-7 days)" } } // Within last week
93
+ ]
94
+ }
95
+ }
96
+ }
97
+ ```
98
+
99
+ ## File Metadata Fields
100
+
101
+ - `id`: Unique identifier
102
+ - `storage`: Storage adapter used
103
+ - `filename_disk`: Actual filename on disk
104
+ - `filename_download`: Suggested download filename
105
+ - `title`: Display title
106
+ - `type`: MIME type (e.g., "image/jpeg", "application/pdf")
107
+ - `folder`: Parent folder ID
108
+ - `uploaded_by`: User who uploaded
109
+ - `uploaded_on`: Upload timestamp
110
+ - `modified_by`: Last modifier
111
+ - `modified_on`: Last modification time
112
+ - `filesize`: Size in bytes
113
+ - `width`/`height`: Dimensions for images (in pixels)
114
+ - `duration`: Length for video/audio
115
+ - `description`: File description
116
+ - `location`: Geo-location data
117
+ - `tags`: Array of tag strings (e.g., ["product", "red", "handbag"])
118
+ - `metadata`: Additional metadata object
119
+ - `focal_point_x`: Horizontal focal point (in pixels from left edge)
120
+ - `focal_point_y`: Vertical focal point (in pixels from top edge)
121
+
122
+ ## Real-World Use Cases
123
+
124
+ ### Asset Selection for Content
125
+
126
+ Find appropriate images for articles, pages, or products:
127
+
128
+ _Example: "Find images in our asset library related to customer support for our new help center article."_
129
+
130
+ ```json
131
+ {
132
+ "action": "read",
133
+ "query": {
134
+ "fields": ["id", "title", "description", "tags", "type"],
135
+ "search": "help center"
136
+ }
137
+ }
138
+ ```
139
+
140
+ ### Asset Organization & Cleanup
141
+
142
+ Transform generic files into well-organized, searchable assets:
143
+
144
+ 1. **Find files needing metadata:**
145
+
146
+ ```json
147
+ {
148
+ "action": "read",
149
+ "query": {
150
+ "fields": ["id", "filename_disk", "title", "description"],
151
+ "filter": { "description": { "_null": true } }
152
+ }
153
+ }
154
+ ```
155
+
156
+ 2. **Analyze with vision (use `assets` tool for base64):** Get image content for AI analysis
157
+
158
+ 3. **Update with descriptive metadata:**
159
+
160
+ ```json
161
+ {
162
+ "action": "update",
163
+ "keys": ["image-uuid"],
164
+ "data": {
165
+ "title": "Red leather handbag product photo",
166
+ "description": "Professional e-commerce photo with white background",
167
+ "tags": ["handbag", "leather", "red", "product-photo", "accessories"],
168
+ "focal_point_x": 512,
169
+ "focal_point_y": 300 // Focal points ensure that when images are cropped for different aspect ratios (thumbnails, hero images, etc.), the important subject remains visible. Coordinates are in pixels from the top-left corner of the original image.
170
+ }
171
+ }
172
+ ```
173
+
174
+ ## Key Points
175
+
176
+ - **ALWAYS pass data as native objects**, NOT stringified JSON
177
+ - **Metadata only**: This tool manages file metadata, not file content or uploads
178
+ - **Permissions**: Respects Directus access control
179
+ - **Arrays required**: `keys` and `tags` must be arrays: `["item"]` not `"item"`
180
+ - **Performance**: Large files handled automatically but may impact performance