@xano/developer-mcp 1.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 (46) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +261 -0
  3. package/api_docs/addon.md +193 -0
  4. package/api_docs/agent.md +154 -0
  5. package/api_docs/api_group.md +236 -0
  6. package/api_docs/authentication.md +68 -0
  7. package/api_docs/file.md +190 -0
  8. package/api_docs/function.md +217 -0
  9. package/api_docs/history.md +263 -0
  10. package/api_docs/index.md +104 -0
  11. package/api_docs/mcp_server.md +139 -0
  12. package/api_docs/middleware.md +205 -0
  13. package/api_docs/realtime.md +153 -0
  14. package/api_docs/table.md +151 -0
  15. package/api_docs/task.md +191 -0
  16. package/api_docs/tool.md +216 -0
  17. package/api_docs/triggers.md +344 -0
  18. package/api_docs/workspace.md +246 -0
  19. package/dist/index.d.ts +2 -0
  20. package/dist/index.js +495 -0
  21. package/package.json +49 -0
  22. package/xanoscript_docs/README.md +1 -0
  23. package/xanoscript_docs/api_query_examples.md +1255 -0
  24. package/xanoscript_docs/api_query_guideline.md +129 -0
  25. package/xanoscript_docs/build_from_lovable.md +715 -0
  26. package/xanoscript_docs/db_query_guideline.md +427 -0
  27. package/xanoscript_docs/ephemeral_environment_guideline.md +529 -0
  28. package/xanoscript_docs/expression_guideline.md +1086 -0
  29. package/xanoscript_docs/frontend_guideline.md +67 -0
  30. package/xanoscript_docs/function_examples.md +1406 -0
  31. package/xanoscript_docs/function_guideline.md +130 -0
  32. package/xanoscript_docs/functions.md +2155 -0
  33. package/xanoscript_docs/input_guideline.md +227 -0
  34. package/xanoscript_docs/mcp_server_examples.md +36 -0
  35. package/xanoscript_docs/mcp_server_guideline.md +69 -0
  36. package/xanoscript_docs/query_filter.md +489 -0
  37. package/xanoscript_docs/table_examples.md +586 -0
  38. package/xanoscript_docs/table_guideline.md +137 -0
  39. package/xanoscript_docs/task_examples.md +511 -0
  40. package/xanoscript_docs/task_guideline.md +103 -0
  41. package/xanoscript_docs/tips_and_tricks.md +144 -0
  42. package/xanoscript_docs/tool_examples.md +69 -0
  43. package/xanoscript_docs/tool_guideline.md +139 -0
  44. package/xanoscript_docs/unit_testing_guideline.md +328 -0
  45. package/xanoscript_docs/version.json +3 -0
  46. package/xanoscript_docs/workspace.md +17 -0
@@ -0,0 +1,511 @@
1
+ ---
2
+ applyTo: "tasks/*.xs"
3
+ ---
4
+
5
+ # Xanoscript Task Examples
6
+
7
+ Below are some examples of tasks defined in Xanoscript.
8
+
9
+ ## deactivate_user_profile_task
10
+
11
+ ```xs
12
+ task "deactivate_inactive_profiles" {
13
+ description = "Deactivate user profiles for users who have not had session activity in the past 30 days. This task runs monthly."
14
+ stack {
15
+ var $current_time {
16
+ value = now
17
+ description = "Get the current timestamp for comparison"
18
+ }
19
+
20
+ var $threshold_time {
21
+ value = $current_time - (30 * 86400 * 1000)
22
+ description = "Calculate the timestamp for 30 days ago"
23
+ }
24
+
25
+ db.query "sessions" {
26
+ description = "Find users with no session activity in the past 30 days"
27
+ where = $db.sessions.last_activity < $threshold_time
28
+ output = ["id", "user_id", "is_active"]
29
+ } as $inactive_users
30
+
31
+ foreach ($inactive_users) {
32
+ each as $user {
33
+ db.edit "user_profile" {
34
+ field_name = "id"
35
+ field_value = $user.user_id
36
+ data = {is_active: false}
37
+ description = "Deactivate user profile"
38
+ } as $user_profile
39
+
40
+ debug.log {
41
+ value = "Deactivated user profile with ID: " ~ $var.user_profileuser.user_id
42
+ description = "Log individual profile deactivation"
43
+ }
44
+ }
45
+ }
46
+
47
+ debug.log {
48
+ value = "Profile deactivation task completed. Total profiles deactivated: " ~ $inactive_users|count
49
+ description = "Log successful task completion"
50
+ }
51
+ }
52
+
53
+ schedule = [{starts_on: 2025-07-01 00:00:00+0000, freq: 2592000}]
54
+
55
+ history = "inherit"
56
+ }
57
+ ```
58
+
59
+ ## cleanup_expired_sessions_task
60
+
61
+ ```xs
62
+ task "cleanup_expired_sessions" {
63
+ description = "Clean up expired sessions from the sessions table every 6 hours starting Feb 1, 2026. This task deletes expired sessions and logs the number of deletions for monitoring purposes."
64
+ stack {
65
+ var $current_time {
66
+ value = now
67
+ description = "Get the current timestamp for comparison"
68
+ }
69
+
70
+ db.query "sessions" {
71
+ description = "Count expired sessions before deletion"
72
+ where = $db.sessions.expires_at < $current_time && $db.sessions.is_active
73
+ } as $expired_sessions
74
+
75
+ var $expired_count {
76
+ value = $expired_sessions|count
77
+ description = "Count of expired sessions to be deleted"
78
+ }
79
+
80
+ var $total_deletions {
81
+ value = 0
82
+ description = "Track the total number of sessions deleted"
83
+ }
84
+
85
+ debug.log {
86
+ value = "Found " ~ $expired_count ~ " expired sessions for cleanup"
87
+ description = "Log count of sessions found for deletion"
88
+ }
89
+
90
+ foreach ($expired_sessions) {
91
+ each as $session {
92
+ db.del sessions {
93
+ field_name = "id"
94
+ field_value = $session.id
95
+ description = "Delete expired session"
96
+ }
97
+
98
+ math.add $total_deletions {
99
+ value = 1
100
+ description = "Increment deletion counter"
101
+ }
102
+
103
+ debug.log {
104
+ value = "Deleted session with ID: " ~ $session.id
105
+ description = "Log individual session deletion"
106
+ }
107
+ }
108
+ }
109
+
110
+ debug.log {
111
+ value = "Session cleanup completed. Total sessions deleted: " ~ $total_deletions
112
+ description = "Log successful cleanup completion"
113
+ }
114
+ }
115
+
116
+ schedule = [{starts_on: 2026-02-01 00:00:00+0000, freq: 21600}]
117
+
118
+ history = 1000
119
+ }
120
+ ```
121
+
122
+ ## slack_prompts_gif_finder
123
+
124
+ ```xs
125
+ task "slack_prompts_gif_finder" {
126
+ description = "Find and populate GIF URLs for Slack prompts using AI completion"
127
+ stack {
128
+ debug.log {
129
+ value = "Starting GIF URL population task"
130
+ description = "Log task start"
131
+ }
132
+
133
+ db.query "slack_prompts" {
134
+ description = "Retrieve prompts that are missing a GIF URL"
135
+ where = $db.slack_prompts.gif_url == "" && $db.slack_prompts.prompt != ""
136
+ } as $prompts_without_gifs
137
+
138
+ debug.log {
139
+ value = {
140
+ count: ($prompts_without_gifs|count)
141
+ }
142
+
143
+ description = "Log prompts found"
144
+ }
145
+
146
+ conditional {
147
+ description = "Process if prompts exist"
148
+ if (($prompts_without_gifs|count) > 0) {
149
+ var $processed {
150
+ value = 0
151
+ }
152
+
153
+ foreach ($prompts_without_gifs) {
154
+ each as $prompt {
155
+ util.template_engine {
156
+ value = """
157
+ Based on the following Slack message, suggest a single search query of 2-3 words for finding a funny GIF on Giphy. Your response should *ONLY* include the search term. Do not included any other explanation in your response.
158
+
159
+ Message:
160
+ {{$prompt.prompt}}
161
+ """
162
+
163
+ description = "Gemini Prompt"
164
+ } as $ai_request
165
+
166
+ var $search_term {
167
+ value = "cute dog"
168
+ description = "Set the fallback search term"
169
+ }
170
+
171
+ try_catch {
172
+ description = "Get AI suggestion"
173
+ try {
174
+ function.run "ai/Gemini: Simple Chat Completion" {
175
+ description = "Use Gemini to convert the Slack prompt into a search term for Giphy"
176
+ input = {model: "gemini-2.5-flash", message: $ai_request}
177
+ } as $ai_result
178
+
179
+ var.update $search_term {
180
+ value = $ai_result
181
+ }
182
+ }
183
+
184
+ catch {
185
+ debug.log {
186
+ value = "AI request failed, using fallback"
187
+ description = "Log AI failure"
188
+ errorCode = $error.code
189
+ errorMessage = $error.message
190
+ }
191
+ }
192
+ }
193
+
194
+ try_catch {
195
+ description = "Search Giphy"
196
+ try {
197
+ api.request {
198
+ url = "https://api.giphy.com/v1/gifs/search"
199
+ method = "GET"
200
+ params = {
201
+ api_key: $env.giphy_key
202
+ q: $search_term
203
+ limit: 1
204
+ rating: "g"
205
+ }
206
+
207
+ verify_host = false
208
+ verify_peer = false
209
+ description = "Giphy search"
210
+ } as $gif_result
211
+
212
+ var.update $gif_result {
213
+ value = $gif_result.response.result
214
+ }
215
+
216
+ conditional {
217
+ description = "Update if GIF found"
218
+ if (($gif_result.data|count) > 0) {
219
+ var $gif_url {
220
+ value = ($gif_result.data|first).images.original.url
221
+ }
222
+
223
+ db.edit "slack_prompts" {
224
+ field_name = "id"
225
+ field_value = $prompt.id
226
+ data = {gif_url: $gif_url}
227
+ description = "Update the GIF URL and updated_at for the prompt"
228
+ } as $updated_record
229
+
230
+ debug.log {
231
+ value = {
232
+ id: $var.updated_record.id
233
+ gif_url: $var.updated_record.gif_url
234
+ }
235
+
236
+ description = "GIF URL added"
237
+ }
238
+ }
239
+ }
240
+ }
241
+
242
+ catch {
243
+ debug.log {
244
+ value = {
245
+ id: $var.updated_record.id
246
+ error: "Giphy search failed"
247
+ errorCode = $error.code
248
+ errorMessage = $error.message
249
+ }
250
+
251
+ description = "Giphy error"
252
+ }
253
+ }
254
+ }
255
+
256
+ var.update $processed {
257
+ value = $var.processed + 1
258
+ description = "Increment the processed counter"
259
+ }
260
+ }
261
+ }
262
+
263
+ debug.log {
264
+ value = {
265
+ processed: $var.processed
266
+ }
267
+
268
+ description = "Processing complete"
269
+ }
270
+ }
271
+
272
+ else {
273
+ debug.log {
274
+ value = "No prompts need GIFs"
275
+ description = "Nothing to process"
276
+ }
277
+ }
278
+ }
279
+
280
+ debug.log {
281
+ value = "Task completed"
282
+ description = "Task end"
283
+ }
284
+ }
285
+
286
+ schedule = [{starts_on: 2026-01-14 09:00:00+0000, freq: 86400}]
287
+
288
+ history = "inherit"
289
+ }
290
+ ```
291
+
292
+ ## scheduled_end_of_month_task
293
+
294
+ ```xs
295
+ task "end_of_month_task" {
296
+ stack {
297
+ var $timezone {
298
+ value = "UTC"
299
+ description = "Set Timezone"
300
+ }
301
+
302
+ var $now {
303
+ value = now
304
+ }
305
+
306
+ var $today {
307
+ value = $now|format_timestamp:"Y-m-d":$timezone
308
+ description = "Today"
309
+ }
310
+
311
+ var $end_of_month {
312
+ value = $now|transform_timestamp:"last day of this month":$timezone|format_timestamp:"Y-m-d":$timezone
313
+ description = "Last day of this month"
314
+ }
315
+
316
+ conditional {
317
+ description = "If Today is NOT the last day of the month, stop running"
318
+ if ($today != $end_of_month) {
319
+ return {
320
+ value = "Today is not the last day of the month. Stop running."
321
+ }
322
+ }
323
+ }
324
+
325
+ debug.log {
326
+ value = "It's the end of the month... executing task..."
327
+ description = "Beginning of end of month task"
328
+ }
329
+ }
330
+
331
+ schedule = [{starts_on: 2026-05-01 23:00:00+0000, freq: 86400}]
332
+
333
+ history = "all"
334
+ }
335
+ ```
336
+
337
+ ## subscription_renewal_reminder_task
338
+
339
+ ```xs
340
+ task "subscription_renewal_reminder" {
341
+ stack {
342
+ var $current_time {
343
+ value = now
344
+ description = "Current timestamp for calculations"
345
+ }
346
+
347
+ debug.log {
348
+ value = "Starting subscription renewal reminder task"
349
+ description = "Log task start"
350
+ }
351
+
352
+ db.query "subscription" {
353
+ description = "Query subscriptions expiring in next 7 days"
354
+ where = $db.subscription.status == "active" && $db.subscription.end_date > $current_time && $db.subscription.end_date <= ($current_time + 604800000)
355
+ } as $expiring_subscriptions
356
+
357
+ foreach ($expiring_subscriptions) {
358
+ each as $subscription {
359
+ db.query "user" {
360
+ description = "Get user details"
361
+ where = $db.user.id == $subscription.user_id
362
+ } as $user_result
363
+
364
+ conditional {
365
+ description = "Process if user found"
366
+ if (($user_result|count) > 0) {
367
+ var $user {
368
+ value = $user_result|first
369
+ description = "Extract user from result"
370
+ }
371
+
372
+ api.request {
373
+ url = "https://mandrillapp.com/api/1.0/messages/send"
374
+ method = "POST"
375
+ params = {}|set:"key":$env.mandrill_api_key|set:"message":({}|set:"from_email":"noreply@example.com"|set:"subject":"Subscription Reminder"|set:"text":"Your subscription expires soon"|set:"to":([]|push:({}|set:"email":$user.email|set:"type":"to")))
376
+ headers = []|push:"Content-Type: application/json"
377
+ description = "Send email reminder"
378
+ } as $email_response
379
+
380
+ db.add notification_log {
381
+ data = {
382
+ created_at : $current_time
383
+ user_id : $user.id
384
+ notification_type: "subscription_renewal_reminder"
385
+ title : "Subscription Reminder"
386
+ message : "Reminder sent successfully"
387
+ }
388
+
389
+ description = "Log notification"
390
+ } as $log_entry
391
+ }
392
+ }
393
+ }
394
+ }
395
+
396
+ debug.log {
397
+ value = "Task completed"
398
+ description = "Log completion"
399
+ }
400
+ }
401
+
402
+ schedule = [{starts_on: 2026-01-01 09:00:00+0000, freq: 86400}]
403
+
404
+ history = "all"
405
+ }
406
+ ```
407
+
408
+ ## low_stock_alert
409
+
410
+ ```xs
411
+ task "low_stock_alert" {
412
+ stack {
413
+ db.query "product" {
414
+ description = "Fetch products with stock quantity below 10"
415
+ where = $db.product.stock_quantity < 10
416
+ } as $low_stock_products
417
+
418
+ var $alert_count {
419
+ value = 0
420
+ description = "Counter for alerted products"
421
+ }
422
+
423
+ foreach ($low_stock_products) {
424
+ each as $product {
425
+ api.realtime_event {
426
+ channel = "stock_channel"
427
+ data = {product_id: $product.id, stock_quantity: $product.stock_quantity}
428
+ auth_table = "user"
429
+ auth_id = "123"
430
+ description = "Send real-time notification for low stock product"
431
+ }
432
+
433
+ math.add $alert_count {
434
+ value = 1
435
+ description = "Increment alert count"
436
+ }
437
+ }
438
+ }
439
+
440
+ debug.log {
441
+ value = $alert_count
442
+ description = "Log the number of alerted products"
443
+ }
444
+ }
445
+
446
+ schedule = [{starts_on: 2026-01-01 09:00:00+0000, freq: 86400}]
447
+
448
+ history = "inherit"
449
+ }
450
+ ```
451
+
452
+ ## daily_sales_report_task
453
+
454
+ ```xs
455
+ task "daily_sales_report" {
456
+ description = "Daily at 11 PM UTC generate a sales report by querying all payment transactions from the past 24 hours and calculating the total sales amount and transaction count. The task automatically executes every day starting from May 1, 2026, providing a summary of daily sales performance."
457
+ stack {
458
+ var $twenty_four_hours_ago {
459
+ value = (now|transform_timestamp:"24 hours ago":"UTC")
460
+ description = "Calculate timestamp for 24 hours ago"
461
+ }
462
+
463
+ db.query "payment_transactions" {
464
+ description = "Get all transactions from the past 24 hours"
465
+ where = $db.payment_transactions.transaction_date >= $twenty_four_hours_ago
466
+ } as $daily_sales
467
+
468
+ var $transaction_count {
469
+ value = $daily_sales|count
470
+ description = "Count number of transactions"
471
+ }
472
+
473
+ var $total_sales {
474
+ value = ($daily_sales[$$].amount)|sum
475
+ description = "Initialize total sales amount"
476
+ }
477
+
478
+ var $report_date {
479
+ value = now
480
+ description = "Current timestamp for the report"
481
+ }
482
+
483
+ db.transaction {
484
+ description = "Store daily sales report with data consistency"
485
+ stack {
486
+ db.add reports {
487
+ data = {
488
+ report_type : "daily_sales"
489
+ report_date : $report_date
490
+ total_sales : $total_sales
491
+ transaction_count: $transaction_count
492
+ period_start : $twenty_four_hours_ago
493
+ period_end : $report_date
494
+ }
495
+
496
+ description = "Insert daily sales report into reports table"
497
+ } as $report_result
498
+
499
+ debug.log {
500
+ value = "Daily sales report generated successfully"
501
+ description = "Log successful report generation"
502
+ }
503
+ }
504
+ }
505
+ }
506
+
507
+ schedule = [{starts_on: 2026-05-01 23:00:00+0000, freq: 86400}]
508
+
509
+ history = "inherit"
510
+ }
511
+ ```
@@ -0,0 +1,103 @@
1
+ ---
2
+ applyTo: "tasks/*.xs"
3
+ ---
4
+
5
+ # How to Define Tasks in XanoScript
6
+
7
+ A **task** in XanoScript is a scheduled job that automates operations at specific times or intervals. Tasks are created in the `tasks` folder and are ideal for recurring jobs like data cleanup, report generation, or sending notifications.
8
+
9
+ ## Task Structure
10
+
11
+ A task file consists of:
12
+
13
+ - The task name (e.g., `daily_report`, `cleanup_expired_sessions`)
14
+ - An optional `description` field
15
+ - A `stack` block containing the logic to execute
16
+ - A `schedule` block specifying when the task runs
17
+
18
+ ## Example Task
19
+
20
+ The following task would be stored in `tasks/daily_sales_report.xs`
21
+
22
+ ```xs
23
+ task "daily_sales_report" {
24
+ description = "Generate a daily sales report at 11 PM UTC"
25
+ stack {
26
+ db.query "payment_transactions" {
27
+ description = "Get all transactions from the past 24 hours"
28
+ where = $db.payment_transactions.transaction_date >= (now|transform_timestamp:"24 hours ago":"UTC")
29
+ } as $daily_sales
30
+
31
+ var $transaction_count {
32
+ value = $daily_sales|count
33
+ description = "Count number of transactions"
34
+ }
35
+
36
+ var $total_sales {
37
+ value = ($daily_sales[$$].amount)|sum
38
+ description = "Calculate total sales amount"
39
+ }
40
+
41
+ db.add reports {
42
+ data = {
43
+ report_type : "daily_sales"
44
+ report_date : now
45
+ total_sales : $total_sales
46
+ transaction_count: $transaction_count
47
+ }
48
+ description = "Insert daily sales report"
49
+ } as $report_result
50
+
51
+ debug.log {
52
+ value = "Daily sales report generated"
53
+ description = "Log report generation"
54
+ }
55
+ }
56
+
57
+ schedule = [{starts_on: 2026-05-01 23:00:00+0000, freq: 86400}]
58
+ }
59
+ ```
60
+
61
+ ## Stack Block
62
+
63
+ The `stack` block contains the sequence of actions to perform, such as:
64
+
65
+ - Database queries (`db.query`, `db.add`, `db.edit`, `db.patch` etc.)
66
+ - Variable declarations (`var`)
67
+ - Control flow (`foreach`, `conditional`)
68
+ - Logging (`debug.log`)
69
+ - API calls (`api.request`)
70
+
71
+ ## Schedule Block
72
+
73
+ The `schedule` block defines when the task runs. It uses an `events` array with:
74
+
75
+ - `starts_on`: Start date and time (e.g., `2026-05-01 23:00:00+0000`)
76
+ - `freq`: Frequency in seconds (e.g., `86400` for daily)
77
+ - `ends_on`: Optional end date
78
+
79
+ **Example:**
80
+
81
+ ```xs
82
+ schedule {
83
+ events = [
84
+ {starts_on: 2026-05-01 23:00:00+0000, freq: 86400}
85
+ ]
86
+ }
87
+ ```
88
+
89
+ ## Best Practices
90
+
91
+ - Use `description` fields to document the purpose of your task and each block.
92
+ - Place all logic inside the `stack` block.
93
+ - Use the `schedule` block to automate execution.
94
+ - Use logging (`debug.log`) to track task execution and outcomes.
95
+
96
+ ## Summary
97
+
98
+ - Place tasks in the `tasks` folder.
99
+ - Use the `stack` block for job logic.
100
+ - Use the `schedule` block for timing.
101
+ - Document your task with `description` fields.
102
+
103
+ For more examples, see the documentation or sample tasks in your