@xano/developer-mcp 1.0.7 → 1.0.8

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/README.md CHANGED
@@ -39,6 +39,18 @@ Add to your Claude Desktop configuration file:
39
39
  }
40
40
  ```
41
41
 
42
+ ## Checking Your Version
43
+
44
+ ```bash
45
+ npx @xano/developer-mcp --version
46
+ ```
47
+
48
+ If installed from source:
49
+
50
+ ```bash
51
+ node dist/index.js --version
52
+ ```
53
+
42
54
  ## Installation from Source
43
55
 
44
56
  ### Prerequisites
package/dist/index.js CHANGED
@@ -11,6 +11,12 @@ import { getSchemeFromContent } from "@xano/xanoscript-language-server/utils.js"
11
11
  import { generateInitWorkspaceTemplate } from "./templates/init-workspace.js";
12
12
  const __filename = fileURLToPath(import.meta.url);
13
13
  const __dirname = dirname(__filename);
14
+ const pkg = JSON.parse(readFileSync(join(__dirname, "..", "package.json"), "utf-8"));
15
+ const SERVER_VERSION = pkg.version;
16
+ if (process.argv.includes("--version") || process.argv.includes("-v")) {
17
+ console.log(SERVER_VERSION);
18
+ process.exit(0);
19
+ }
14
20
  const XANOSCRIPT_DOCS_V2 = {
15
21
  readme: {
16
22
  file: "README.md",
@@ -357,7 +363,7 @@ function generateInitWorkspaceDoc() {
357
363
  // =============================================================================
358
364
  const server = new Server({
359
365
  name: "xano-developer-mcp",
360
- version: "1.0.0",
366
+ version: SERVER_VERSION,
361
367
  description: "MCP server for Xano Headless API documentation and XanoScript code validation",
362
368
  }, {
363
369
  capabilities: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xano/developer-mcp",
3
- "version": "1.0.7",
3
+ "version": "1.0.8",
4
4
  "description": "MCP server for Xano Headless API documentation and XanoScript code validation",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -18,6 +18,157 @@ Event-driven handlers that execute in response to system events. Triggers allow
18
18
 
19
19
  ---
20
20
 
21
+ ## Predefined Input Blocks
22
+
23
+ Each trigger type has a **predefined read-only input block**. These input structures are automatically provided by the system and **cannot be modified**. When creating a trigger, use the predefined input block as-is.
24
+
25
+ ### Table Trigger Input
26
+
27
+ ```xs
28
+ input {
29
+ json new
30
+ json old
31
+ enum action {
32
+ values = ["insert", "update", "delete", "truncate"]
33
+ }
34
+
35
+ text datasource
36
+ }
37
+ ```
38
+
39
+ | Field | Type | Description |
40
+ |-------|------|-------------|
41
+ | `new` | json | The new record data (after insert/update) |
42
+ | `old` | json | The old record data (before update/delete) |
43
+ | `action` | enum | The action that triggered: `insert`, `update`, `delete`, or `truncate` |
44
+ | `datasource` | text | The datasource name where the change occurred |
45
+
46
+ ### Agent Trigger Input
47
+
48
+ ```xs
49
+ input {
50
+ object toolset {
51
+ schema {
52
+ int id
53
+ text name
54
+ text instructions
55
+ }
56
+ }
57
+
58
+ object[] tools {
59
+ schema {
60
+ int id
61
+ text name
62
+ text instructions
63
+ }
64
+ }
65
+ }
66
+ ```
67
+
68
+ | Field | Type | Description |
69
+ |-------|------|-------------|
70
+ | `toolset` | object | The toolset configuration with id, name, and instructions |
71
+ | `tools` | object[] | Array of available tools with their id, name, and instructions |
72
+
73
+ ### MCP Server Trigger Input
74
+
75
+ ```xs
76
+ input {
77
+ object toolset {
78
+ schema {
79
+ int id
80
+ text name
81
+ text instructions
82
+ }
83
+ }
84
+
85
+ object[] tools {
86
+ schema {
87
+ int id
88
+ text name
89
+ text instructions
90
+ }
91
+ }
92
+ }
93
+ ```
94
+
95
+ | Field | Type | Description |
96
+ |-------|------|-------------|
97
+ | `toolset` | object | The toolset configuration with id, name, and instructions |
98
+ | `tools` | object[] | Array of available tools with their id, name, and instructions |
99
+
100
+ ### Workspace Trigger Input
101
+
102
+ ```xs
103
+ input {
104
+ object to_branch {
105
+ schema {
106
+ int id
107
+ text label
108
+ }
109
+ }
110
+
111
+ object from_branch {
112
+ schema {
113
+ int id
114
+ text label
115
+ }
116
+ }
117
+
118
+ enum action {
119
+ values = ["branch_live", "branch_merge", "branch_new"]
120
+ }
121
+ }
122
+ ```
123
+
124
+ | Field | Type | Description |
125
+ |-------|------|-------------|
126
+ | `to_branch` | object | The target branch with id and label |
127
+ | `from_branch` | object | The source branch with id and label |
128
+ | `action` | enum | The branch action: `branch_live`, `branch_merge`, or `branch_new` |
129
+
130
+ ### Realtime Trigger Input
131
+
132
+ ```xs
133
+ input {
134
+ enum action {
135
+ values = ["message", "join"]
136
+ }
137
+
138
+ text channel
139
+ object client {
140
+ schema {
141
+ json extras
142
+ object permissions {
143
+ schema {
144
+ int dbo_id
145
+ text row_id
146
+ }
147
+ }
148
+ }
149
+ }
150
+
151
+ object options {
152
+ schema {
153
+ bool authenticated
154
+ text channel
155
+ }
156
+ }
157
+
158
+ json payload
159
+ }
160
+ ```
161
+
162
+ | Field | Type | Description |
163
+ |-------|------|-------------|
164
+ | `action` | enum | The event type: `message` or `join` |
165
+ | `channel` | text | The channel name |
166
+ | `client` | object | Client information including extras and permissions |
167
+ | `options` | object | Channel options including authentication status |
168
+ | `payload` | json | The message payload data |
169
+
170
+ ---
171
+
21
172
  ## Table Trigger
22
173
 
23
174
  Executes when database table records are inserted, updated, deleted, or truncated.
@@ -33,8 +184,14 @@ table_trigger "<name>" {
33
184
  description = "Description of this trigger"
34
185
  tags = ["tag1", "tag2"]
35
186
 
187
+ // Predefined input block - read-only, do not modify
36
188
  input {
37
- // Define input parameters
189
+ json new
190
+ json old
191
+ enum action {
192
+ values = ["insert", "update", "delete", "truncate"]
193
+ }
194
+ text datasource
38
195
  }
39
196
 
40
197
  stack {
@@ -50,7 +207,7 @@ table_trigger "<name>" {
50
207
  | Clause | Description |
51
208
  |--------|-------------|
52
209
  | `table` | The database table name to monitor |
53
- | `input` | Input parameter definitions |
210
+ | `input` | Predefined input block (read-only) |
54
211
  | `stack` | Logic to execute when triggered |
55
212
 
56
213
  ### Optional Clauses
@@ -83,15 +240,24 @@ table_trigger "audit_user_changes" {
83
240
  description = "Log all changes to user records"
84
241
  datasources = ["main_db"]
85
242
 
243
+ // Input block is predefined and read-only - do not modify
86
244
  input {
245
+ json new
246
+ json old
247
+ enum action {
248
+ values = ["insert", "update", "delete", "truncate"]
249
+ }
250
+ text datasource
87
251
  }
88
252
 
89
253
  stack {
90
254
  db.add "audit_log" {
91
255
  data = {
92
256
  table_name: "user",
93
- action: $trigger.action,
94
- record_id: $trigger.record.id,
257
+ action: $input.action,
258
+ old_data: $input.old,
259
+ new_data: $input.new,
260
+ datasource: $input.datasource,
95
261
  timestamp: now
96
262
  }
97
263
  }
@@ -117,8 +283,30 @@ realtime_trigger "<name>" {
117
283
  description = "Description of this trigger"
118
284
  tags = ["tag1", "tag2"]
119
285
 
286
+ // Predefined input block - read-only, do not modify
120
287
  input {
121
- // Define input parameters
288
+ enum action {
289
+ values = ["message", "join"]
290
+ }
291
+ text channel
292
+ object client {
293
+ schema {
294
+ json extras
295
+ object permissions {
296
+ schema {
297
+ int dbo_id
298
+ text row_id
299
+ }
300
+ }
301
+ }
302
+ }
303
+ object options {
304
+ schema {
305
+ bool authenticated
306
+ text channel
307
+ }
308
+ }
309
+ json payload
122
310
  }
123
311
 
124
312
  stack {
@@ -136,7 +324,7 @@ realtime_trigger "<name>" {
136
324
  | Clause | Description |
137
325
  |--------|-------------|
138
326
  | `channel` | The real-time channel to monitor |
139
- | `input` | Input parameter definitions |
327
+ | `input` | Predefined input block (read-only) |
140
328
  | `stack` | Logic to execute when triggered |
141
329
  | `response` | Value to return to the client |
142
330
 
@@ -166,21 +354,43 @@ realtime_trigger "chat_message_handler" {
166
354
  active = true
167
355
  description = "Handle chat room messages and joins"
168
356
 
357
+ // Input block is predefined and read-only - do not modify
169
358
  input {
170
- text message filters=trim
359
+ enum action {
360
+ values = ["message", "join"]
361
+ }
362
+ text channel
363
+ object client {
364
+ schema {
365
+ json extras
366
+ object permissions {
367
+ schema {
368
+ int dbo_id
369
+ text row_id
370
+ }
371
+ }
372
+ }
373
+ }
374
+ object options {
375
+ schema {
376
+ bool authenticated
377
+ text channel
378
+ }
379
+ }
380
+ json payload
171
381
  }
172
382
 
173
383
  stack {
174
384
  conditional {
175
- if ($trigger.action == "join") {
385
+ if ($input.action == "join") {
176
386
  var $welcome { value = "Welcome to the chat!" }
177
387
  }
178
388
  else {
179
389
  db.add "chat_message" {
180
390
  data = {
181
- channel: "chat_room",
391
+ channel: $input.channel,
182
392
  user_id: $auth.id,
183
- message: $input.message,
393
+ message: $input.payload.message,
184
394
  timestamp: now
185
395
  }
186
396
  }
@@ -210,8 +420,23 @@ workspace_trigger "<name>" {
210
420
  description = "Description of this trigger"
211
421
  tags = ["tag1", "tag2"]
212
422
 
423
+ // Predefined input block - read-only, do not modify
213
424
  input {
214
- // Define input parameters
425
+ object to_branch {
426
+ schema {
427
+ int id
428
+ text label
429
+ }
430
+ }
431
+ object from_branch {
432
+ schema {
433
+ int id
434
+ text label
435
+ }
436
+ }
437
+ enum action {
438
+ values = ["branch_live", "branch_merge", "branch_new"]
439
+ }
215
440
  }
216
441
 
217
442
  stack {
@@ -226,7 +451,7 @@ workspace_trigger "<name>" {
226
451
 
227
452
  | Clause | Description |
228
453
  |--------|-------------|
229
- | `input` | Input parameter definitions |
454
+ | `input` | Predefined input block (read-only) |
230
455
  | `stack` | Logic to execute when triggered |
231
456
 
232
457
  ### Optional Clauses
@@ -256,7 +481,23 @@ workspace_trigger "branch_notification" {
256
481
  description = "Send notifications on branch events"
257
482
  tags = ["devops", "notifications"]
258
483
 
484
+ // Input block is predefined and read-only - do not modify
259
485
  input {
486
+ object to_branch {
487
+ schema {
488
+ int id
489
+ text label
490
+ }
491
+ }
492
+ object from_branch {
493
+ schema {
494
+ int id
495
+ text label
496
+ }
497
+ }
498
+ enum action {
499
+ values = ["branch_live", "branch_merge", "branch_new"]
500
+ }
260
501
  }
261
502
 
262
503
  stack {
@@ -265,8 +506,8 @@ workspace_trigger "branch_notification" {
265
506
  api_key = $env.RESEND_API_KEY
266
507
  to = "team@example.com"
267
508
  from = "system@example.com"
268
- subject = "Branch Event: " ~ $trigger.action
269
- message = "Branch '" ~ $trigger.branch_name ~ "' event: " ~ $trigger.action
509
+ subject = "Branch Event: " ~ $input.action
510
+ message = "Branch '" ~ $input.from_branch.label ~ "' -> '" ~ $input.to_branch.label ~ "' event: " ~ $input.action
270
511
  }
271
512
  }
272
513
 
@@ -291,8 +532,22 @@ agent_trigger "<name>" {
291
532
  docs = "Extended documentation for the trigger"
292
533
  tags = ["tag1", "tag2"]
293
534
 
535
+ // Predefined input block - read-only, do not modify
294
536
  input {
295
- // Define input parameters
537
+ object toolset {
538
+ schema {
539
+ int id
540
+ text name
541
+ text instructions
542
+ }
543
+ }
544
+ object[] tools {
545
+ schema {
546
+ int id
547
+ text name
548
+ text instructions
549
+ }
550
+ }
296
551
  }
297
552
 
298
553
  stack {
@@ -310,7 +565,7 @@ agent_trigger "<name>" {
310
565
  | Clause | Description |
311
566
  |--------|-------------|
312
567
  | `agent` | The AI agent name this trigger handles |
313
- | `input` | Input parameter definitions |
568
+ | `input` | Predefined input block (read-only) |
314
569
  | `stack` | Logic to execute when triggered |
315
570
  | `response` | Value to return |
316
571
 
@@ -341,21 +596,31 @@ agent_trigger "assistant_handler" {
341
596
  description = "Handle customer assistant agent connections"
342
597
  docs = "This trigger initializes the customer context when the agent connects"
343
598
 
599
+ // Input block is predefined and read-only - do not modify
344
600
  input {
345
- text session_id filters=trim
601
+ object toolset {
602
+ schema {
603
+ int id
604
+ text name
605
+ text instructions
606
+ }
607
+ }
608
+ object[] tools {
609
+ schema {
610
+ int id
611
+ text name
612
+ text instructions
613
+ }
614
+ }
346
615
  }
347
616
 
348
617
  stack {
349
- db.get "customer" {
350
- field_name = "session_id"
351
- field_value = $input.session_id
352
- } as $customer
353
-
618
+ // Access toolset and tools information from the predefined input
354
619
  var $context {
355
620
  value = {
356
- customer_name: $customer.name,
357
- customer_tier: $customer.tier,
358
- history: $customer.support_history
621
+ toolset_name: $input.toolset.name,
622
+ toolset_instructions: $input.toolset.instructions,
623
+ available_tools: $input.tools
359
624
  }
360
625
  }
361
626
  }
@@ -382,8 +647,22 @@ mcp_server_trigger "<name>" {
382
647
  description = "Description of this trigger"
383
648
  tags = ["tag1", "tag2"]
384
649
 
650
+ // Predefined input block - read-only, do not modify
385
651
  input {
386
- // Define input parameters
652
+ object toolset {
653
+ schema {
654
+ int id
655
+ text name
656
+ text instructions
657
+ }
658
+ }
659
+ object[] tools {
660
+ schema {
661
+ int id
662
+ text name
663
+ text instructions
664
+ }
665
+ }
387
666
  }
388
667
 
389
668
  stack {
@@ -401,7 +680,7 @@ mcp_server_trigger "<name>" {
401
680
  | Clause | Description |
402
681
  |--------|-------------|
403
682
  | `mcp_server` | The MCP server name this trigger handles |
404
- | `input` | Input parameter definitions |
683
+ | `input` | Predefined input block (read-only) |
405
684
  | `stack` | Logic to execute when triggered |
406
685
  | `response` | Value to return to the MCP client |
407
686
 
@@ -431,25 +710,31 @@ mcp_server_trigger "database_tool_handler" {
431
710
  description = "Handle database tool calls from MCP clients"
432
711
  tags = ["mcp", "database"]
433
712
 
713
+ // Input block is predefined and read-only - do not modify
434
714
  input {
435
- text operation filters=trim
436
- object params
715
+ object toolset {
716
+ schema {
717
+ int id
718
+ text name
719
+ text instructions
720
+ }
721
+ }
722
+ object[] tools {
723
+ schema {
724
+ int id
725
+ text name
726
+ text instructions
727
+ }
728
+ }
437
729
  }
438
730
 
439
731
  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"} }
732
+ // Access toolset and tools information from the predefined input
733
+ var $result {
734
+ value = {
735
+ server: $input.toolset.name,
736
+ instructions: $input.toolset.instructions,
737
+ tool_count: count($input.tools)
453
738
  }
454
739
  }
455
740
  }
@@ -471,7 +756,14 @@ table_trigger "safe_audit" {
471
756
  table = "sensitive_data"
472
757
  actions = {insert: true, update: true, delete: true, truncate: false}
473
758
 
759
+ // Input block is predefined and read-only
474
760
  input {
761
+ json new
762
+ json old
763
+ enum action {
764
+ values = ["insert", "update", "delete", "truncate"]
765
+ }
766
+ text datasource
475
767
  }
476
768
 
477
769
  stack {
@@ -479,7 +771,9 @@ table_trigger "safe_audit" {
479
771
  try {
480
772
  db.add "audit_log" {
481
773
  data = {
482
- action: $trigger.action,
774
+ action: $input.action,
775
+ new_data: $input.new,
776
+ old_data: $input.old,
483
777
  timestamp: now
484
778
  }
485
779
  }
@@ -499,19 +793,26 @@ table_trigger "conditional_notification" {
499
793
  table = "order"
500
794
  actions = {insert: true, update: false, delete: false, truncate: false}
501
795
 
796
+ // Input block is predefined and read-only
502
797
  input {
798
+ json new
799
+ json old
800
+ enum action {
801
+ values = ["insert", "update", "delete", "truncate"]
802
+ }
803
+ text datasource
503
804
  }
504
805
 
505
806
  stack {
506
807
  conditional {
507
- if ($trigger.record.total > 1000) {
808
+ if ($input.new.total > 1000) {
508
809
  util.send_email {
509
810
  service_provider = "resend"
510
811
  api_key = $env.RESEND_API_KEY
511
812
  to = "sales@example.com"
512
813
  from = "system@example.com"
513
814
  subject = "High Value Order"
514
- message = "Order #" ~ $trigger.record.id ~ " for $" ~ $trigger.record.total
815
+ message = "Order #" ~ $input.new.id ~ " for $" ~ $input.new.total
515
816
  }
516
817
  }
517
818
  }
@@ -523,10 +824,11 @@ table_trigger "conditional_notification" {
523
824
 
524
825
  ## Best Practices
525
826
 
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
827
+ 1. **Use predefined input blocks as-is** - Each trigger type has a read-only input block that cannot be modified; use the exact structure provided
828
+ 2. **Use descriptive names** - Indicate the event and action: `user_audit_log`, `chat_message_handler`
829
+ 3. **Handle errors gracefully** - Use try_catch to prevent trigger failures from affecting the main operation
830
+ 4. **Keep triggers lightweight** - Offload heavy processing to functions or tasks
831
+ 5. **Set appropriate history** - Use `history = false` for high-frequency triggers to save storage
832
+ 6. **Use tags** - Organize triggers with meaningful tags for easier management
833
+ 7. **Document with description** - Always provide a description explaining the trigger's purpose
834
+ 8. **Test thoroughly** - Triggers execute automatically, so ensure they handle edge cases