@xano/developer-mcp 1.0.1 → 1.0.3

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 (42) hide show
  1. package/README.md +96 -31
  2. package/dist/index.js +248 -180
  3. package/package.json +4 -2
  4. package/xanoscript_docs/README.md +107 -1
  5. package/xanoscript_docs/agents.md +329 -0
  6. package/xanoscript_docs/apis.md +380 -0
  7. package/xanoscript_docs/database.md +417 -0
  8. package/xanoscript_docs/ephemeral.md +333 -0
  9. package/xanoscript_docs/frontend.md +291 -0
  10. package/xanoscript_docs/functions.md +232 -2035
  11. package/xanoscript_docs/integrations.md +439 -0
  12. package/xanoscript_docs/mcp-servers.md +190 -0
  13. package/xanoscript_docs/plan.md +192 -0
  14. package/xanoscript_docs/syntax.md +314 -0
  15. package/xanoscript_docs/tables.md +270 -0
  16. package/xanoscript_docs/tasks.md +254 -0
  17. package/xanoscript_docs/testing.md +335 -0
  18. package/xanoscript_docs/tools.md +305 -0
  19. package/xanoscript_docs/types.md +297 -0
  20. package/xanoscript_docs/version.json +2 -1
  21. package/xanoscript_docs/api_query_examples.md +0 -1255
  22. package/xanoscript_docs/api_query_guideline.md +0 -129
  23. package/xanoscript_docs/build_from_lovable.md +0 -715
  24. package/xanoscript_docs/db_query_guideline.md +0 -427
  25. package/xanoscript_docs/ephemeral_environment_guideline.md +0 -529
  26. package/xanoscript_docs/expression_guideline.md +0 -1086
  27. package/xanoscript_docs/frontend_guideline.md +0 -67
  28. package/xanoscript_docs/function_examples.md +0 -1406
  29. package/xanoscript_docs/function_guideline.md +0 -130
  30. package/xanoscript_docs/input_guideline.md +0 -227
  31. package/xanoscript_docs/mcp_server_examples.md +0 -36
  32. package/xanoscript_docs/mcp_server_guideline.md +0 -69
  33. package/xanoscript_docs/query_filter.md +0 -489
  34. package/xanoscript_docs/table_examples.md +0 -586
  35. package/xanoscript_docs/table_guideline.md +0 -137
  36. package/xanoscript_docs/task_examples.md +0 -511
  37. package/xanoscript_docs/task_guideline.md +0 -103
  38. package/xanoscript_docs/tips_and_tricks.md +0 -144
  39. package/xanoscript_docs/tool_examples.md +0 -69
  40. package/xanoscript_docs/tool_guideline.md +0 -139
  41. package/xanoscript_docs/unit_testing_guideline.md +0 -328
  42. package/xanoscript_docs/workspace.md +0 -17
@@ -0,0 +1,380 @@
1
+ ---
2
+ applyTo: "apis/**/*.xs"
3
+ ---
4
+
5
+ # APIs
6
+
7
+ HTTP endpoint definitions in XanoScript.
8
+
9
+ ## Quick Reference
10
+
11
+ ```xs
12
+ query "<path>" verb=<METHOD> {
13
+ description = "What this endpoint does"
14
+ auth = "<table>" # Optional: require authentication
15
+ input { ... }
16
+ stack { ... }
17
+ response = $result
18
+ }
19
+ ```
20
+
21
+ ### HTTP Methods
22
+ `GET`, `POST`, `PUT`, `PATCH`, `DELETE`
23
+
24
+ ### API Groups (Required)
25
+
26
+ Every API endpoint **must** belong to an API group. An API group is a folder within `apis/` that organizes related endpoints together.
27
+
28
+ - API groups appear as top-level folders under `apis/`
29
+ - Each group **must** have an `api_group.xs` file that defines the group
30
+ - The group contains `.xs` files defining individual endpoints
31
+ - The group name becomes part of the endpoint URL path
32
+ - You cannot create endpoints directly in the `apis/` root folder
33
+
34
+ #### Defining an API Group
35
+
36
+ Create an `api_group.xs` file in the group folder:
37
+
38
+ ```xs
39
+ api_group "users" {
40
+ description = "User management endpoints"
41
+ }
42
+ ```
43
+
44
+ #### API Group Properties
45
+
46
+ | Property | Description |
47
+ |----------|-------------|
48
+ | `description` | What this API group contains |
49
+ | `canonical` | Optional: custom URL path (overrides folder name) |
50
+
51
+ ```xs
52
+ api_group "events" {
53
+ canonical = "events-api" # URL will use /events-api instead of /events
54
+ }
55
+ ```
56
+
57
+ ### File Structure
58
+ ```
59
+ apis/
60
+ ├── users/ # API group folder
61
+ │ ├── api_group.xs # Required: defines the group
62
+ │ ├── list.xs # GET /users
63
+ │ ├── create.xs # POST /users
64
+ │ └── {id}.xs # GET/PATCH/DELETE /users/{id}
65
+ └── products/ # Another API group
66
+ ├── api_group.xs # Required: defines the group
67
+ └── search.xs # GET /products/search
68
+ ```
69
+
70
+ > **Note:** Files placed directly in `apis/` without a group folder are invalid. Each API group folder must contain an `api_group.xs` file.
71
+
72
+ ---
73
+
74
+ ## Basic Structure
75
+
76
+ ```xs
77
+ query "products" verb=GET {
78
+ description = "List all products"
79
+ input {
80
+ int page?=1 filters=min:1
81
+ int per_page?=20 filters=min:1|max:100
82
+ }
83
+ stack {
84
+ db.query "product" {
85
+ return = { type: "list", paging: { page: $input.page, per_page: $input.per_page } }
86
+ } as $products
87
+ }
88
+ response = $products
89
+ }
90
+ ```
91
+
92
+ ---
93
+
94
+ ## Authentication
95
+
96
+ ### Public Endpoint (default)
97
+ ```xs
98
+ query "status" verb=GET {
99
+ stack { }
100
+ response = { status: "ok" }
101
+ }
102
+ ```
103
+
104
+ ### Authenticated Endpoint
105
+ ```xs
106
+ query "profile" verb=GET {
107
+ auth = "user" # Requires valid JWT
108
+ stack {
109
+ db.get "user" {
110
+ field_name = "id"
111
+ field_value = $auth.id # User ID from token
112
+ } as $user
113
+ }
114
+ response = $user
115
+ }
116
+ ```
117
+
118
+ When `auth` is set:
119
+ - Endpoint requires Bearer token in `Authorization` header
120
+ - `$auth.id` contains authenticated user's ID
121
+ - Invalid/missing token returns 401
122
+
123
+ ---
124
+
125
+ ## Path Parameters
126
+
127
+ Use `{param}` in the path:
128
+
129
+ ```xs
130
+ query "users/{user_id}" verb=GET {
131
+ auth = "user"
132
+ input {
133
+ int user_id { table = "user" }
134
+ }
135
+ stack {
136
+ db.get "user" {
137
+ field_name = "id"
138
+ field_value = $input.user_id
139
+ } as $user
140
+ }
141
+ response = $user
142
+ }
143
+ ```
144
+
145
+ ---
146
+
147
+ ## CRUD Examples
148
+
149
+ ### List (GET)
150
+ ```xs
151
+ query "products" verb=GET {
152
+ input {
153
+ text category? filters=trim|lower
154
+ int page?=1
155
+ int per_page?=20
156
+ }
157
+ stack {
158
+ db.query "product" {
159
+ where = $db.product.category ==? $input.category
160
+ sort = { created_at: "desc" }
161
+ return = { type: "list", paging: { page: $input.page, per_page: $input.per_page } }
162
+ } as $products
163
+ }
164
+ response = $products
165
+ }
166
+ ```
167
+
168
+ ### Create (POST)
169
+ ```xs
170
+ query "products" verb=POST {
171
+ auth = "user"
172
+ input {
173
+ text name filters=trim
174
+ text description? filters=trim
175
+ decimal price filters=min:0
176
+ int category_id { table = "category" }
177
+ }
178
+ stack {
179
+ db.add "product" {
180
+ data = {
181
+ name: $input.name,
182
+ description: $input.description,
183
+ price: $input.price,
184
+ category_id: $input.category_id,
185
+ created_by: $auth.id
186
+ }
187
+ } as $product
188
+ }
189
+ response = $product
190
+ }
191
+ ```
192
+
193
+ ### Read (GET with ID)
194
+ ```xs
195
+ query "products/{product_id}" verb=GET {
196
+ input {
197
+ int product_id { table = "product" }
198
+ }
199
+ stack {
200
+ db.get "product" {
201
+ field_name = "id"
202
+ field_value = $input.product_id
203
+ } as $product
204
+
205
+ precondition ($product != null) {
206
+ error_type = "notfound"
207
+ error = "Product not found"
208
+ }
209
+ }
210
+ response = $product
211
+ }
212
+ ```
213
+
214
+ ### Update (PATCH)
215
+ ```xs
216
+ query "products/{product_id}" verb=PATCH {
217
+ auth = "user"
218
+ input {
219
+ int product_id { table = "product" }
220
+ text name? filters=trim
221
+ text description? filters=trim
222
+ decimal price? filters=min:0
223
+ }
224
+ stack {
225
+ var $updates { value = {} }
226
+
227
+ conditional {
228
+ if ($input.name != null) {
229
+ var.update $updates { value = $updates|set:"name":$input.name }
230
+ }
231
+ }
232
+ conditional {
233
+ if ($input.price != null) {
234
+ var.update $updates { value = $updates|set:"price":$input.price }
235
+ }
236
+ }
237
+
238
+ db.patch "product" {
239
+ field_name = "id"
240
+ field_value = $input.product_id
241
+ data = $updates
242
+ } as $product
243
+ }
244
+ response = $product
245
+ }
246
+ ```
247
+
248
+ ### Delete (DELETE)
249
+ ```xs
250
+ query "products/{product_id}" verb=DELETE {
251
+ auth = "user"
252
+ input {
253
+ int product_id { table = "product" }
254
+ }
255
+ stack {
256
+ db.del "product" {
257
+ field_name = "id"
258
+ field_value = $input.product_id
259
+ }
260
+ }
261
+ response = { success: true }
262
+ }
263
+ ```
264
+
265
+ ---
266
+
267
+ ## Response Types
268
+
269
+ ### JSON (default)
270
+ ```xs
271
+ response = $data
272
+ ```
273
+
274
+ ### HTML
275
+ ```xs
276
+ stack {
277
+ util.set_header {
278
+ value = "Content-Type: text/html; charset=utf-8"
279
+ duplicates = "replace"
280
+ }
281
+
282
+ util.template_engine {
283
+ value = """
284
+ <html>
285
+ <body><h1>{{ $var.title }}</h1></body>
286
+ </html>
287
+ """
288
+ } as $html
289
+ }
290
+ response = $html
291
+ ```
292
+
293
+ ### Streaming
294
+ ```xs
295
+ stack {
296
+ api.stream { value = $processed_data }
297
+ }
298
+ response = null
299
+ ```
300
+
301
+ ---
302
+
303
+ ## Custom Headers
304
+
305
+ ```xs
306
+ stack {
307
+ util.set_header {
308
+ value = "X-Custom-Header: value"
309
+ duplicates = "replace"
310
+ }
311
+
312
+ util.set_header {
313
+ value = "Set-Cookie: session=abc123; HttpOnly; Secure"
314
+ duplicates = "add"
315
+ }
316
+ }
317
+ ```
318
+
319
+ ---
320
+
321
+ ## Error Handling
322
+
323
+ ### Preconditions
324
+ ```xs
325
+ stack {
326
+ precondition ($input.amount > 0) {
327
+ error_type = "inputerror"
328
+ error = "Amount must be positive"
329
+ }
330
+
331
+ precondition ($user != null) {
332
+ error_type = "notfound"
333
+ error = "User not found"
334
+ }
335
+
336
+ precondition ($user.id == $auth.id) {
337
+ error_type = "accessdenied"
338
+ error = "Not authorized"
339
+ }
340
+ }
341
+ ```
342
+
343
+ ### Error Types
344
+ | Type | HTTP Status |
345
+ |------|-------------|
346
+ | `inputerror` | 400 Bad Request |
347
+ | `accessdenied` | 403 Forbidden |
348
+ | `notfound` | 404 Not Found |
349
+ | `standard` | 500 Internal Server Error |
350
+
351
+ ---
352
+
353
+ ## Pagination Response Format
354
+
355
+ When using `return = { type: "list", paging: {...} }`:
356
+
357
+ ```json
358
+ {
359
+ "itemsReceived": 20,
360
+ "curPage": 1,
361
+ "nextPage": 2,
362
+ "prevPage": null,
363
+ "offset": 0,
364
+ "perPage": 20,
365
+ "items": [...]
366
+ }
367
+ ```
368
+
369
+ ---
370
+
371
+ ## Best Practices
372
+
373
+ 1. **RESTful design** - Use appropriate HTTP methods
374
+ 2. **Consistent naming** - Use lowercase, hyphens for multi-word paths
375
+ 3. **Authenticate sensitive operations** - Always auth for writes
376
+ 4. **Validate inputs** - Use filters and preconditions
377
+ 5. **Return appropriate errors** - Use correct error types
378
+ 6. **Paginate lists** - Never return unbounded lists
379
+ 7. **Document with description** - Explain what endpoint does
380
+ 8. **Group related endpoints** - Organize by resource in api groups