@xano/developer-mcp 1.0.5 → 1.0.7

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.
@@ -15,7 +15,7 @@ function "<name>" {
15
15
  <type> <name> [filters=...] { description = "..." }
16
16
  }
17
17
  stack {
18
- # Logic here
18
+ // Logic here
19
19
  }
20
20
  response = $result
21
21
  }
@@ -63,20 +63,13 @@ Reference with path: `function.run "math/add" { ... }`
63
63
 
64
64
  ## Input Block
65
65
 
66
- See [types.md](types.md) for complete type reference.
66
+ For complete type and filter reference, use `xanoscript_docs({ keyword: "input" })`.
67
67
 
68
68
  ```xs
69
69
  input {
70
70
  text name filters=trim
71
71
  int age? filters=min:0
72
72
  email contact filters=lower { sensitive = true }
73
- object address? {
74
- schema {
75
- text street
76
- text city
77
- text zip
78
- }
79
- }
80
73
  }
81
74
  ```
82
75
 
@@ -117,21 +110,21 @@ stack {
117
110
  ### Loops
118
111
  ```xs
119
112
  stack {
120
- # For loop (count-based)
113
+ // For loop (count-based)
121
114
  for (10) {
122
115
  each as $i {
123
116
  debug.log { value = $i }
124
117
  }
125
118
  }
126
119
 
127
- # Foreach (array iteration)
120
+ // Foreach (array iteration)
128
121
  foreach ($input.items) {
129
122
  each as $item {
130
123
  debug.log { value = $item.name }
131
124
  }
132
125
  }
133
126
 
134
- # While loop
127
+ // While loop
135
128
  while ($counter < 5) {
136
129
  each {
137
130
  math.add $counter { value = 1 }
@@ -158,49 +151,8 @@ stack {
158
151
  ```
159
152
 
160
153
  ### Error Handling
161
- ```xs
162
- stack {
163
- try_catch {
164
- try {
165
- function.run "risky_operation" { input = {} } as $result
166
- }
167
- catch {
168
- debug.log { value = "Operation failed" }
169
- var $result { value = null }
170
- }
171
- finally {
172
- debug.log { value = "Cleanup complete" }
173
- }
174
- }
175
- }
176
- ```
177
154
 
178
- ### Throwing Errors
179
- ```xs
180
- stack {
181
- precondition ($input.amount > 0) {
182
- error_type = "inputerror"
183
- error = "Amount must be positive"
184
- }
185
-
186
- throw {
187
- name = "ValidationError"
188
- value = "Custom error message"
189
- }
190
- }
191
- ```
192
-
193
- ### Early Return
194
- ```xs
195
- stack {
196
- conditional {
197
- if ($input.skip) {
198
- return { value = null }
199
- }
200
- }
201
- # Continue processing...
202
- }
203
- ```
155
+ For complete error handling reference (preconditions, try-catch, throw, early return), use `xanoscript_docs({ keyword: "syntax" })`.
204
156
 
205
157
  ---
206
158
 
@@ -209,10 +161,10 @@ stack {
209
161
  Specify what the function returns:
210
162
 
211
163
  ```xs
212
- response = $total # Single variable
213
- response = { success: true, data: $result } # Object literal
214
- response = $items|first # With filter
215
- response = null # No return value
164
+ response = $total // Single variable
165
+ response = { success: true, data: $result } // Object literal
166
+ response = $items|first // With filter
167
+ response = null // No return value
216
168
  ```
217
169
 
218
170
  ---
@@ -345,8 +297,5 @@ function "validate_email_unique" {
345
297
  1. **Single responsibility** - Each function does one thing well
346
298
  2. **Descriptive names** - Use verb_noun format: `calculate_total`, `validate_user`
347
299
  3. **Organize in folders** - Group related functions: `utils/`, `auth/`, `orders/`
348
- 4. **Validate inputs** - Use filters and preconditions
349
- 5. **Handle errors** - Use try_catch for external calls
350
- 6. **Document purpose** - Add description field
351
- 7. **Return early** - Use return for guard clauses
352
- 8. **Keep stacks shallow** - Avoid deeply nested conditionals
300
+ 4. **Return early** - Use return for guard clauses
301
+ 5. **Keep stacks shallow** - Avoid deeply nested conditionals
@@ -182,20 +182,20 @@ cloud.elasticsearch.document {
182
182
 
183
183
  ### Key-Value Operations
184
184
  ```xs
185
- # Set value
185
+ // Set value
186
186
  redis.set {
187
187
  key = "user:123:session"
188
188
  data = $session_data
189
- ttl = 3600 # Expires in 1 hour
189
+ ttl = 3600 // Expires in 1 hour
190
190
  }
191
191
 
192
- # Get value
192
+ // Get value
193
193
  redis.get { key = "user:123:session" } as $session
194
194
 
195
- # Check exists
195
+ // Check exists
196
196
  redis.has { key = "user:123:session" } as $exists
197
197
 
198
- # Delete
198
+ // Delete
199
199
  redis.del { key = "user:123:session" }
200
200
  ```
201
201
 
@@ -147,18 +147,18 @@ mcp_server "CRM" {
147
147
  ### By Domain
148
148
  ```
149
149
  mcp_servers/
150
- ├── support.xs # Customer support tools
151
- ├── ecommerce.xs # Store management
152
- ├── analytics.xs # Reporting and metrics
153
- └── admin.xs # Administrative functions
150
+ ├── support.xs // Customer support tools
151
+ ├── ecommerce.xs // Store management
152
+ ├── analytics.xs // Reporting and metrics
153
+ └── admin.xs // Administrative functions
154
154
  ```
155
155
 
156
156
  ### By Access Level
157
157
  ```
158
158
  mcp_servers/
159
- ├── public.xs # Public-facing tools
160
- ├── authenticated.xs # Requires auth
161
- └── admin.xs # Admin-only tools
159
+ ├── public.xs // Public-facing tools
160
+ ├── authenticated.xs // Requires auth
161
+ └── admin.xs // Admin-only tools
162
162
  ```
163
163
 
164
164
  ---
@@ -182,9 +182,6 @@ The MCP protocol handles:
182
182
  ## Best Practices
183
183
 
184
184
  1. **Clear naming** - Server name should indicate its purpose
185
- 2. **Memorable canonical IDs** - Use descriptive, stable identifiers
186
- 3. **Comprehensive instructions** - Guide AI on server's overall purpose
187
- 4. **Logical tool grouping** - Group related tools in one server
188
- 5. **Use tags** - Organize servers by category
189
- 6. **Keep focused** - One domain per server (support, analytics, etc.)
190
- 7. **Document internally** - Use description for team documentation
185
+ 2. **Comprehensive instructions** - Guide AI on server's overall purpose
186
+ 3. **Logical tool grouping** - Group related tools in one server
187
+ 4. **Keep focused** - One domain per server (support, analytics, etc.)
@@ -44,24 +44,24 @@ var $total { value = `$input.qty * $input.price` }
44
44
 
45
45
  ### Comparison
46
46
  ```xs
47
- $a == $b # Equal
48
- $a != $b # Not equal
49
- $a > $b # Greater than
50
- $a >= $b # Greater or equal
51
- $a < $b # Less than
52
- $a <= $b # Less or equal
47
+ $a == $b // Equal
48
+ $a != $b // Not equal
49
+ $a > $b // Greater than
50
+ $a >= $b // Greater or equal
51
+ $a < $b // Less than
52
+ $a <= $b // Less or equal
53
53
  ```
54
54
 
55
55
  ### Logical
56
56
  ```xs
57
- $a && $b # AND
58
- $a || $b # OR
59
- !$a # NOT
57
+ $a && $b // AND
58
+ $a || $b // OR
59
+ !$a // NOT
60
60
  ```
61
61
 
62
62
  ### Null-Safe Comparisons (DB Queries)
63
63
  ```xs
64
- # In db.query where clauses - ignore condition if value is null
64
+ // In db.query where clauses - ignore condition if value is null
65
65
  $db.post.category ==? $input.category
66
66
  $db.post.date >=? $input.start_date
67
67
  ```
@@ -88,11 +88,11 @@ $db.post.date >=? $input.start_date
88
88
 
89
89
  ### Array Math
90
90
  ```xs
91
- [1,2,3,4]|sum # 10
92
- [1,2,3,4]|avg # 2.5
93
- [1,2,3,4]|product # 24
94
- [5,2,8,1]|array_min # 1
95
- [5,2,8,1]|array_max # 8
91
+ [1,2,3,4]|sum // 10
92
+ [1,2,3,4]|avg // 2.5
93
+ [1,2,3,4]|product // 24
94
+ [5,2,8,1]|array_min // 1
95
+ [5,2,8,1]|array_max // 8
96
96
  ```
97
97
 
98
98
  ### Trigonometry
@@ -123,10 +123,10 @@ $db.post.date >=? $input.start_date
123
123
 
124
124
  ### Regex
125
125
  ```xs
126
- "/pattern/"|regex_matches:"subject" # Boolean match
127
- "/(\w+)/"|regex_get_first_match:"test" # First match
128
- "/\w+/"|regex_get_all_matches:"a b c" # All matches
129
- "/\s+/"|regex_replace:"-":"a b" # Replace: "a-b"
126
+ "/pattern/"|regex_matches:"subject" // Boolean match
127
+ "/(\w+)/"|regex_get_first_match:"test" // First match
128
+ "/\w+/"|regex_get_all_matches:"a b c" // All matches
129
+ "/\s+/"|regex_replace:"-":"a b" // Replace: "a-b"
130
130
  ```
131
131
 
132
132
  ---
@@ -155,36 +155,36 @@ $db.post.date >=? $input.start_date
155
155
 
156
156
  ### Functional Operations
157
157
  ```xs
158
- # Map - transform each element
159
- [{v:1},{v:2}]|map:$$.v*2 # [2,4]
158
+ // Map - transform each element
159
+ [{v:1},{v:2}]|map:$$.v*2 // [2,4]
160
160
 
161
- # Filter - keep matching elements
162
- [1,2,3,4]|filter:$$%2==0 # [2,4]
161
+ // Filter - keep matching elements
162
+ [1,2,3,4]|filter:$$%2==0 // [2,4]
163
163
 
164
- # Find - first matching element
165
- [{id:1},{id:2}]|find:$$.id==2 # {id:2}
164
+ // Find - first matching element
165
+ [{id:1},{id:2}]|find:$$.id==2 // {id:2}
166
166
 
167
- # FindIndex - index of first match
168
- [{id:1},{id:2}]|findIndex:$$.id==2 # 1
167
+ // FindIndex - index of first match
168
+ [{id:1},{id:2}]|findIndex:$$.id==2 // 1
169
169
 
170
- # Some - any element matches?
171
- [1,2,3]|some:$$>2 # true
170
+ // Some - any element matches?
171
+ [1,2,3]|some:$$>2 // true
172
172
 
173
- # Every - all elements match?
174
- [2,4,6]|every:$$%2==0 # true
173
+ // Every - all elements match?
174
+ [2,4,6]|every:$$%2==0 // true
175
175
 
176
- # Reduce - accumulate to single value
177
- [1,2,3,4]|reduce:$$+$result:0 # 10
176
+ // Reduce - accumulate to single value
177
+ [1,2,3,4]|reduce:$$+$result:0 // 10
178
178
  ```
179
179
 
180
180
  ### Grouping & Indexing
181
181
  ```xs
182
- # Group by property
182
+ // Group by property
183
183
  [{g:"a",v:1},{g:"b",v:2},{g:"a",v:3}]|index_by:g
184
- # {"a":[{g:"a",v:1},{g:"a",v:3}],"b":[{g:"b",v:2}]}
184
+ // {"a":[{g:"a",v:1},{g:"a",v:3}],"b":[{g:"b",v:2}]}
185
185
 
186
- # Sort
187
- [{n:"z"},{n:"a"}]|sort:n:text:false # Ascending by n
186
+ // Sort
187
+ [{n:"z"},{n:"a"}]|sort:n:text:false // Ascending by n
188
188
  ```
189
189
 
190
190
  ---
@@ -205,9 +205,9 @@ $db.post.date >=? $input.start_date
205
205
 
206
206
  ### Conditional Set
207
207
  ```xs
208
- {a:1}|set_conditional:"b":2:true # {a:1,b:2} if condition true
209
- {a:1}|set_ifnotempty:"b":"val" # Set only if val not empty
210
- {a:1}|set_ifnotnull:"b":$var # Set only if $var not null
208
+ {a:1}|set_conditional:"b":2:true // {a:1,b:2} if condition true
209
+ {a:1}|set_ifnotempty:"b":"val" // Set only if val not empty
210
+ {a:1}|set_ifnotnull:"b":$var // Set only if $var not null
211
211
  ```
212
212
 
213
213
  ---
@@ -229,8 +229,8 @@ $db.post.date >=? $input.start_date
229
229
 
230
230
  ### Null Handling
231
231
  ```xs
232
- null|first_notnull:0 # 0
233
- ""|first_notempty:"default" # "default"
232
+ null|first_notnull:0 // 0
233
+ ""|first_notempty:"default" // "default"
234
234
  ```
235
235
 
236
236
  ---
@@ -249,12 +249,12 @@ null|first_notnull:0 # 0
249
249
 
250
250
  ### Timestamp Parts
251
251
  ```xs
252
- $ts|timestamp_year # Year
253
- $ts|timestamp_month # Month (1-12)
254
- $ts|timestamp_day_of_month # Day (1-31)
255
- $ts|timestamp_hour # Hour (0-23)
256
- $ts|timestamp_minute # Minute (0-59)
257
- $ts|timestamp_day_of_week # Day (0=Sunday)
252
+ $ts|timestamp_year // Year
253
+ $ts|timestamp_month // Month (1-12)
254
+ $ts|timestamp_day_of_month // Day (1-31)
255
+ $ts|timestamp_hour // Hour (0-23)
256
+ $ts|timestamp_minute // Minute (0-59)
257
+ $ts|timestamp_day_of_week // Day (0=Sunday)
258
258
  ```
259
259
 
260
260
  ---
@@ -312,3 +312,73 @@ Used in `db.query` where clauses:
312
312
  $db.created_at|timestamp_add_days:7
313
313
  $db.created_at|timestamp_subtract_hours:24
314
314
  ```
315
+
316
+ ---
317
+
318
+ ## Error Handling
319
+
320
+ ### Preconditions
321
+
322
+ Validate conditions and throw typed errors:
323
+
324
+ ```xs
325
+ precondition ($input.amount > 0) {
326
+ error_type = "inputerror"
327
+ error = "Amount must be positive"
328
+ }
329
+
330
+ precondition ($user != null) {
331
+ error_type = "notfound"
332
+ error = "User not found"
333
+ }
334
+
335
+ precondition ($user.id == $auth.id) {
336
+ error_type = "accessdenied"
337
+ error = "Not authorized"
338
+ }
339
+ ```
340
+
341
+ ### Error Types
342
+
343
+ | Type | HTTP Status | Use Case |
344
+ |------|-------------|----------|
345
+ | `inputerror` | 400 Bad Request | Invalid input data |
346
+ | `accessdenied` | 403 Forbidden | Authorization failure |
347
+ | `notfound` | 404 Not Found | Resource doesn't exist |
348
+ | `standard` | 500 Internal Server Error | General errors |
349
+
350
+ ### Throwing Errors
351
+
352
+ ```xs
353
+ throw {
354
+ name = "ValidationError"
355
+ value = "Custom error message"
356
+ }
357
+ ```
358
+
359
+ ### Try-Catch
360
+
361
+ ```xs
362
+ try_catch {
363
+ try {
364
+ function.run "risky_operation" { input = {} } as $result
365
+ }
366
+ catch {
367
+ debug.log { value = "Operation failed" }
368
+ var $result { value = null }
369
+ }
370
+ finally {
371
+ debug.log { value = "Cleanup complete" }
372
+ }
373
+ }
374
+ ```
375
+
376
+ ### Early Return
377
+
378
+ ```xs
379
+ conditional {
380
+ if ($input.skip) {
381
+ return { value = null }
382
+ }
383
+ }
384
+ ```
@@ -10,9 +10,9 @@ Database table definitions in XanoScript.
10
10
 
11
11
  ```xs
12
12
  table "<name>" {
13
- auth = false # true if used for authentication
13
+ auth = false // true if used for authentication
14
14
  schema {
15
- int id # Primary key (required)
15
+ int id // Primary key (required)
16
16
  text name filters=trim
17
17
  timestamp created_at?=now
18
18
  }
@@ -72,10 +72,10 @@ schema {
72
72
  ### Optional & Defaults
73
73
  ```xs
74
74
  schema {
75
- text nickname? # Optional, no default
76
- timestamp created_at?=now # Optional, defaults to current time
77
- bool is_active?=true # Optional, defaults to true
78
- int status?=0 # Optional, defaults to 0
75
+ text nickname? // Optional, no default
76
+ timestamp created_at?=now // Optional, defaults to current time
77
+ bool is_active?=true // Optional, defaults to true
78
+ int status?=0 // Optional, defaults to 0
79
79
  }
80
80
  ```
81
81
 
@@ -139,7 +139,7 @@ schema {
139
139
  ### Vector Fields
140
140
  ```xs
141
141
  schema {
142
- vector embedding # For AI/ML embeddings
142
+ vector embedding // For AI/ML embeddings
143
143
  }
144
144
  ```
145
145
 
@@ -264,7 +264,4 @@ table "order" {
264
264
  2. **Use `auth = true`** only for authentication tables (typically just `user`)
265
265
  3. **Add indexes** for fields used in WHERE clauses and JOINs
266
266
  4. **Use appropriate types** - `email` for emails, `password` for credentials
267
- 5. **Mark sensitive fields** - Set `sensitive = true` for PII
268
- 6. **Use filters** - Apply `trim`, `lower` for consistency
269
- 7. **Default timestamps** - Use `?=now` for created_at fields
270
- 8. **Document with descriptions** - Add descriptions for non-obvious fields
267
+ 5. **Default timestamps** - Use `?=now` for created_at fields
@@ -222,7 +222,7 @@ task "risky_sync" {
222
222
  url = "https://external-api.com/data"
223
223
  method = "GET"
224
224
  } as $data
225
- # Process data...
225
+ // Process data...
226
226
  }
227
227
  catch {
228
228
  util.send_email {
@@ -244,11 +244,8 @@ task "risky_sync" {
244
244
 
245
245
  ## Best Practices
246
246
 
247
- 1. **Use descriptive names** - Indicate what and when: `daily_cleanup`, `hourly_sync`
248
- 2. **Add descriptions** - Explain the purpose and schedule
249
- 3. **Handle errors** - Use try_catch for external dependencies
250
- 4. **Log important events** - Use debug.log for tracking
251
- 5. **Use appropriate frequency** - Don't run more often than needed
252
- 6. **Consider timezone** - Schedule uses UTC (+0000)
253
- 7. **Batch operations** - Process in chunks for large datasets
254
- 8. **Set end dates** - Use ends_on for temporary schedules
247
+ 1. **Descriptive names** - Indicate what and when: `daily_cleanup`, `hourly_sync`
248
+ 2. **Handle errors** - Use try_catch for external dependencies
249
+ 3. **Consider timezone** - Schedule uses UTC (+0000)
250
+ 4. **Batch operations** - Process in chunks for large datasets
251
+ 5. **Set end dates** - Use ends_on for temporary schedules
@@ -325,11 +325,8 @@ function "calculate_discount" {
325
325
 
326
326
  ## Best Practices
327
327
 
328
- 1. **Test happy paths** - Verify expected behavior works
329
- 2. **Test edge cases** - Empty arrays, null values, boundaries
330
- 3. **Test error cases** - Invalid inputs, missing data
331
- 4. **Use mocks** - Isolate from external dependencies
332
- 5. **Descriptive test names** - Explain what's being tested
333
- 6. **One assertion focus** - Each test verifies one behavior
334
- 7. **Keep tests independent** - No shared state between tests
335
- 8. **Test at boundaries** - Min/max values, length limits
328
+ 1. **Test happy paths, edge cases, and errors** - Cover expected, boundary, and failure scenarios
329
+ 2. **Use mocks** - Isolate from external dependencies
330
+ 3. **Descriptive test names** - Explain what's being tested
331
+ 4. **One assertion focus** - Each test verifies one behavior
332
+ 5. **Keep tests independent** - No shared state between tests
@@ -62,20 +62,15 @@ tool "get_user_by_email" {
62
62
 
63
63
  ## Input Block
64
64
 
65
- Same as functions, but descriptions are especially important:
65
+ For complete type reference, use `xanoscript_docs({ keyword: "input" })`. For tools, input `description` fields are sent to the AI, so write them clearly:
66
66
 
67
67
  ```xs
68
68
  input {
69
- int order_id {
70
- description = "The unique order ID to look up"
71
- }
69
+ int order_id { description = "The unique order ID to look up" }
72
70
  enum status {
73
71
  description = "New status to set"
74
72
  values = ["pending", "processing", "shipped", "delivered"]
75
73
  }
76
- text reason? {
77
- description = "Optional reason for the status change"
78
- }
79
74
  }
80
75
  ```
81
76
 
@@ -299,7 +294,4 @@ tool "cancel_order" {
299
294
  2. **Describe all inputs** - Help AI construct valid requests
300
295
  3. **Use enums for fixed options** - Reduces AI errors
301
296
  4. **Keep tools focused** - One task per tool
302
- 5. **Handle errors gracefully** - Return clear error messages
303
- 6. **Validate inputs** - Use filters and preconditions
304
- 7. **Limit response size** - Don't return huge datasets
305
- 8. **Use composition** - Call other tools for complex operations
297
+ 5. **Limit response size** - Don't return huge datasets