@xano/developer-mcp 1.0.9 → 1.0.10

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xano/developer-mcp",
3
- "version": "1.0.9",
3
+ "version": "1.0.10",
4
4
  "description": "MCP server for Xano Headless API documentation and XanoScript code validation",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -9,15 +9,16 @@ Reusable subqueries for fetching related data in database queries.
9
9
  ## Quick Reference
10
10
 
11
11
  ```xs
12
- addon "<name>" {
13
- description = "What this addon fetches"
12
+ addon <name> {
14
13
  input {
15
14
  <type> <name>
16
15
  }
16
+
17
17
  stack {
18
- // Query logic
18
+ db.query <tableName> {
19
+ return = {type: "<return_type>"}
20
+ }
19
21
  }
20
- response = $result
21
22
  }
22
23
  ```
23
24
 
@@ -25,21 +26,20 @@ addon "<name>" {
25
26
 
26
27
  ## Basic Structure
27
28
 
28
- Addons define reusable data fetching logic that can be attached to query results.
29
+ Addons define reusable data fetching logic that can be attached to query results. The stack can only contain a `db.query` block.
29
30
 
30
31
  ```xs
31
- addon "comment_count" {
32
- description = "Count of comments for a post"
32
+ addon comment_count {
33
33
  input {
34
34
  int post_id
35
35
  }
36
+
36
37
  stack {
37
- db.query "comment" {
38
+ db.query comment {
38
39
  where = $db.comment.post_id == $input.post_id
39
- return = { type: "count" }
40
- } as $count
40
+ return = {type: "count"}
41
+ }
41
42
  }
42
- response = $count
43
43
  }
44
44
  ```
45
45
 
@@ -50,12 +50,12 @@ addon "comment_count" {
50
50
  ### In db.query
51
51
 
52
52
  ```xs
53
- db.query "post" {
53
+ db.query post {
54
54
  where = $db.post.author_id == $auth.id
55
55
  addon = [
56
56
  {
57
57
  name: "comment_count",
58
- input: { post_id: $output.id },
58
+ input: {post_id: $output.id},
59
59
  as: "items.comment_count"
60
60
  }
61
61
  ]
@@ -79,22 +79,22 @@ db.query "post" {
79
79
  ### Multiple Addons
80
80
 
81
81
  ```xs
82
- db.query "post" {
82
+ db.query post {
83
83
  where = $db.post.is_published == true
84
84
  addon = [
85
85
  {
86
86
  name: "comment_count",
87
- input: { post_id: $output.id },
87
+ input: {post_id: $output.id},
88
88
  as: "items.comments"
89
89
  },
90
90
  {
91
91
  name: "like_count",
92
- input: { post_id: $output.id },
92
+ input: {post_id: $output.id},
93
93
  as: "items.likes"
94
94
  },
95
95
  {
96
96
  name: "author_details",
97
- input: { user_id: $output.author_id },
97
+ input: {user_id: $output.author_id},
98
98
  as: "items.author"
99
99
  }
100
100
  ]
@@ -108,103 +108,75 @@ db.query "post" {
108
108
  ### Related List
109
109
 
110
110
  ```xs
111
- addon "recent_comments" {
112
- description = "Get recent comments for a post"
111
+ addon recent_comments {
113
112
  input {
114
113
  int post_id
115
114
  int limit?=5
116
115
  }
116
+
117
117
  stack {
118
- db.query "comment" {
118
+ db.query comment {
119
119
  where = $db.comment.post_id == $input.post_id
120
- sort = { created_at: "desc" }
120
+ sort = {created_at: "desc"}
121
121
  return = {
122
122
  type: "list",
123
- paging: { per_page: $input.limit }
123
+ paging: {per_page: $input.limit}
124
124
  }
125
- } as $comments
125
+ }
126
126
  }
127
- response = $comments.items
128
127
  }
129
128
  ```
130
129
 
131
- ### Aggregation
130
+ ### Count
132
131
 
133
132
  ```xs
134
- addon "order_stats" {
135
- description = "Order statistics for a user"
133
+ addon order_count {
136
134
  input {
137
135
  int user_id
138
136
  }
137
+
139
138
  stack {
140
- db.query "order" {
139
+ db.query order {
141
140
  where = $db.order.user_id == $input.user_id
142
- } as $orders
143
-
144
- var $stats {
145
- value = {
146
- total_orders: $orders|count,
147
- total_spent: $orders|map:$$.total|sum,
148
- avg_order: $orders|map:$$.total|avg
149
- }
141
+ return = {type: "count"}
150
142
  }
151
143
  }
152
- response = $stats
153
144
  }
154
145
  ```
155
146
 
156
- ### Nested Object
147
+ ### Boolean Check (Exists)
157
148
 
158
149
  ```xs
159
- addon "full_address" {
160
- description = "Get formatted address for a user"
150
+ addon has_premium {
161
151
  input {
162
152
  int user_id
163
153
  }
154
+
164
155
  stack {
165
- db.get "address" {
166
- field_name = "user_id"
167
- field_value = $input.user_id
168
- } as $address
169
-
170
- conditional {
171
- if ($address != null) {
172
- var $formatted {
173
- value = {
174
- street: $address.street,
175
- city: $address.city,
176
- state: $address.state,
177
- zip: $address.zip,
178
- full: $address.street ~ ", " ~ $address.city ~ ", " ~ $address.state ~ " " ~ $address.zip
179
- }
180
- }
181
- }
182
- else {
183
- var $formatted { value = null }
184
- }
156
+ db.query subscription {
157
+ where = $db.subscription.user_id == $input.user_id
158
+ && $db.subscription.status == "active"
159
+ && $db.subscription.expires_at > now
160
+ return = {type: "exists"}
185
161
  }
186
162
  }
187
- response = $formatted
188
163
  }
189
164
  ```
190
165
 
191
- ### Boolean Check
166
+ ### Single Record
192
167
 
193
168
  ```xs
194
- addon "has_premium" {
195
- description = "Check if user has premium subscription"
169
+ addon author_details {
196
170
  input {
197
171
  int user_id
198
172
  }
173
+
199
174
  stack {
200
- db.query "subscription" {
201
- where = $db.subscription.user_id == $input.user_id
202
- && $db.subscription.status == "active"
203
- && $db.subscription.expires_at > now
204
- return = { type: "exists" }
205
- } as $has_premium
175
+ db.query user {
176
+ where = $db.user.id == $input.user_id
177
+ return = {type: "single"}
178
+ }
206
179
  }
207
- response = $has_premium
208
180
  }
209
181
  ```
210
182
 
@@ -215,8 +187,8 @@ addon "has_premium" {
215
187
  Call an addon directly from a function or API.
216
188
 
217
189
  ```xs
218
- addon.call "comment_count" {
219
- input = { post_id: $input.post_id }
190
+ addon.call comment_count {
191
+ input = {post_id: $input.post_id}
220
192
  } as $count
221
193
  ```
222
194
 
@@ -224,16 +196,16 @@ addon.call "comment_count" {
224
196
 
225
197
  ```xs
226
198
  // Get stats for single record
227
- addon.call "order_stats" {
228
- input = { user_id: $auth.id }
229
- } as $my_stats
199
+ addon.call order_count {
200
+ input = {user_id: $auth.id}
201
+ } as $my_order_count
230
202
 
231
203
  // Conditional addon call
232
204
  conditional {
233
205
  if ($input.include_stats) {
234
- addon.call "detailed_stats" {
235
- input = { entity_id: $entity.id }
236
- } as $stats
206
+ addon.call order_count {
207
+ input = {user_id: $entity.id}
208
+ } as $count
237
209
  }
238
210
  }
239
211
  ```
@@ -245,9 +217,9 @@ conditional {
245
217
  Use `dbAddonAttr` for computed fields in queries.
246
218
 
247
219
  ```xs
248
- db.query "product" {
220
+ db.query product {
249
221
  eval = {
250
- discount_price: dbAddonAttr("calculate_discount", { product_id: $db.product.id })
222
+ discount_price: dbAddonAttr("calculate_discount", {product_id: $db.product.id})
251
223
  }
252
224
  } as $products
253
225
  ```
@@ -263,7 +235,7 @@ addons/
263
235
  ├── comment_count.xs
264
236
  ├── like_count.xs
265
237
  ├── author_details.xs
266
- ├── order_stats.xs
238
+ ├── order_count.xs
267
239
  └── has_premium.xs
268
240
  ```
269
241
 
@@ -279,7 +251,6 @@ addons/
279
251
 
280
252
  1. **Keep addons focused** - One purpose per addon
281
253
  2. **Use input parameters** - Make addons reusable
282
- 3. **Handle null cases** - Return sensible defaults
283
- 4. **Cache expensive addons** - Use Redis for slow queries
284
- 5. **Limit nested queries** - Avoid N+1 query patterns
285
- 6. **Document inputs** - Add descriptions to input fields
254
+ 3. **Use appropriate return types** - `list`, `single`, `count`, `exists`
255
+ 4. **Limit nested queries** - Avoid N+1 query patterns
256
+ 5. **Document inputs** - Add descriptions to input fields