@xano/developer-mcp 1.0.26 → 1.0.28

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.
@@ -8,17 +8,17 @@ Complete reference for XanoScript database operations.
8
8
 
9
9
  ## Quick Reference
10
10
 
11
- | Operation | Purpose | Returns |
12
- |-----------|---------|---------|
13
- | `db.query` | Query multiple records | List/single/count/exists |
14
- | `db.get` | Get single record by field | Record or null |
15
- | `db.has` | Check if record exists | Boolean |
16
- | `db.add` | Insert new record | Created record |
17
- | `db.edit` | Update record (inline data) | Updated record |
18
- | `db.patch` | Update record (variable data) | Updated record |
19
- | `db.add_or_edit` | Upsert record | Record |
20
- | `db.del` | Delete record | None |
21
- | `db.truncate` | Delete all records | None |
11
+ | Operation | Purpose | Returns |
12
+ | ---------------- | ----------------------------- | ------------------------ |
13
+ | `db.query` | Query multiple records | List/single/count/exists |
14
+ | `db.get` | Get single record by field | Record or null |
15
+ | `db.has` | Check if record exists | Boolean |
16
+ | `db.add` | Insert new record | Created record |
17
+ | `db.edit` | Update record (inline data) | Updated record |
18
+ | `db.patch` | Update record (variable data) | Updated record |
19
+ | `db.add_or_edit` | Upsert record | Record |
20
+ | `db.del` | Delete record | None |
21
+ | `db.truncate` | Delete all records | None |
22
22
 
23
23
  ---
24
24
 
@@ -27,6 +27,7 @@ Complete reference for XanoScript database operations.
27
27
  Query multiple records with filters, sorting, and pagination.
28
28
 
29
29
  ### Basic Query
30
+
30
31
  ```xs
31
32
  db.query "product" {
32
33
  where = $db.product.is_active == true
@@ -34,6 +35,7 @@ db.query "product" {
34
35
  ```
35
36
 
36
37
  ### Where Operators
38
+
37
39
  ```xs
38
40
  // Comparison
39
41
  $db.product.price == 100
@@ -62,13 +64,14 @@ $db.product.category == "electronics" || $db.product.featured == true
62
64
  ```
63
65
 
64
66
  ### Return Types
67
+
65
68
  ```xs
66
- // List (default)
69
+ // returns an array of products (default)
67
70
  db.query "product" {
68
71
  return = { type: "list" }
69
72
  } as $products
70
73
 
71
- // With pagination
74
+ // Returns a paginated list of products
72
75
  db.query "product" {
73
76
  return = {
74
77
  type: "list",
@@ -76,19 +79,19 @@ db.query "product" {
76
79
  }
77
80
  } as $products
78
81
 
79
- // Single record
82
+ // Returns a single record
80
83
  db.query "product" {
81
84
  where = $db.product.sku == $input.sku
82
85
  return = { type: "single" }
83
86
  } as $product
84
87
 
85
- // Count
88
+ // Returns a count (number)
86
89
  db.query "product" {
87
90
  where = $db.product.is_active == true
88
91
  return = { type: "count" }
89
92
  } as $count
90
93
 
91
- // Exists
94
+ // Returns a boolean indicating existence
92
95
  db.query "product" {
93
96
  where = $db.product.email == $input.email
94
97
  return = { type: "exists" }
@@ -96,6 +99,7 @@ db.query "product" {
96
99
  ```
97
100
 
98
101
  ### Sorting
102
+
99
103
  ```xs
100
104
  db.query "product" {
101
105
  sort = { created_at: "desc" } // Descending
@@ -105,6 +109,7 @@ db.query "product" {
105
109
  ```
106
110
 
107
111
  ### Joins
112
+
108
113
  ```xs
109
114
  db.query "comment" {
110
115
  join = {
@@ -114,11 +119,15 @@ db.query "comment" {
114
119
  where: $db.comment.post_id == $db.post.id
115
120
  }
116
121
  }
122
+ eval = {
123
+ post_title: $db.post.title
124
+ }
117
125
  where = $db.post.author_id == $auth.id
118
126
  } as $comments
119
127
  ```
120
128
 
121
129
  ### Eval (Computed Fields)
130
+
122
131
  ```xs
123
132
  db.query "order" {
124
133
  join = {
@@ -132,6 +141,7 @@ db.query "order" {
132
141
  ```
133
142
 
134
143
  ### Addons (Related Data)
144
+
135
145
  ```xs
136
146
  db.query "post" {
137
147
  where = $db.post.author_id == $auth.id
@@ -141,6 +151,30 @@ db.query "post" {
141
151
  } as $posts
142
152
  ```
143
153
 
154
+ ### Vector Search (Similarity)
155
+
156
+ Search by vector similarity using embeddings. Requires a `vector` column with a `vector` index on the table (see [tables.md](tables.md)).
157
+
158
+ ```xs
159
+ // Embeddings from an LLM engine
160
+ var $embeddings {
161
+ value = [0.345, 0.1553, ...]
162
+ }
163
+
164
+ db.query agent_message {
165
+ sort = {distance: "asc"}
166
+ eval = {
167
+ distance: $db.agent_message.embeddings|cosine_distance:$embeddings
168
+ }
169
+ return = {
170
+ type : "list"
171
+ paging: {page: 1, per_page: 5, metadata: false}
172
+ }
173
+ } as $search_results
174
+ ```
175
+
176
+ The `cosine_distance` filter computes the distance between the row's vector and the provided embeddings. Sort by `distance` ascending (smallest distance = most similar) — this ordering is required to leverage the PostgreSQL vector index.
177
+
144
178
  ---
145
179
 
146
180
  ## db.get
@@ -338,6 +372,7 @@ db.transaction {
338
372
  Filters for use in `where` clauses:
339
373
 
340
374
  ### String/Text
375
+
341
376
  ```xs
342
377
  $db.name|to_lower // Case conversion
343
378
  $db.name|concat:" " // Concatenation
@@ -345,6 +380,7 @@ $db.text|substr:0:100 // Substring
345
380
  ```
346
381
 
347
382
  ### Numeric
383
+
348
384
  ```xs
349
385
  $db.price|round:2
350
386
  $db.price|floor
@@ -354,6 +390,7 @@ $db.price|mul:1.1
354
390
  ```
355
391
 
356
392
  ### Timestamp
393
+
357
394
  ```xs
358
395
  $db.created_at|timestamp_year
359
396
  $db.created_at|timestamp_month
@@ -362,18 +399,21 @@ $db.created_at|timestamp_subtract_hours:24
362
399
  ```
363
400
 
364
401
  ### Geographic
402
+
365
403
  ```xs
366
404
  $db.location|distance:$input.point // Distance in meters
367
405
  $db.location|within:$input.point:1000 // Within radius
368
406
  ```
369
407
 
370
408
  ### Vector (AI/ML)
409
+
371
410
  ```xs
372
- $db.embedding|cosine_similarity:$input.vector
411
+ $db.embedding|cosine_distance:$input.vector
373
412
  $db.embedding|l2_distance_euclidean:$input.vector
374
413
  ```
375
414
 
376
415
  ### Full-Text Search
416
+
377
417
  ```xs
378
418
  $db.content|search_rank:$input.query
379
419
  ```
@@ -19,7 +19,9 @@ function "<name>" {
19
19
  }
20
20
  response = $result
21
21
  }
22
+ ```
22
23
 
24
+ ```xs
23
25
  // Function with no inputs - IMPORTANT: braces must be on separate lines
24
26
  function "<name>" {
25
27
  description = "..."
@@ -31,6 +33,7 @@ function "<name>" {
31
33
  ```
32
34
 
33
35
  ### Calling Functions
36
+
34
37
  ```xs
35
38
  function.run "<name>" {
36
39
  input = { key: value }
@@ -55,7 +58,9 @@ function "calculate_total" {
55
58
  ```
56
59
 
57
60
  ### With Subfolders
61
+
58
62
  Functions can be organized in subfolders:
63
+
59
64
  ```
60
65
  functions/
61
66
  ├── math/
@@ -82,33 +87,6 @@ input {
82
87
  }
83
88
  ```
84
89
 
85
- ### Empty Input Blocks
86
-
87
- **CRITICAL:** When a function has no input parameters, the input block braces MUST be on separate lines. This is a syntax requirement.
88
-
89
- ```xs
90
- // CORRECT - braces on separate lines
91
- function "get_all_users" {
92
- description = "Returns all users"
93
- input {
94
- }
95
- stack {
96
- db.query "user" {} as $users
97
- }
98
- response = $users
99
- }
100
-
101
- // WRONG - will cause parsing errors
102
- function "get_all_users" {
103
- description = "Returns all users"
104
- input {} // <-- ERROR: braces must be on separate lines
105
- stack {
106
- db.query "user" {} as $users
107
- }
108
- response = $users
109
- }
110
- ```
111
-
112
90
  ---
113
91
 
114
92
  ## Stack Block
@@ -116,6 +94,7 @@ function "get_all_users" {
116
94
  Contains the function logic using control flow, variables, and operations.
117
95
 
118
96
  ### Variables
97
+
119
98
  ```xs
120
99
  stack {
121
100
  var $counter { value = 0 }
@@ -127,6 +106,7 @@ stack {
127
106
  ```
128
107
 
129
108
  ### Conditionals
109
+
130
110
  ```xs
131
111
  stack {
132
112
  conditional {
@@ -144,6 +124,7 @@ stack {
144
124
  ```
145
125
 
146
126
  ### Loops
127
+
147
128
  ```xs
148
129
  stack {
149
130
  // For loop (count-based)
@@ -170,6 +151,7 @@ stack {
170
151
  ```
171
152
 
172
153
  ### Switch
154
+
173
155
  ```xs
174
156
  stack {
175
157
  switch ($input.status) {
@@ -208,6 +190,7 @@ response = null // No return value
208
190
  ## Calling Functions
209
191
 
210
192
  ### Basic Call
193
+
211
194
  ```xs
212
195
  function.run "calculate_total" {
213
196
  input = { quantity: 5, price: 10.50 }
@@ -215,6 +198,7 @@ function.run "calculate_total" {
215
198
  ```
216
199
 
217
200
  ### With Variables
201
+
218
202
  ```xs
219
203
  function.run "process_order" {
220
204
  input = {
@@ -226,6 +210,7 @@ function.run "process_order" {
226
210
  ```
227
211
 
228
212
  ### Nested Calls
213
+
229
214
  ```xs
230
215
  stack {
231
216
  function.run "validate_user" {
@@ -245,6 +230,7 @@ stack {
245
230
  ## Complete Examples
246
231
 
247
232
  ### Utility Function
233
+
248
234
  ```xs
249
235
  function "utils/format_currency" {
250
236
  description = "Format number as currency string"
@@ -265,6 +251,7 @@ function "utils/format_currency" {
265
251
  ```
266
252
 
267
253
  ### Data Processing
254
+
268
255
  ```xs
269
256
  function "process_order" {
270
257
  input {
@@ -305,6 +292,7 @@ function "process_order" {
305
292
  ```
306
293
 
307
294
  ### Validation Function
295
+
308
296
  ```xs
309
297
  function "validate_email_unique" {
310
298
  input {
@@ -346,65 +334,28 @@ stack {
346
334
  }
347
335
  ```
348
336
 
349
- ### group (Parallel Execution)
337
+ ### group (Organizational Block)
350
338
 
351
- Execute multiple operations in parallel and wait for all to complete.
339
+ Group related statements together for readability. The `group` block is purely organizational — it does **not** create parallel execution or a new scope.
352
340
 
353
341
  ```xs
354
342
  stack {
343
+ // Use group to visually organize related initialization
355
344
  group {
356
- api.request {
357
- url = "https://api.example.com/users"
358
- method = "GET"
359
- } as $users
360
-
361
- api.request {
362
- url = "https://api.example.com/products"
363
- method = "GET"
364
- } as $products
365
-
366
- api.request {
367
- url = "https://api.example.com/orders"
368
- method = "GET"
369
- } as $orders
370
- }
345
+ stack {
346
+ var $total {
347
+ value = 0
348
+ }
371
349
 
372
- // All three requests complete before continuing
373
- var $combined {
374
- value = {
375
- users: $users.response.result,
376
- products: $products.response.result,
377
- orders: $orders.response.result
350
+ var $count {
351
+ value = 0
352
+ }
378
353
  }
379
354
  }
380
- }
381
- ```
382
-
383
- ### Parallel Database Queries
384
-
385
- ```xs
386
- stack {
387
- group {
388
- db.query "user" {
389
- where = $db.user.is_active == true
390
- return = { type: "count" }
391
- } as $active_users
392
-
393
- db.query "order" {
394
- where = $db.order.created_at >= $input.start_date
395
- return = { type: "count" }
396
- } as $order_count
397
-
398
- db.query "product" {
399
- where = $db.product.stock == 0
400
- return = { type: "count" }
401
- } as $out_of_stock
402
- }
403
355
 
404
- response = {
405
- active_users: $active_users,
406
- orders: $order_count,
407
- out_of_stock: $out_of_stock
356
+ // Variables from the group are accessible here
357
+ var $average {
358
+ value = $total / $count
408
359
  }
409
360
  }
410
361
  ```
@@ -512,5 +463,5 @@ foreach ($items) {
512
463
  3. **Organize in folders** - Group related functions: `utils/`, `auth/`, `orders/`
513
464
  4. **Return early** - Use return for guard clauses
514
465
  5. **Keep stacks shallow** - Avoid deeply nested conditionals
515
- 6. **Use group for parallel calls** - Improves performance for independent operations
466
+ 6. **Use group for organization** - Visually group related statements for readability
516
467
  7. **Use remove sparingly** - Consider filtering arrays instead
@@ -506,16 +506,6 @@ security.check_password {
506
506
  } as $is_valid
507
507
  ```
508
508
 
509
- ### Auth Tokens
510
- ```xs
511
- security.create_auth_token {
512
- table = "user"
513
- id = $user.id
514
- extras = { role: $user.role }
515
- expiration = 86400
516
- } as $token
517
- ```
518
-
519
509
  ### Encryption
520
510
  ```xs
521
511
  # Encrypt
@@ -12,7 +12,7 @@ Best practices for building fast, efficient XanoScript applications.
12
12
  |------|----------------|
13
13
  | Database | Indexes, query optimization, pagination |
14
14
  | Caching | Redis, response caching |
15
- | Loops | Bulk operations, parallel execution |
15
+ | Loops | Bulk operations, efficient iteration |
16
16
  | Filters | Efficient data transformations |
17
17
 
18
18
  ---
@@ -212,34 +212,25 @@ conditional {
212
212
 
213
213
  ---
214
214
 
215
- ## Parallel Execution
215
+ ## Organizing with Group
216
216
 
217
- ### Use Group for Independent Operations
217
+ The `group` statement is an organizational block for visually grouping related statements. It does **not** create parallel execution or a new scope — variables declared inside a group are accessible outside it.
218
218
 
219
219
  ```xs
220
- // Execute in parallel
220
+ // Use group to organize related variable initialization
221
221
  group {
222
- db.query "user" { return = { type: "count" } } as $user_count
223
- db.query "order" { return = { type: "count" } } as $order_count
224
- db.query "product" { return = { type: "count" } } as $product_count
225
- }
222
+ stack {
223
+ var $total {
224
+ value = 0
225
+ }
226
226
 
227
- // All counts available after group completes
228
- response = {
229
- users: $user_count,
230
- orders: $order_count,
231
- products: $product_count
227
+ var $count {
228
+ value = 0
229
+ }
230
+ }
232
231
  }
233
- ```
234
-
235
- ### Parallel API Calls
236
232
 
237
- ```xs
238
- group {
239
- api.request { url = "https://api1.example.com/data" } as $data1
240
- api.request { url = "https://api2.example.com/data" } as $data2
241
- api.request { url = "https://api3.example.com/data" } as $data3
242
- }
233
+ // $total and $count are accessible here
243
234
  ```
244
235
 
245
236
  ---
@@ -285,16 +276,7 @@ api.request {
285
276
 
286
277
  ## Rate Limiting
287
278
 
288
- ### Protect Endpoints
289
-
290
- ```xs
291
- redis.ratelimit {
292
- key = "api:" ~ $auth.id
293
- max = 100
294
- ttl = 60
295
- error = "Rate limit exceeded. Try again in 1 minute."
296
- }
297
- ```
279
+ For basic rate limiting setup, see `xanoscript_docs({ topic: "security" })`. Below are performance-focused patterns.
298
280
 
299
281
  ### Tiered Limits
300
282
 
@@ -401,7 +383,7 @@ conditional {
401
383
  4. **Avoid N+1 queries** - Use joins or batch fetching
402
384
  5. **Use bulk operations** - For batch inserts/updates
403
385
  6. **Cache expensive operations** - Redis with appropriate TTL
404
- 7. **Execute in parallel** - Group independent operations
386
+ 7. **Use group for organization** - Group related statements for readability
405
387
  8. **Filter early** - In database, not application code
406
388
  9. **Stream large responses** - Don't load into memory
407
389
  10. **Monitor performance** - Log slow operations
@@ -261,54 +261,7 @@ api.realtime_event {
261
261
 
262
262
  ## Realtime Triggers
263
263
 
264
- Handle events from connected clients.
265
-
266
- ### Basic Realtime Trigger
267
-
268
- ```xs
269
- realtime_trigger "on_presence" {
270
- channel = "room:*"
271
- event = "join"
272
- stack {
273
- // $input contains event data
274
- // $channel contains matched channel
275
- db.add "presence" {
276
- data = {
277
- user_id: $auth.id,
278
- room_id: $input.room_id,
279
- joined_at: now
280
- }
281
- }
282
-
283
- // Notify room members
284
- api.realtime_event {
285
- channel = $channel
286
- event = "user_joined"
287
- data = { user_id: $auth.id }
288
- }
289
- }
290
- }
291
- ```
292
-
293
- ### Channel Pattern Matching
294
-
295
- ```xs
296
- realtime_trigger "document_cursor" {
297
- channel = "document:*" // Wildcard match
298
- event = "cursor_move"
299
- stack {
300
- // Broadcast cursor position to other viewers
301
- api.realtime_event {
302
- channel = $channel
303
- event = "cursor_update"
304
- data = {
305
- user_id: $auth.id,
306
- position: $input.position
307
- }
308
- }
309
- }
310
- }
311
- ```
264
+ Handle events from connected clients using `realtime_trigger`. For complete trigger syntax, input schemas, and configuration options, see `xanoscript_docs({ topic: "triggers" })`.
312
265
 
313
266
  ---
314
267
 
@@ -33,6 +33,8 @@ security.create_auth_token {
33
33
  } as $token
34
34
  ```
35
35
 
36
+ **Note:** The `extras` parameter is required even if you don't need to store additional claims (`extras = { }`).
37
+
36
38
  ### Token Verification
37
39
 
38
40
  ```xs