@xano/developer-mcp 1.0.7 → 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
@@ -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
@@ -168,6 +180,7 @@ Retrieves XanoScript programming language documentation with context-aware suppo
168
180
  | `functions` | Reusable function stacks with inputs and responses |
169
181
  | `apis` | HTTP endpoint definitions with authentication and CRUD patterns |
170
182
  | `tasks` | Scheduled and cron jobs |
183
+ | `triggers` | Event-driven handlers (table, realtime, workspace, agent, MCP) |
171
184
  | `database` | All db.* operations: query, get, add, edit, patch, delete |
172
185
  | `agents` | AI agent configuration with LLM providers and tools |
173
186
  | `tools` | AI tools for agents and MCP servers |
@@ -176,6 +189,13 @@ Retrieves XanoScript programming language documentation with context-aware suppo
176
189
  | `integrations` | Cloud storage, Redis, security, and external APIs |
177
190
  | `frontend` | Static frontend development and deployment |
178
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 |
179
199
 
180
200
  **Examples:**
181
201
  ```
@@ -222,6 +242,7 @@ The server also exposes XanoScript documentation as MCP resources for direct acc
222
242
  | `xanoscript://docs/functions` | Reusable function stacks |
223
243
  | `xanoscript://docs/apis` | HTTP endpoint definitions |
224
244
  | `xanoscript://docs/tasks` | Scheduled and cron jobs |
245
+ | `xanoscript://docs/triggers` | Event-driven handlers |
225
246
  | `xanoscript://docs/database` | Database operations |
226
247
  | `xanoscript://docs/agents` | AI agent configuration |
227
248
  | `xanoscript://docs/tools` | AI tools for agents |
@@ -230,6 +251,13 @@ The server also exposes XanoScript documentation as MCP resources for direct acc
230
251
  | `xanoscript://docs/integrations` | External service integrations |
231
252
  | `xanoscript://docs/frontend` | Static frontend development |
232
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 |
233
261
 
234
262
  ## npm Scripts
235
263
 
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",
@@ -92,6 +98,41 @@ const XANOSCRIPT_DOCS_V2 = {
92
98
  applyTo: ["ephemeral/**/*.xs"],
93
99
  description: "Temporary test environments",
94
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
+ },
95
136
  };
96
137
  const XANO_OBJECT_TYPES = {
97
138
  function: {
@@ -357,7 +398,7 @@ function generateInitWorkspaceDoc() {
357
398
  // =============================================================================
358
399
  const server = new Server({
359
400
  name: "xano-developer-mcp",
360
- version: "1.0.0",
401
+ version: SERVER_VERSION,
361
402
  description: "MCP server for Xano Headless API documentation and XanoScript code validation",
362
403
  }, {
363
404
  capabilities: {
@@ -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.7",
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