@xano/developer-mcp 1.0.5 → 1.0.6

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/dist/index.js CHANGED
@@ -47,6 +47,11 @@ const XANOSCRIPT_DOCS_V2 = {
47
47
  applyTo: ["tasks/*.xs"],
48
48
  description: "Scheduled and cron jobs",
49
49
  },
50
+ triggers: {
51
+ file: "triggers.md",
52
+ applyTo: ["triggers/**/*.xs"],
53
+ description: "Event-driven handlers (table, realtime, workspace, agent, MCP)",
54
+ },
50
55
  database: {
51
56
  file: "database.md",
52
57
  applyTo: ["functions/**/*.xs", "apis/**/*.xs", "tasks/*.xs", "tools/**/*.xs"],
@@ -22,6 +22,7 @@ ${formatRow("function", "Custom reusable functions in `functions/`")}
22
22
  ${formatRow("api_query", "HTTP API endpoints in `apis/`")}
23
23
  ${formatRow("table", "Database table schemas in `tables/`")}
24
24
  ${formatRow("task", "Scheduled background tasks in `tasks/`")}
25
+ ${formatRow("triggers", "Event-driven handlers in `triggers/`")}
25
26
  ${formatRow("tool", "AI-callable tools in `tools/`")}
26
27
  ${formatRow("agent", "AI agents in `agents/`")}
27
28
  ${formatRow("mcp_server", "MCP servers in `mcp_servers/`")}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xano/developer-mcp",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "description": "MCP server for Xano Headless API documentation and XanoScript code validation",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -10,6 +10,7 @@ XanoScript is the declarative scripting language for [Xano](https://xano.com), a
10
10
  | `function` | `functions/**/*.xs` | Reusable logic blocks |
11
11
  | `query` | `apis/<group>/*.xs` | HTTP API endpoints |
12
12
  | `task` | `tasks/*.xs` | Scheduled/cron jobs |
13
+ | `*_trigger` | `triggers/**/*.xs` | Event-driven handlers |
13
14
  | `agent` | `agents/**/*.xs` | AI-powered agents |
14
15
  | `tool` | `tools/**/*.xs` | Tools for AI agents |
15
16
  | `mcp_server` | `mcp_servers/**/*.xs` | MCP server definitions |
@@ -24,6 +25,7 @@ project/
24
25
  ├── apis/
25
26
  │ └── <api-group>/ # API endpoints grouped by domain
26
27
  ├── tasks/ # Scheduled jobs
28
+ ├── triggers/ # Event-driven handlers
27
29
  ├── agents/ # AI agents
28
30
  ├── tools/ # AI tools
29
31
  ├── mcp_servers/ # MCP server definitions
@@ -91,17 +93,21 @@ This helps AI tools apply the correct documentation based on the file being edit
91
93
 
92
94
  ## Documentation Index
93
95
 
94
- 1. [Syntax Reference](syntax.md) - Expressions, operators, filters
95
- 2. [Types & Inputs](types.md) - Data types, validation, input blocks
96
- 3. [Tables](tables.md) - Database schema definitions
97
- 4. [Functions](functions.md) - Reusable function stacks
98
- 5. [APIs](apis.md) - HTTP endpoint definitions
99
- 6. [Tasks](tasks.md) - Scheduled jobs
100
- 7. [Database Operations](database.md) - Query, add, edit, delete
101
- 8. [Agents](agents.md) - AI agent configuration
102
- 9. [Tools](tools.md) - AI tools for agents
103
- 10. [MCP Servers](mcp-servers.md) - Model Context Protocol servers
104
- 11. [Testing](testing.md) - Unit tests and mocking
105
- 12. [Integrations](integrations.md) - Cloud services, Redis, security
106
- 13. [Frontend](frontend.md) - Static frontend development
107
- 14. [Ephemeral](ephemeral.md) - Temporary environments
96
+ Use `xanoscript_docs({ keyword: "<keyword>" })` to retrieve documentation.
97
+
98
+ | Topic | Keyword | Description |
99
+ |-------|---------|-------------|
100
+ | Syntax Reference | `syntax` | Expressions, operators, filters |
101
+ | Types & Inputs | `input` | Data types, validation, input blocks |
102
+ | Tables | `table` | Database schema definitions |
103
+ | Functions | `function` | Reusable function stacks |
104
+ | APIs | `api_query` | HTTP endpoint definitions |
105
+ | Tasks | `task` | Scheduled jobs |
106
+ | Triggers | `trigger` | Event-driven handlers (table, realtime, workspace, agent, MCP) |
107
+ | Database Operations | `db_query` | Query, add, edit, delete |
108
+ | Agents | `agent` | AI agent configuration |
109
+ | Tools | `tool` | AI tools for agents |
110
+ | MCP Servers | `mcp_server` | Model Context Protocol servers |
111
+ | Testing | `testing` | Unit tests and mocking |
112
+ | Frontend | `frontend` | Static frontend development |
113
+ | Ephemeral | `ephemeral` | Temporary environments
@@ -324,6 +324,4 @@ agent "Research Assistant" {
324
324
  3. **Limit max_steps** - Prevent infinite loops (3-10 typical)
325
325
  4. **Don't repeat tool descriptions** - They're auto-injected
326
326
  5. **Use environment variables** - Never hardcode API keys
327
- 6. **Keep prompts focused** - One task per agent
328
- 7. **Test with xano-free first** - Free for development
329
- 8. **Use structured outputs** - When you need consistent JSON
327
+ 6. **Test with xano-free first** - Free for development
@@ -38,61 +38,28 @@ The query name can include slashes for nested paths:
38
38
 
39
39
  ### API Groups (Required)
40
40
 
41
- Every API endpoint **must** belong to an API group. API groups organize related endpoints together.
42
-
43
- **Two requirements for API groups:**
44
- 1. Each `query` definition **must** include an `api_group` property specifying which group it belongs to
45
- 2. API groups are organized as folders within `apis/`, each with an `api_group.xs` file
46
-
47
- - API groups appear as top-level folders under `apis/`
48
- - Each group **must** have an `api_group.xs` file that defines the group
49
- - The group contains `.xs` files defining individual endpoints
50
- - The group name becomes part of the endpoint URL path
51
- - You cannot create endpoints directly in the `apis/` root folder
52
-
53
- #### Defining an API Group
54
-
55
- Create an `api_group.xs` file in the group folder:
41
+ Every endpoint must belong to an API group. Each group is a folder with an `api_group.xs` file:
56
42
 
57
43
  ```xs
58
44
  api_group "users" {
59
- canonical = "users" # Required: the URL path segment
60
- description = "User management endpoints"
45
+ canonical = "users" # Required: URL path segment
46
+ description = "User management" # Optional
61
47
  }
62
48
  ```
63
49
 
64
- #### API Group Properties
65
-
66
- | Property | Required | Description |
67
- |----------|----------|-------------|
68
- | `canonical` | **Yes** | The URL path segment for this group. You cannot access a Xano API without it. |
69
- | `description` | No | What this API group contains |
70
-
71
- ```xs
72
- api_group "events" {
73
- canonical = "events-api" # Required: URL will use /events-api
74
- description = "Event management"
75
- }
76
- ```
77
-
78
- > **Important:** The `canonical` property is required. It defines the base path for all endpoints in this group.
79
-
80
50
  ### File Structure
81
51
  ```
82
52
  apis/
83
- ├── users/ # API group folder
84
- │ ├── api_group.xs # Required: defines the group (canonical = "users")
53
+ ├── users/
54
+ │ ├── api_group.xs # Defines group (canonical = "users")
85
55
  │ ├── list.xs # GET /users/list
86
- │ ├── create.xs # POST /users/create
87
56
  │ └── by-id.xs # GET/PATCH/DELETE /users/{id}
88
- └── products/ # Another API group
89
- ├── api_group.xs # Required: defines the group (canonical = "products")
57
+ └── products/
58
+ ├── api_group.xs # Defines group (canonical = "products")
90
59
  └── search.xs # GET /products/search
91
60
  ```
92
61
 
93
- > **URL Path:** The full endpoint URL is always `/<canonical>/<query name>`. For example, if `api_group.xs` has `canonical = "users"` and a query has `query "profile" verb=GET`, the endpoint URL is `/users/profile`.
94
-
95
- > **Note:** Files placed directly in `apis/` without a group folder are invalid. Each API group folder must contain an `api_group.xs` file.
62
+ Full URL: `/<canonical>/<query name>` (e.g., `/users/profile`)
96
63
 
97
64
  ---
98
65
 
@@ -354,33 +321,11 @@ stack {
354
321
 
355
322
  ## Error Handling
356
323
 
357
- ### Preconditions
358
- ```xs
359
- stack {
360
- precondition ($input.amount > 0) {
361
- error_type = "inputerror"
362
- error = "Amount must be positive"
363
- }
364
-
365
- precondition ($user != null) {
366
- error_type = "notfound"
367
- error = "User not found"
368
- }
369
-
370
- precondition ($user.id == $auth.id) {
371
- error_type = "accessdenied"
372
- error = "Not authorized"
373
- }
374
- }
375
- ```
324
+ For complete error handling reference, use `xanoscript_docs({ keyword: "syntax" })`.
376
325
 
377
- ### Error Types
378
326
  | Type | HTTP Status |
379
327
  |------|-------------|
380
- | `inputerror` | 400 Bad Request |
381
- | `accessdenied` | 403 Forbidden |
382
- | `notfound` | 404 Not Found |
383
- | `standard` | 500 Internal Server Error |
328
+ | `inputerror` | 400 | `accessdenied` | 403 | `notfound` | 404 | `standard` | 500 |
384
329
 
385
330
  ---
386
331
 
@@ -404,13 +349,8 @@ When using `return = { type: "list", paging: {...} }`:
404
349
 
405
350
  ## Best Practices
406
351
 
407
- 1. **Always set canonical** - Every `api_group` requires a `canonical` property
408
- 2. **Always name queries** - Every `query` requires a non-empty name
409
- 3. **RESTful design** - Use appropriate HTTP methods
410
- 4. **Consistent naming** - Use lowercase, hyphens for multi-word paths
411
- 5. **Authenticate sensitive operations** - Always auth for writes
412
- 6. **Validate inputs** - Use filters and preconditions
413
- 7. **Return appropriate errors** - Use correct error types
414
- 8. **Paginate lists** - Never return unbounded lists
415
- 9. **Document with description** - Explain what endpoint does
416
- 10. **Group related endpoints** - Organize by resource in api groups
352
+ 1. **RESTful design** - Use appropriate HTTP methods for operations
353
+ 2. **Consistent naming** - Use lowercase, hyphens for multi-word paths
354
+ 3. **Authenticate writes** - Always require auth for POST/PATCH/DELETE
355
+ 4. **Paginate lists** - Never return unbounded result sets
356
+ 5. **Group by resource** - Organize endpoints in logical api groups
@@ -411,7 +411,4 @@ db.external.oracle.direct_query { ... }
411
411
  2. **Use db.get for single lookups** - Simpler than db.query with single return
412
412
  3. **Use db.patch for dynamic updates** - Accepts variable data
413
413
  4. **Use transactions for atomicity** - Ensure all-or-nothing operations
414
- 5. **Add indexes** - Index fields used in where clauses
415
- 6. **Use null-safe operators** - `==?` for optional filters
416
- 7. **Paginate results** - Never return unbounded lists
417
- 8. **Validate before delete** - Check ownership/permissions
414
+ 5. **Use null-safe operators** - `==?` for optional filters
@@ -325,9 +325,6 @@ publish_ephemeral_service name="migration" directory="ephemeral/my-job" mode="jo
325
325
 
326
326
  1. **Keep isolated** - Self-contained with own tables/functions
327
327
  2. **Seed test data** - Use `items` in table definitions
328
- 3. **Use environment variables** - Store config in workspace `env`
329
- 4. **Handle cleanup** - Use `$post` for notifications/cleanup
330
- 5. **Validate in $pre** - Check preconditions before main logic
331
- 6. **Use preconditions** - Verify expected outcomes in jobs
332
- 7. **Name clearly** - Indicate purpose: `auth-test`, `data-migration`
333
- 8. **Set end dates** - Use `ends_on` for temporary schedules
328
+ 3. **Handle cleanup** - Use `$post` for notifications/cleanup
329
+ 4. **Validate in $pre** - Check preconditions before main logic
330
+ 5. **Name clearly** - Indicate purpose: `auth-test`, `data-migration`
@@ -284,8 +284,5 @@ The tool will:
284
284
 
285
285
  1. **Get API specs first** - Use `get_xano_api_specifications` before coding
286
286
  2. **Centralize API calls** - Single `api.js` file
287
- 3. **Handle errors** - Show user-friendly messages
288
- 4. **Store tokens securely** - localStorage for web, secure storage for mobile
289
- 5. **Validate before submit** - Client-side validation before API calls
290
- 6. **Use loading states** - Show progress during API calls
291
- 7. **Test incrementally** - Migrate one feature at a time
287
+ 3. **Store tokens securely** - localStorage for web, secure storage for mobile
288
+ 4. **Test incrementally** - Migrate one feature at a time
@@ -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
 
@@ -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
 
@@ -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,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.)
@@ -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
+ ```
@@ -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
@@ -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
@@ -0,0 +1,532 @@
1
+ ---
2
+ applyTo: "triggers/**/*.xs"
3
+ ---
4
+
5
+ # Triggers
6
+
7
+ Event-driven handlers that execute in response to system events. Triggers allow you to react to database changes, real-time messages, workspace events, agent connections, and MCP server tool calls.
8
+
9
+ ## Quick Reference
10
+
11
+ | Trigger Type | Purpose | Required Clauses |
12
+ |--------------|---------|------------------|
13
+ | `table_trigger` | React to database table changes | `table`, `input`, `stack` |
14
+ | `realtime_trigger` | Handle real-time channel events | `channel`, `input`, `stack`, `response` |
15
+ | `workspace_trigger` | React to branch lifecycle events | `input`, `stack` |
16
+ | `agent_trigger` | Handle AI agent connections | `agent`, `input`, `stack`, `response` |
17
+ | `mcp_server_trigger` | Handle MCP server tool calls | `mcp_server`, `input`, `stack`, `response` |
18
+
19
+ ---
20
+
21
+ ## Table Trigger
22
+
23
+ Executes when database table records are inserted, updated, deleted, or truncated.
24
+
25
+ ### Syntax
26
+
27
+ ```xs
28
+ table_trigger "<name>" {
29
+ table = "<table_name>"
30
+ actions = {insert: true, update: true, delete: true, truncate: false}
31
+ datasources = ["datasource1", "datasource2"]
32
+ active = true
33
+ description = "Description of this trigger"
34
+ tags = ["tag1", "tag2"]
35
+
36
+ input {
37
+ # Define input parameters
38
+ }
39
+
40
+ stack {
41
+ # Logic to execute when triggered
42
+ }
43
+
44
+ history = 100
45
+ }
46
+ ```
47
+
48
+ ### Required Clauses
49
+
50
+ | Clause | Description |
51
+ |--------|-------------|
52
+ | `table` | The database table name to monitor |
53
+ | `input` | Input parameter definitions |
54
+ | `stack` | Logic to execute when triggered |
55
+
56
+ ### Optional Clauses
57
+
58
+ | Clause | Type | Description |
59
+ |--------|------|-------------|
60
+ | `actions` | object | Which operations trigger execution |
61
+ | `active` | boolean | Enable/disable the trigger |
62
+ | `datasources` | array | List of datasources to apply trigger to |
63
+ | `description` | string | Human-readable description |
64
+ | `history` | integer/string | History retention setting |
65
+ | `tags` | array | Tags for organization |
66
+
67
+ ### Actions
68
+
69
+ | Action | Description |
70
+ |--------|-------------|
71
+ | `insert` | Trigger on new record creation |
72
+ | `update` | Trigger on record modification |
73
+ | `delete` | Trigger on record deletion |
74
+ | `truncate` | Trigger when table is truncated |
75
+
76
+ ### Example
77
+
78
+ ```xs
79
+ table_trigger "audit_user_changes" {
80
+ table = "user"
81
+ actions = {insert: true, update: true, delete: true, truncate: false}
82
+ active = true
83
+ description = "Log all changes to user records"
84
+ datasources = ["main_db"]
85
+
86
+ input {
87
+ }
88
+
89
+ stack {
90
+ db.add "audit_log" {
91
+ data = {
92
+ table_name: "user",
93
+ action: $trigger.action,
94
+ record_id: $trigger.record.id,
95
+ timestamp: now
96
+ }
97
+ }
98
+ }
99
+
100
+ history = 100
101
+ }
102
+ ```
103
+
104
+ ---
105
+
106
+ ## Realtime Trigger
107
+
108
+ Handles events from real-time channels, such as client joins or messages.
109
+
110
+ ### Syntax
111
+
112
+ ```xs
113
+ realtime_trigger "<name>" {
114
+ channel = "<channel_name>"
115
+ actions = {join: true, message: true}
116
+ active = true
117
+ description = "Description of this trigger"
118
+ tags = ["tag1", "tag2"]
119
+
120
+ input {
121
+ # Define input parameters
122
+ }
123
+
124
+ stack {
125
+ # Logic to execute when triggered
126
+ }
127
+
128
+ response = $result
129
+
130
+ history = 100
131
+ }
132
+ ```
133
+
134
+ ### Required Clauses
135
+
136
+ | Clause | Description |
137
+ |--------|-------------|
138
+ | `channel` | The real-time channel to monitor |
139
+ | `input` | Input parameter definitions |
140
+ | `stack` | Logic to execute when triggered |
141
+ | `response` | Value to return to the client |
142
+
143
+ ### Optional Clauses
144
+
145
+ | Clause | Type | Description |
146
+ |--------|------|-------------|
147
+ | `actions` | object | Which events trigger execution |
148
+ | `active` | boolean | Enable/disable the trigger |
149
+ | `description` | string | Human-readable description |
150
+ | `history` | integer/string | History retention setting |
151
+ | `tags` | array | Tags for organization |
152
+
153
+ ### Actions
154
+
155
+ | Action | Description |
156
+ |--------|-------------|
157
+ | `join` | Trigger when a client joins the channel |
158
+ | `message` | Trigger when a message is received |
159
+
160
+ ### Example
161
+
162
+ ```xs
163
+ realtime_trigger "chat_message_handler" {
164
+ channel = "chat_room"
165
+ actions = {join: true, message: true}
166
+ active = true
167
+ description = "Handle chat room messages and joins"
168
+
169
+ input {
170
+ text message filters=trim
171
+ }
172
+
173
+ stack {
174
+ conditional {
175
+ if ($trigger.action == "join") {
176
+ var $welcome { value = "Welcome to the chat!" }
177
+ }
178
+ else {
179
+ db.add "chat_message" {
180
+ data = {
181
+ channel: "chat_room",
182
+ user_id: $auth.id,
183
+ message: $input.message,
184
+ timestamp: now
185
+ }
186
+ }
187
+ var $welcome { value = null }
188
+ }
189
+ }
190
+ }
191
+
192
+ response = {status: "ok", welcome: $welcome}
193
+
194
+ history = false
195
+ }
196
+ ```
197
+
198
+ ---
199
+
200
+ ## Workspace Trigger
201
+
202
+ Executes in response to workspace branch lifecycle events.
203
+
204
+ ### Syntax
205
+
206
+ ```xs
207
+ workspace_trigger "<name>" {
208
+ actions = {branch_new: true, branch_merge: true, branch_live: true}
209
+ active = true
210
+ description = "Description of this trigger"
211
+ tags = ["tag1", "tag2"]
212
+
213
+ input {
214
+ # Define input parameters
215
+ }
216
+
217
+ stack {
218
+ # Logic to execute when triggered
219
+ }
220
+
221
+ history = 100
222
+ }
223
+ ```
224
+
225
+ ### Required Clauses
226
+
227
+ | Clause | Description |
228
+ |--------|-------------|
229
+ | `input` | Input parameter definitions |
230
+ | `stack` | Logic to execute when triggered |
231
+
232
+ ### Optional Clauses
233
+
234
+ | Clause | Type | Description |
235
+ |--------|------|-------------|
236
+ | `actions` | object | Which branch events trigger execution |
237
+ | `active` | boolean | Enable/disable the trigger |
238
+ | `description` | string | Human-readable description |
239
+ | `history` | integer/string | History retention setting |
240
+ | `tags` | array | Tags for organization |
241
+
242
+ ### Actions
243
+
244
+ | Action | Description |
245
+ |--------|-------------|
246
+ | `branch_new` | Trigger when a new branch is created |
247
+ | `branch_merge` | Trigger when a branch is merged |
248
+ | `branch_live` | Trigger when a branch goes live |
249
+
250
+ ### Example
251
+
252
+ ```xs
253
+ workspace_trigger "branch_notification" {
254
+ actions = {branch_new: true, branch_merge: true, branch_live: true}
255
+ active = true
256
+ description = "Send notifications on branch events"
257
+ tags = ["devops", "notifications"]
258
+
259
+ input {
260
+ }
261
+
262
+ stack {
263
+ util.send_email {
264
+ service_provider = "resend"
265
+ api_key = $env.RESEND_API_KEY
266
+ to = "team@example.com"
267
+ from = "system@example.com"
268
+ subject = "Branch Event: " ~ $trigger.action
269
+ message = "Branch '" ~ $trigger.branch_name ~ "' event: " ~ $trigger.action
270
+ }
271
+ }
272
+
273
+ history = false
274
+ }
275
+ ```
276
+
277
+ ---
278
+
279
+ ## Agent Trigger
280
+
281
+ Handles connections and interactions with AI agents.
282
+
283
+ ### Syntax
284
+
285
+ ```xs
286
+ agent_trigger "<name>" {
287
+ agent = "<agent_name>"
288
+ actions = {connection: true}
289
+ active = true
290
+ description = "Description of this trigger"
291
+ docs = "Extended documentation for the trigger"
292
+ tags = ["tag1", "tag2"]
293
+
294
+ input {
295
+ # Define input parameters
296
+ }
297
+
298
+ stack {
299
+ # Logic to execute when triggered
300
+ }
301
+
302
+ response = $result
303
+
304
+ history = "inherit"
305
+ }
306
+ ```
307
+
308
+ ### Required Clauses
309
+
310
+ | Clause | Description |
311
+ |--------|-------------|
312
+ | `agent` | The AI agent name this trigger handles |
313
+ | `input` | Input parameter definitions |
314
+ | `stack` | Logic to execute when triggered |
315
+ | `response` | Value to return |
316
+
317
+ ### Optional Clauses
318
+
319
+ | Clause | Type | Description |
320
+ |--------|------|-------------|
321
+ | `actions` | object | Which agent events trigger execution |
322
+ | `active` | boolean | Enable/disable the trigger |
323
+ | `description` | string | Short description |
324
+ | `docs` | string | Extended documentation |
325
+ | `history` | integer/string/boolean | History retention setting |
326
+ | `tags` | array | Tags for organization |
327
+
328
+ ### Actions
329
+
330
+ | Action | Description |
331
+ |--------|-------------|
332
+ | `connection` | Trigger on agent connection events |
333
+
334
+ ### Example
335
+
336
+ ```xs
337
+ agent_trigger "assistant_handler" {
338
+ agent = "customer_assistant"
339
+ actions = {connection: true}
340
+ active = true
341
+ description = "Handle customer assistant agent connections"
342
+ docs = "This trigger initializes the customer context when the agent connects"
343
+
344
+ input {
345
+ text session_id filters=trim
346
+ }
347
+
348
+ stack {
349
+ db.get "customer" {
350
+ field_name = "session_id"
351
+ field_value = $input.session_id
352
+ } as $customer
353
+
354
+ var $context {
355
+ value = {
356
+ customer_name: $customer.name,
357
+ customer_tier: $customer.tier,
358
+ history: $customer.support_history
359
+ }
360
+ }
361
+ }
362
+
363
+ response = $context
364
+
365
+ history = "inherit"
366
+ }
367
+ ```
368
+
369
+ ---
370
+
371
+ ## MCP Server Trigger
372
+
373
+ Handles tool calls from MCP (Model Context Protocol) servers.
374
+
375
+ ### Syntax
376
+
377
+ ```xs
378
+ mcp_server_trigger "<name>" {
379
+ mcp_server = "<server_name>"
380
+ actions = {connection: true}
381
+ active = true
382
+ description = "Description of this trigger"
383
+ tags = ["tag1", "tag2"]
384
+
385
+ input {
386
+ # Define input parameters
387
+ }
388
+
389
+ stack {
390
+ # Logic to execute when triggered
391
+ }
392
+
393
+ response = $result
394
+
395
+ history = false
396
+ }
397
+ ```
398
+
399
+ ### Required Clauses
400
+
401
+ | Clause | Description |
402
+ |--------|-------------|
403
+ | `mcp_server` | The MCP server name this trigger handles |
404
+ | `input` | Input parameter definitions |
405
+ | `stack` | Logic to execute when triggered |
406
+ | `response` | Value to return to the MCP client |
407
+
408
+ ### Optional Clauses
409
+
410
+ | Clause | Type | Description |
411
+ |--------|------|-------------|
412
+ | `actions` | object | Which MCP events trigger execution |
413
+ | `active` | boolean | Enable/disable the trigger |
414
+ | `description` | string | Human-readable description |
415
+ | `history` | integer/string/boolean | History retention setting |
416
+ | `tags` | array | Tags for organization |
417
+
418
+ ### Actions
419
+
420
+ | Action | Description |
421
+ |--------|-------------|
422
+ | `connection` | Trigger on MCP connection events (required) |
423
+
424
+ ### Example
425
+
426
+ ```xs
427
+ mcp_server_trigger "database_tool_handler" {
428
+ mcp_server = "database_tools"
429
+ actions = {connection: true}
430
+ active = true
431
+ description = "Handle database tool calls from MCP clients"
432
+ tags = ["mcp", "database"]
433
+
434
+ input {
435
+ text operation filters=trim
436
+ object params
437
+ }
438
+
439
+ stack {
440
+ conditional {
441
+ if ($input.operation == "query") {
442
+ db.query $input.params.table {
443
+ where = $input.params.where
444
+ } as $result
445
+ }
446
+ elseif ($input.operation == "insert") {
447
+ db.add $input.params.table {
448
+ data = $input.params.data
449
+ } as $result
450
+ }
451
+ else {
452
+ var $result { value = {error: "Unknown operation"} }
453
+ }
454
+ }
455
+ }
456
+
457
+ response = $result
458
+
459
+ history = false
460
+ }
461
+ ```
462
+
463
+ ---
464
+
465
+ ## Common Patterns
466
+
467
+ ### Error Handling in Triggers
468
+
469
+ ```xs
470
+ table_trigger "safe_audit" {
471
+ table = "sensitive_data"
472
+ actions = {insert: true, update: true, delete: true, truncate: false}
473
+
474
+ input {
475
+ }
476
+
477
+ stack {
478
+ try_catch {
479
+ try {
480
+ db.add "audit_log" {
481
+ data = {
482
+ action: $trigger.action,
483
+ timestamp: now
484
+ }
485
+ }
486
+ }
487
+ catch {
488
+ debug.log { value = "Audit logging failed" }
489
+ }
490
+ }
491
+ }
492
+ }
493
+ ```
494
+
495
+ ### Conditional Trigger Logic
496
+
497
+ ```xs
498
+ table_trigger "conditional_notification" {
499
+ table = "order"
500
+ actions = {insert: true, update: false, delete: false, truncate: false}
501
+
502
+ input {
503
+ }
504
+
505
+ stack {
506
+ conditional {
507
+ if ($trigger.record.total > 1000) {
508
+ util.send_email {
509
+ service_provider = "resend"
510
+ api_key = $env.RESEND_API_KEY
511
+ to = "sales@example.com"
512
+ from = "system@example.com"
513
+ subject = "High Value Order"
514
+ message = "Order #" ~ $trigger.record.id ~ " for $" ~ $trigger.record.total
515
+ }
516
+ }
517
+ }
518
+ }
519
+ }
520
+ ```
521
+
522
+ ---
523
+
524
+ ## Best Practices
525
+
526
+ 1. **Use descriptive names** - Indicate the event and action: `user_audit_log`, `chat_message_handler`
527
+ 2. **Handle errors gracefully** - Use try_catch to prevent trigger failures from affecting the main operation
528
+ 3. **Keep triggers lightweight** - Offload heavy processing to functions or tasks
529
+ 4. **Set appropriate history** - Use `history = false` for high-frequency triggers to save storage
530
+ 5. **Use tags** - Organize triggers with meaningful tags for easier management
531
+ 6. **Document with description** - Always provide a description explaining the trigger's purpose
532
+ 7. **Test thoroughly** - Triggers execute automatically, so ensure they handle edge cases
@@ -268,19 +268,12 @@ input {
268
268
 
269
269
  ## Validation with Preconditions
270
270
 
271
- For complex validation beyond filters:
271
+ For complex validation beyond filters, use preconditions. For complete error handling reference, use `xanoscript_docs({ keyword: "syntax" })`.
272
272
 
273
273
  ```xs
274
- stack {
275
- precondition ($input.start_date < $input.end_date) {
276
- error_type = "inputerror"
277
- error = "Start date must be before end date"
278
- }
279
-
280
- precondition ($input.password == $input.confirm_password) {
281
- error_type = "inputerror"
282
- error = "Passwords must match"
283
- }
274
+ precondition ($input.start_date < $input.end_date) {
275
+ error_type = "inputerror"
276
+ error = "Start date must be before end date"
284
277
  }
285
278
  ```
286
279
 
@@ -290,8 +283,5 @@ stack {
290
283
 
291
284
  1. **Always specify types** - Never leave inputs untyped
292
285
  2. **Use filters first** - Prefer declarative filters over stack validation
293
- 3. **Add descriptions** - Document every field's purpose
294
- 4. **Mark sensitive data** - Use `sensitive = true` for PII/credentials
295
- 5. **Use defaults sparingly** - Make requirements explicit
296
- 6. **Validate at boundaries** - Validate user input, trust internal calls
297
- 7. **Limit nesting depth** - Keep object schemas 2-3 levels max
286
+ 3. **Mark sensitive data** - Use `sensitive = true` for PII/credentials
287
+ 4. **Validate at boundaries** - Validate user input, trust internal calls
@@ -1,192 +0,0 @@
1
- # XanoScript AI Documentation v2 - Implementation Plan
2
-
3
- ## Design Principles
4
-
5
- ### AI-First Documentation Goals
6
- 1. **Scannable** - AI can quickly locate relevant syntax/patterns
7
- 2. **Self-contained** - Each doc has everything needed for its topic
8
- 3. **Pattern-consistent** - Identical structure across all docs
9
- 4. **Minimal but complete** - Not verbose, but covers all cases
10
- 5. **Examples inline** - Code immediately follows syntax it demonstrates
11
-
12
- ### Document Structure Template
13
- Every doc follows this structure:
14
- ```
15
- ---
16
- applyTo: "<glob pattern>"
17
- ---
18
-
19
- # <Topic>
20
-
21
- ## Quick Reference
22
- <Table or code block with syntax summary>
23
-
24
- ## Overview
25
- <1-2 paragraph explanation>
26
-
27
- ## <Concept 1>
28
- ### Syntax
29
- ### Example
30
- ### Notes
31
-
32
- ## <Concept 2>
33
- ...
34
-
35
- ## Best Practices
36
- <Bullet list>
37
-
38
- ## Common Patterns
39
- <Real-world usage patterns>
40
- ```
41
-
42
- ---
43
-
44
- ## Proposed File Structure
45
-
46
- ### Core (Required for any XanoScript work)
47
- | File | Purpose | Source Files |
48
- |------|---------|--------------|
49
- | `README.md` | Overview, workspace structure, getting started | README.md, workspace.md |
50
- | `syntax.md` | Expressions, operators, filters | expression_guideline.md, query_filter.md |
51
- | `types.md` | Data types, input blocks, validation | input_guideline.md, functions.md (input section) |
52
-
53
- ### Primary Constructs
54
- | File | Purpose | Source Files |
55
- |------|---------|--------------|
56
- | `tables.md` | Database schemas, indexes, relationships | table_guideline.md, table_examples.md |
57
- | `functions.md` | Reusable function stacks | function_guideline.md, function_examples.md |
58
- | `apis.md` | HTTP API endpoints | api_query_guideline.md, api_query_examples.md |
59
- | `tasks.md` | Scheduled jobs | task_guideline.md, task_examples.md |
60
- | `database.md` | All db.* operations | db_query_guideline.md, functions.md (db section) |
61
-
62
- ### AI Integration
63
- | File | Purpose | Source Files |
64
- |------|---------|--------------|
65
- | `agents.md` | AI agents, LLM providers | agent_guideline.md, agent_examples.md |
66
- | `tools.md` | AI tools for agents/MCP | tool_guideline.md, tool_examples.md |
67
- | `mcp-servers.md` | MCP server configuration | mcp_server_guideline.md, mcp_server_examples.md |
68
-
69
- ### Advanced Features
70
- | File | Purpose | Source Files |
71
- |------|---------|--------------|
72
- | `testing.md` | Unit tests, mocks, assertions | unit_testing_guideline.md |
73
- | `integrations.md` | Cloud, Redis, storage, security | functions.md (cloud/redis/security sections) |
74
- | `frontend.md` | Static frontend, Lovable migration | frontend_guideline.md, build_from_lovable.md |
75
- | `ephemeral.md` | Ephemeral services and jobs | ephemeral_environment_guideline.md |
76
-
77
- ### Reference (Optional)
78
- | File | Purpose | Source Files |
79
- |------|---------|--------------|
80
- | `tips.md` | Tips, tricks, gotchas | tips_and_tricks.md |
81
-
82
- ---
83
-
84
- ## Content Reduction Strategy
85
-
86
- ### V1 Verbosity Issues
87
- 1. **Redundant examples** - Multiple examples showing same pattern
88
- 2. **Explanation repetition** - Same concept explained in guideline AND examples
89
- 3. **Over-commented code** - Examples have excessive inline comments
90
- 4. **Separate files** - guideline.md + examples.md = duplication
91
-
92
- ### V2 Approach
93
- 1. **One canonical example** per feature (not 3-5)
94
- 2. **Table-based syntax reference** - Quick scan, no prose
95
- 3. **Inline examples** - Example immediately after syntax
96
- 4. **Comments only for non-obvious** - Trust the reader
97
-
98
- ### Example Transformation
99
-
100
- **V1 Style (verbose):**
101
- ```xs
102
- // This function calculates the total cost
103
- // by multiplying quantity by price per item
104
- // and returns the result
105
- function "maths/calculate_total" {
106
- description = "Calculate the total cost based on quantity and price per item"
107
-
108
- input {
109
- int quantity filters=min:0 {
110
- description = "Number of items"
111
- }
112
-
113
- decimal price_per_item filters=min:0.01 {
114
- description = "Price for each item"
115
- }
116
- }
117
-
118
- stack {
119
- var $total {
120
- value = 0
121
- description = "Initialize total"
122
- }
123
-
124
- math.add $total {
125
- value = $input.quantity * $input.price_per_item
126
- description = "Calculate total"
127
- }
128
- }
129
-
130
- response = $total
131
- }
132
- ```
133
-
134
- **V2 Style (minimal):**
135
- ```xs
136
- function "calculate_total" {
137
- input {
138
- int quantity filters=min:0
139
- decimal price filters=min:0.01
140
- }
141
- stack {
142
- var $total { value = $input.quantity * $input.price }
143
- }
144
- response = $total
145
- }
146
- ```
147
-
148
- ---
149
-
150
- ## Estimated Reduction
151
-
152
- | Metric | V1 | V2 Target | Reduction |
153
- |--------|-----|-----------|-----------|
154
- | Files | 27 | 14 | ~48% |
155
- | Total Lines | ~5000 | ~2000 | ~60% |
156
- | Avg File Size | 185 lines | 140 lines | ~25% |
157
-
158
- ---
159
-
160
- ## Implementation Order
161
-
162
- ### Phase 1: Foundation
163
- 1. README.md - Workspace overview
164
- 2. syntax.md - All expressions and filters
165
- 3. types.md - Data types and inputs
166
-
167
- ### Phase 2: Core Constructs
168
- 4. tables.md - Database tables
169
- 5. functions.md - Functions
170
- 6. apis.md - API endpoints
171
- 7. tasks.md - Scheduled tasks
172
- 8. database.md - DB operations
173
-
174
- ### Phase 3: AI Features
175
- 9. agents.md - AI agents
176
- 10. tools.md - AI tools
177
- 11. mcp-servers.md - MCP servers
178
-
179
- ### Phase 4: Advanced
180
- 12. testing.md - Unit testing
181
- 13. integrations.md - Cloud/Redis/Security
182
- 14. frontend.md - Frontend + Lovable
183
- 15. ephemeral.md - Ephemeral environments
184
-
185
- ---
186
-
187
- ## Questions Resolved
188
-
189
- - [x] Structure: Consolidated (single file per concept)
190
- - [x] Examples: Minimal (just enough to demonstrate)
191
- - [x] Quick Reference: Yes (syntax cheatsheets at top)
192
- - [x] Scope: Complete coverage (all features)