@xano/developer-mcp 1.0.8 → 1.0.9

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
@@ -180,6 +180,7 @@ Retrieves XanoScript programming language documentation with context-aware suppo
180
180
  | `functions` | Reusable function stacks with inputs and responses |
181
181
  | `apis` | HTTP endpoint definitions with authentication and CRUD patterns |
182
182
  | `tasks` | Scheduled and cron jobs |
183
+ | `triggers` | Event-driven handlers (table, realtime, workspace, agent, MCP) |
183
184
  | `database` | All db.* operations: query, get, add, edit, patch, delete |
184
185
  | `agents` | AI agent configuration with LLM providers and tools |
185
186
  | `tools` | AI tools for agents and MCP servers |
@@ -188,6 +189,13 @@ Retrieves XanoScript programming language documentation with context-aware suppo
188
189
  | `integrations` | Cloud storage, Redis, security, and external APIs |
189
190
  | `frontend` | Static frontend development and deployment |
190
191
  | `ephemeral` | Temporary test environments |
192
+ | `addons` | Reusable subqueries for fetching related data |
193
+ | `debugging` | Logging, inspecting, and debugging XanoScript execution |
194
+ | `performance` | Performance optimization best practices |
195
+ | `realtime` | Real-time channels and events for push updates |
196
+ | `schema` | Runtime schema parsing and validation |
197
+ | `security` | Security best practices for authentication and authorization |
198
+ | `streaming` | Streaming data from files, requests, and responses |
191
199
 
192
200
  **Examples:**
193
201
  ```
@@ -234,6 +242,7 @@ The server also exposes XanoScript documentation as MCP resources for direct acc
234
242
  | `xanoscript://docs/functions` | Reusable function stacks |
235
243
  | `xanoscript://docs/apis` | HTTP endpoint definitions |
236
244
  | `xanoscript://docs/tasks` | Scheduled and cron jobs |
245
+ | `xanoscript://docs/triggers` | Event-driven handlers |
237
246
  | `xanoscript://docs/database` | Database operations |
238
247
  | `xanoscript://docs/agents` | AI agent configuration |
239
248
  | `xanoscript://docs/tools` | AI tools for agents |
@@ -242,6 +251,13 @@ The server also exposes XanoScript documentation as MCP resources for direct acc
242
251
  | `xanoscript://docs/integrations` | External service integrations |
243
252
  | `xanoscript://docs/frontend` | Static frontend development |
244
253
  | `xanoscript://docs/ephemeral` | Temporary test environments |
254
+ | `xanoscript://docs/addons` | Reusable subqueries for related data |
255
+ | `xanoscript://docs/debugging` | Logging and debugging tools |
256
+ | `xanoscript://docs/performance` | Performance optimization |
257
+ | `xanoscript://docs/realtime` | Real-time channels and events |
258
+ | `xanoscript://docs/schema` | Runtime schema parsing |
259
+ | `xanoscript://docs/security` | Security best practices |
260
+ | `xanoscript://docs/streaming` | Data streaming operations |
245
261
 
246
262
  ## npm Scripts
247
263
 
package/dist/index.js CHANGED
@@ -98,6 +98,41 @@ const XANOSCRIPT_DOCS_V2 = {
98
98
  applyTo: ["ephemeral/**/*.xs"],
99
99
  description: "Temporary test environments",
100
100
  },
101
+ addons: {
102
+ file: "addons.md",
103
+ applyTo: ["addons/*.xs", "functions/**/*.xs", "apis/**/*.xs"],
104
+ description: "Reusable subqueries for fetching related data",
105
+ },
106
+ debugging: {
107
+ file: "debugging.md",
108
+ applyTo: ["**/*.xs"],
109
+ description: "Logging, inspecting, and debugging XanoScript execution",
110
+ },
111
+ performance: {
112
+ file: "performance.md",
113
+ applyTo: ["functions/**/*.xs", "apis/**/*.xs"],
114
+ description: "Performance optimization best practices",
115
+ },
116
+ realtime: {
117
+ file: "realtime.md",
118
+ applyTo: ["functions/**/*.xs", "apis/**/*.xs", "triggers/**/*.xs"],
119
+ description: "Real-time channels and events for push updates",
120
+ },
121
+ schema: {
122
+ file: "schema.md",
123
+ applyTo: ["functions/**/*.xs", "apis/**/*.xs"],
124
+ description: "Runtime schema parsing and validation",
125
+ },
126
+ security: {
127
+ file: "security.md",
128
+ applyTo: ["functions/**/*.xs", "apis/**/*.xs"],
129
+ description: "Security best practices for authentication and authorization",
130
+ },
131
+ streaming: {
132
+ file: "streaming.md",
133
+ applyTo: ["functions/**/*.xs", "apis/**/*.xs"],
134
+ description: "Streaming data from files, requests, and responses",
135
+ },
101
136
  };
102
137
  const XANO_OBJECT_TYPES = {
103
138
  function: {
@@ -53,8 +53,15 @@ ${formatRow("task_workflow", "AI workflow for creating tasks")}
53
53
 
54
54
  | Keyword | Aliases | Description |
55
55
  |---------|---------|-------------|
56
+ ${formatRow("addons", "Reusable subqueries for related data")}
57
+ ${formatRow("debugging", "Logging and debugging tools")}
56
58
  ${formatRow("frontend", "Frontend development with Xano")}
57
59
  ${formatRow("lovable", "Building from Lovable-generated websites")}
60
+ ${formatRow("performance", "Performance optimization best practices")}
61
+ ${formatRow("realtime", "Real-time channels and events")}
62
+ ${formatRow("schema", "Runtime schema parsing and validation")}
63
+ ${formatRow("security", "Security best practices")}
64
+ ${formatRow("streaming", "Streaming data from files and responses")}
58
65
  ${formatRow("testing", "Unit testing XanoScript code")}
59
66
  ${formatRow("tips", "Tips and tricks")}
60
67
  ${formatRow("ephemeral", "Ephemeral environment setup")}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xano/developer-mcp",
3
- "version": "1.0.8",
3
+ "version": "1.0.9",
4
4
  "description": "MCP server for Xano Headless API documentation and XanoScript code validation",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -105,19 +105,52 @@ This helps AI tools apply the correct documentation based on the file being edit
105
105
 
106
106
  Use `xanoscript_docs({ keyword: "<keyword>" })` to retrieve documentation.
107
107
 
108
+ ### Core Language
108
109
  | Topic | Keyword | Description |
109
110
  |-------|---------|-------------|
110
- | Syntax Reference | `syntax` | Expressions, operators, filters |
111
+ | Syntax Reference | `syntax` | Expressions, operators, filters, system variables |
111
112
  | Types & Inputs | `input` | Data types, validation, input blocks |
113
+ | Functions | `function` | Reusable function stacks, async, loops |
114
+ | Schema | `schema` | Runtime schema parsing and validation |
115
+
116
+ ### Data
117
+ | Topic | Keyword | Description |
118
+ |-------|---------|-------------|
112
119
  | Tables | `table` | Database schema definitions |
113
- | Functions | `function` | Reusable function stacks |
120
+ | Database Operations | `db_query` | Query, add, edit, delete, bulk operations |
121
+ | Addons | `addon` | Reusable subqueries for related data |
122
+ | Streaming | `streaming` | Stream processing for large files |
123
+
124
+ ### APIs & Endpoints
125
+ | Topic | Keyword | Description |
126
+ |-------|---------|-------------|
114
127
  | APIs | `api_query` | HTTP endpoint definitions |
115
128
  | Tasks | `task` | Scheduled jobs |
116
- | Triggers | `trigger` | Event-driven handlers (table, realtime, workspace, agent, MCP) |
117
- | Database Operations | `db_query` | Query, add, edit, delete |
129
+ | Triggers | `trigger` | Event-driven handlers |
130
+ | Realtime | `realtime` | Push events and channels |
131
+
132
+ ### AI & Agents
133
+ | Topic | Keyword | Description |
134
+ |-------|---------|-------------|
118
135
  | Agents | `agent` | AI agent configuration |
119
136
  | Tools | `tool` | AI tools for agents |
120
137
  | MCP Servers | `mcp_server` | Model Context Protocol servers |
138
+
139
+ ### Integrations
140
+ | Topic | Keyword | Description |
141
+ |-------|---------|-------------|
142
+ | Integrations | `integrations` | Cloud storage, search, Redis, zip, Lambda |
143
+
144
+ ### Development
145
+ | Topic | Keyword | Description |
146
+ |-------|---------|-------------|
121
147
  | Testing | `testing` | Unit tests and mocking |
148
+ | Debugging | `debugging` | Logging and inspection tools |
122
149
  | Frontend | `frontend` | Static frontend development |
123
- | Ephemeral | `ephemeral` | Temporary environments
150
+ | Ephemeral | `ephemeral` | Temporary environments |
151
+
152
+ ### Best Practices
153
+ | Topic | Keyword | Description |
154
+ |-------|---------|-------------|
155
+ | Performance | `performance` | Query optimization, caching, parallelism |
156
+ | Security | `security` | Authentication, authorization, encryption |
@@ -0,0 +1,285 @@
1
+ ---
2
+ applyTo: "addons/*.xs, functions/**/*.xs, apis/**/*.xs"
3
+ ---
4
+
5
+ # Addons
6
+
7
+ Reusable subqueries for fetching related data in database queries.
8
+
9
+ ## Quick Reference
10
+
11
+ ```xs
12
+ addon "<name>" {
13
+ description = "What this addon fetches"
14
+ input {
15
+ <type> <name>
16
+ }
17
+ stack {
18
+ // Query logic
19
+ }
20
+ response = $result
21
+ }
22
+ ```
23
+
24
+ ---
25
+
26
+ ## Basic Structure
27
+
28
+ Addons define reusable data fetching logic that can be attached to query results.
29
+
30
+ ```xs
31
+ addon "comment_count" {
32
+ description = "Count of comments for a post"
33
+ input {
34
+ int post_id
35
+ }
36
+ stack {
37
+ db.query "comment" {
38
+ where = $db.comment.post_id == $input.post_id
39
+ return = { type: "count" }
40
+ } as $count
41
+ }
42
+ response = $count
43
+ }
44
+ ```
45
+
46
+ ---
47
+
48
+ ## Using Addons in Queries
49
+
50
+ ### In db.query
51
+
52
+ ```xs
53
+ db.query "post" {
54
+ where = $db.post.author_id == $auth.id
55
+ addon = [
56
+ {
57
+ name: "comment_count",
58
+ input: { post_id: $output.id },
59
+ as: "items.comment_count"
60
+ }
61
+ ]
62
+ } as $posts
63
+ ```
64
+
65
+ ### Result Structure
66
+
67
+ ```json
68
+ {
69
+ "items": [
70
+ {
71
+ "id": 1,
72
+ "title": "My Post",
73
+ "comment_count": 42
74
+ }
75
+ ]
76
+ }
77
+ ```
78
+
79
+ ### Multiple Addons
80
+
81
+ ```xs
82
+ db.query "post" {
83
+ where = $db.post.is_published == true
84
+ addon = [
85
+ {
86
+ name: "comment_count",
87
+ input: { post_id: $output.id },
88
+ as: "items.comments"
89
+ },
90
+ {
91
+ name: "like_count",
92
+ input: { post_id: $output.id },
93
+ as: "items.likes"
94
+ },
95
+ {
96
+ name: "author_details",
97
+ input: { user_id: $output.author_id },
98
+ as: "items.author"
99
+ }
100
+ ]
101
+ } as $posts
102
+ ```
103
+
104
+ ---
105
+
106
+ ## Addon Examples
107
+
108
+ ### Related List
109
+
110
+ ```xs
111
+ addon "recent_comments" {
112
+ description = "Get recent comments for a post"
113
+ input {
114
+ int post_id
115
+ int limit?=5
116
+ }
117
+ stack {
118
+ db.query "comment" {
119
+ where = $db.comment.post_id == $input.post_id
120
+ sort = { created_at: "desc" }
121
+ return = {
122
+ type: "list",
123
+ paging: { per_page: $input.limit }
124
+ }
125
+ } as $comments
126
+ }
127
+ response = $comments.items
128
+ }
129
+ ```
130
+
131
+ ### Aggregation
132
+
133
+ ```xs
134
+ addon "order_stats" {
135
+ description = "Order statistics for a user"
136
+ input {
137
+ int user_id
138
+ }
139
+ stack {
140
+ db.query "order" {
141
+ 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
+ }
150
+ }
151
+ }
152
+ response = $stats
153
+ }
154
+ ```
155
+
156
+ ### Nested Object
157
+
158
+ ```xs
159
+ addon "full_address" {
160
+ description = "Get formatted address for a user"
161
+ input {
162
+ int user_id
163
+ }
164
+ 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
+ }
185
+ }
186
+ }
187
+ response = $formatted
188
+ }
189
+ ```
190
+
191
+ ### Boolean Check
192
+
193
+ ```xs
194
+ addon "has_premium" {
195
+ description = "Check if user has premium subscription"
196
+ input {
197
+ int user_id
198
+ }
199
+ 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
206
+ }
207
+ response = $has_premium
208
+ }
209
+ ```
210
+
211
+ ---
212
+
213
+ ## addon.call
214
+
215
+ Call an addon directly from a function or API.
216
+
217
+ ```xs
218
+ addon.call "comment_count" {
219
+ input = { post_id: $input.post_id }
220
+ } as $count
221
+ ```
222
+
223
+ ### Use Cases
224
+
225
+ ```xs
226
+ // Get stats for single record
227
+ addon.call "order_stats" {
228
+ input = { user_id: $auth.id }
229
+ } as $my_stats
230
+
231
+ // Conditional addon call
232
+ conditional {
233
+ if ($input.include_stats) {
234
+ addon.call "detailed_stats" {
235
+ input = { entity_id: $entity.id }
236
+ } as $stats
237
+ }
238
+ }
239
+ ```
240
+
241
+ ---
242
+
243
+ ## Database Addon Attributes
244
+
245
+ Use `dbAddonAttr` for computed fields in queries.
246
+
247
+ ```xs
248
+ db.query "product" {
249
+ eval = {
250
+ discount_price: dbAddonAttr("calculate_discount", { product_id: $db.product.id })
251
+ }
252
+ } as $products
253
+ ```
254
+
255
+ ---
256
+
257
+ ## Organization
258
+
259
+ ### File Structure
260
+
261
+ ```
262
+ addons/
263
+ ├── comment_count.xs
264
+ ├── like_count.xs
265
+ ├── author_details.xs
266
+ ├── order_stats.xs
267
+ └── has_premium.xs
268
+ ```
269
+
270
+ ### Naming Conventions
271
+
272
+ - Use descriptive names: `comment_count`, not `cc`
273
+ - Use verb_noun for actions: `calculate_discount`
274
+ - Use has_ prefix for boolean checks: `has_premium`
275
+
276
+ ---
277
+
278
+ ## Best Practices
279
+
280
+ 1. **Keep addons focused** - One purpose per addon
281
+ 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
@@ -317,6 +317,89 @@ agent "Research Assistant" {
317
317
 
318
318
  ---
319
319
 
320
+ ## External MCP Tools
321
+
322
+ Integrate external MCP (Model Context Protocol) servers to extend agent capabilities.
323
+
324
+ ### ai.external.mcp.tool.list
325
+
326
+ List available tools from an external MCP server.
327
+
328
+ ```xs
329
+ ai.external.mcp.tool.list {
330
+ server_url = "https://mcp.example.com"
331
+ api_key = $env.MCP_API_KEY
332
+ } as $tools
333
+
334
+ // $tools = [
335
+ // { name: "search_web", description: "Search the web", inputSchema: {...} },
336
+ // { name: "fetch_page", description: "Fetch webpage content", inputSchema: {...} }
337
+ // ]
338
+ ```
339
+
340
+ ### ai.external.mcp.tool.run
341
+
342
+ Execute a tool on an external MCP server.
343
+
344
+ ```xs
345
+ ai.external.mcp.tool.run {
346
+ server_url = "https://mcp.example.com"
347
+ api_key = $env.MCP_API_KEY
348
+ tool_name = "search_web"
349
+ arguments = { query: "latest AI news" }
350
+ } as $result
351
+ ```
352
+
353
+ ### ai.external.mcp.server_details
354
+
355
+ Get metadata about an external MCP server.
356
+
357
+ ```xs
358
+ ai.external.mcp.server_details {
359
+ server_url = "https://mcp.example.com"
360
+ api_key = $env.MCP_API_KEY
361
+ } as $details
362
+
363
+ // $details = {
364
+ // name: "Web Tools",
365
+ // version: "1.0.0",
366
+ // capabilities: ["tools", "resources"],
367
+ // tools: [...]
368
+ // }
369
+ ```
370
+
371
+ ### Using External Tools in Agents
372
+
373
+ ```xs
374
+ agent "Research Agent" {
375
+ canonical = "research-v1"
376
+ llm = {
377
+ type: "openai"
378
+ api_key: "{{ $env.OPENAI_API_KEY }}"
379
+ model: "gpt-5"
380
+ system_prompt: """
381
+ You are a research assistant with access to web search
382
+ and document analysis tools. Use them to find and analyze information.
383
+ """
384
+ prompt: "{{ $args.query }}"
385
+ max_steps: 8
386
+ }
387
+ tools = [
388
+ { name: "search_web" },
389
+ { name: "fetch_page" },
390
+ { name: "summarize_document" }
391
+ ]
392
+ external_mcp_servers = [
393
+ {
394
+ url: "{{ $env.WEB_MCP_URL }}",
395
+ api_key: "{{ $env.WEB_MCP_KEY }}"
396
+ }
397
+ ]
398
+ }
399
+ ```
400
+
401
+ ---
402
+
320
403
  ## Best Practices
321
404
 
322
405
  1. **Clear system prompts** - Define persona, capabilities, and constraints
@@ -325,3 +408,4 @@ agent "Research Assistant" {
325
408
  4. **Don't repeat tool descriptions** - They're auto-injected
326
409
  5. **Use environment variables** - Never hardcode API keys
327
410
  6. **Test with xano-free first** - Free for development
411
+ 7. **Validate external MCP servers** - Check server_details before using