@xano/developer-mcp 1.0.52 → 1.0.54

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.
@@ -26,6 +26,12 @@ export declare function handleCliDocs(args: CliDocsArgs): string;
26
26
  */
27
27
  export declare const cliDocsToolDefinition: {
28
28
  name: string;
29
+ annotations: {
30
+ readOnlyHint: boolean;
31
+ destructiveHint: boolean;
32
+ idempotentHint: boolean;
33
+ openWorldHint: boolean;
34
+ };
29
35
  description: string;
30
36
  inputSchema: {
31
37
  type: string;
@@ -59,6 +59,12 @@ export function handleCliDocs(args) {
59
59
  */
60
60
  export const cliDocsToolDefinition = {
61
61
  name: "cli_docs",
62
+ annotations: {
63
+ readOnlyHint: true,
64
+ destructiveHint: false,
65
+ idempotentHint: true,
66
+ openWorldHint: false,
67
+ },
62
68
  description: `Get documentation for the Xano CLI. Use this to understand how to use the CLI for local development, code sync, and XanoScript execution.
63
69
 
64
70
  ## Topics
@@ -26,6 +26,12 @@ export declare function handleMetaApiDocs(args: MetaApiDocsArgs): string;
26
26
  */
27
27
  export declare const metaApiDocsToolDefinition: {
28
28
  name: string;
29
+ annotations: {
30
+ readOnlyHint: boolean;
31
+ destructiveHint: boolean;
32
+ idempotentHint: boolean;
33
+ openWorldHint: boolean;
34
+ };
29
35
  description: string;
30
36
  inputSchema: {
31
37
  type: string;
@@ -77,6 +77,12 @@ export function handleMetaApiDocs(args) {
77
77
  */
78
78
  export const metaApiDocsToolDefinition = {
79
79
  name: "meta_api_docs",
80
+ annotations: {
81
+ readOnlyHint: true,
82
+ destructiveHint: false,
83
+ idempotentHint: true,
84
+ openWorldHint: false,
85
+ },
80
86
  description: `Get documentation for Xano's Meta API. Use this to understand how to programmatically manage Xano workspaces, databases, APIs, functions, agents, and more.
81
87
 
82
88
  ## Topics
@@ -42,6 +42,12 @@ export { validateXanoscriptToolDefinition, xanoscriptDocsToolDefinition, mcpVers
42
42
  */
43
43
  export declare const toolDefinitions: ({
44
44
  name: string;
45
+ annotations: {
46
+ readOnlyHint: boolean;
47
+ destructiveHint: boolean;
48
+ idempotentHint: boolean;
49
+ openWorldHint: boolean;
50
+ };
45
51
  description: string;
46
52
  inputSchema: {
47
53
  type: string;
@@ -50,6 +56,12 @@ export declare const toolDefinitions: ({
50
56
  };
51
57
  } | {
52
58
  name: string;
59
+ annotations: {
60
+ readOnlyHint: boolean;
61
+ destructiveHint: boolean;
62
+ idempotentHint: boolean;
63
+ openWorldHint: boolean;
64
+ };
53
65
  description: string;
54
66
  inputSchema: {
55
67
  type: string;
@@ -36,6 +36,12 @@ export declare function mcpVersion(): McpVersionResult;
36
36
  export declare function mcpVersionTool(): ToolResult;
37
37
  export declare const mcpVersionToolDefinition: {
38
38
  name: string;
39
+ annotations: {
40
+ readOnlyHint: boolean;
41
+ destructiveHint: boolean;
42
+ idempotentHint: boolean;
43
+ openWorldHint: boolean;
44
+ };
39
45
  description: string;
40
46
  inputSchema: {
41
47
  type: string;
@@ -84,6 +84,12 @@ export function mcpVersionTool() {
84
84
  // =============================================================================
85
85
  export const mcpVersionToolDefinition = {
86
86
  name: "mcp_version",
87
+ annotations: {
88
+ readOnlyHint: true,
89
+ destructiveHint: false,
90
+ idempotentHint: true,
91
+ openWorldHint: false,
92
+ },
87
93
  description: "Get the current version of the Xano Developer MCP server. " +
88
94
  "Returns the version string from package.json.",
89
95
  inputSchema: {
@@ -109,6 +109,12 @@ export declare function validateXanoscript(args: ValidateXanoscriptArgs): Valida
109
109
  export declare function validateXanoscriptTool(args: ValidateXanoscriptArgs): ToolResult;
110
110
  export declare const validateXanoscriptToolDefinition: {
111
111
  name: string;
112
+ annotations: {
113
+ readOnlyHint: boolean;
114
+ destructiveHint: boolean;
115
+ idempotentHint: boolean;
116
+ openWorldHint: boolean;
117
+ };
112
118
  description: string;
113
119
  inputSchema: {
114
120
  type: string;
@@ -388,6 +388,12 @@ export function validateXanoscriptTool(args) {
388
388
  // =============================================================================
389
389
  export const validateXanoscriptToolDefinition = {
390
390
  name: "validate_xanoscript",
391
+ annotations: {
392
+ readOnlyHint: true,
393
+ destructiveHint: false,
394
+ idempotentHint: true,
395
+ openWorldHint: false,
396
+ },
391
397
  description: "Validate XanoScript code for syntax errors. Supports multiple input methods:\n" +
392
398
  "- code: Raw XanoScript code as a string\n" +
393
399
  "- file_path: Path to a single .xs file (easier than escaping code!)\n" +
@@ -50,11 +50,18 @@ export declare function xanoscriptDocsTool(args?: XanoscriptDocsArgs): ToolResul
50
50
  export declare const xanoscriptDocsToolDefinition: {
51
51
  name: string;
52
52
  description: string;
53
+ annotations: {
54
+ readOnlyHint: boolean;
55
+ destructiveHint: boolean;
56
+ idempotentHint: boolean;
57
+ openWorldHint: boolean;
58
+ };
53
59
  inputSchema: {
54
60
  type: string;
55
61
  properties: {
56
62
  topic: {
57
63
  type: string;
64
+ enum: string[];
58
65
  description: string;
59
66
  };
60
67
  file_path: {
@@ -66,6 +73,13 @@ export declare const xanoscriptDocsToolDefinition: {
66
73
  enum: string[];
67
74
  description: string;
68
75
  };
76
+ exclude_topics: {
77
+ type: string;
78
+ items: {
79
+ type: string;
80
+ };
81
+ description: string;
82
+ };
69
83
  };
70
84
  required: never[];
71
85
  };
@@ -7,7 +7,7 @@
7
7
  import { readFileSync } from "fs";
8
8
  import { dirname, join } from "path";
9
9
  import { fileURLToPath } from "url";
10
- import { readXanoscriptDocsV2, getTopicDescriptions, } from "../xanoscript.js";
10
+ import { readXanoscriptDocsV2, getTopicNames, getTopicDescriptions, } from "../xanoscript.js";
11
11
  // =============================================================================
12
12
  // Path Resolution
13
13
  // =============================================================================
@@ -104,12 +104,20 @@ export const xanoscriptDocsToolDefinition = {
104
104
  description: "Get XanoScript programming language documentation for AI code generation. " +
105
105
  "Call without parameters for overview (README). " +
106
106
  "Use 'topic' for specific documentation, or 'file_path' for context-aware docs based on the file you're editing. " +
107
- "Use mode='quick_reference' for compact syntax cheatsheet (recommended for context efficiency).",
107
+ "Use mode='quick_reference' for compact syntax cheatsheet (recommended for context efficiency). " +
108
+ "file_path mode defaults to 'quick_reference' to reduce context size; use mode='full' to get complete docs.",
109
+ annotations: {
110
+ readOnlyHint: true,
111
+ destructiveHint: false,
112
+ idempotentHint: true,
113
+ openWorldHint: false,
114
+ },
108
115
  inputSchema: {
109
116
  type: "object",
110
117
  properties: {
111
118
  topic: {
112
119
  type: "string",
120
+ enum: getTopicNames(),
113
121
  description: "Documentation topic to retrieve. Call without any parameters to get the README overview. " +
114
122
  "Example: topic='syntax' for language syntax, topic='database' for database operations, topic='types' for type system.\n\n" +
115
123
  "Available topics:\n" + getTopicDescriptions(),
@@ -127,7 +135,14 @@ export const xanoscriptDocsToolDefinition = {
127
135
  description: "'full' = complete documentation with explanations and examples. " +
128
136
  "'quick_reference' = compact cheatsheet with just syntax patterns and signatures. " +
129
137
  "Use 'quick_reference' to save context window space when you just need a reminder. " +
130
- "Default: 'full'.",
138
+ "Default: 'full' for topic mode, 'quick_reference' for file_path mode.",
139
+ },
140
+ exclude_topics: {
141
+ type: "array",
142
+ items: { type: "string" },
143
+ description: "List of topic names to exclude from file_path results. " +
144
+ "Use this to skip topics you've already loaded (e.g., exclude_topics: ['syntax', 'quickstart']). " +
145
+ "Only applies when using file_path parameter.",
131
146
  },
132
147
  },
133
148
  required: [],
@@ -13,6 +13,7 @@ export interface XanoscriptDocsArgs {
13
13
  topic?: string;
14
14
  file_path?: string;
15
15
  mode?: "full" | "quick_reference";
16
+ exclude_topics?: string[];
16
17
  }
17
18
  export declare const XANOSCRIPT_DOCS_V2: Record<string, DocConfig>;
18
19
  /**
@@ -93,7 +93,7 @@ export const XANOSCRIPT_DOCS_V2 = {
93
93
  },
94
94
  integrations: {
95
95
  file: "integrations.md",
96
- applyTo: ["functions/**/*.xs", "apis/**/*.xs", "tasks/*.xs"],
96
+ applyTo: [],
97
97
  description: "External service integrations index - see sub-topics for details",
98
98
  },
99
99
  "integrations/cloud-storage": {
@@ -133,7 +133,7 @@ export const XANOSCRIPT_DOCS_V2 = {
133
133
  },
134
134
  addons: {
135
135
  file: "addons.md",
136
- applyTo: ["addons/*.xs", "functions/**/*.xs", "apis/**/*.xs"],
136
+ applyTo: ["addons/*.xs"],
137
137
  description: "Reusable subqueries for fetching related data",
138
138
  },
139
139
  debugging: {
@@ -148,12 +148,12 @@ export const XANOSCRIPT_DOCS_V2 = {
148
148
  },
149
149
  realtime: {
150
150
  file: "realtime.md",
151
- applyTo: ["functions/**/*.xs", "apis/**/*.xs", "triggers/**/*.xs"],
151
+ applyTo: ["triggers/**/*.xs"],
152
152
  description: "Real-time channels and events for push updates",
153
153
  },
154
154
  schema: {
155
155
  file: "schema.md",
156
- applyTo: ["functions/**/*.xs", "apis/**/*.xs"],
156
+ applyTo: [],
157
157
  description: "Runtime schema parsing and validation",
158
158
  },
159
159
  security: {
@@ -163,7 +163,7 @@ export const XANOSCRIPT_DOCS_V2 = {
163
163
  },
164
164
  streaming: {
165
165
  file: "streaming.md",
166
- applyTo: ["functions/**/*.xs", "apis/**/*.xs"],
166
+ applyTo: [],
167
167
  description: "Streaming data from files, requests, and responses",
168
168
  },
169
169
  middleware: {
@@ -241,49 +241,46 @@ export function getXanoscriptDocsVersion(docsPath) {
241
241
  * Read XanoScript documentation with v2 structure
242
242
  */
243
243
  export function readXanoscriptDocsV2(docsPath, args) {
244
- const mode = args?.mode || "full";
244
+ // Default to quick_reference for file_path mode (loads many topics),
245
+ // full for topic mode (loads single topic)
246
+ const mode = args?.mode || (args?.file_path ? "quick_reference" : "full");
245
247
  const version = getXanoscriptDocsVersion(docsPath);
246
- try {
247
- // Default: return README
248
- if (!args?.topic && !args?.file_path) {
249
- const readme = readFileSync(join(docsPath, "README.md"), "utf-8");
250
- return `${readme}\n\n---\nDocumentation version: ${version}`;
248
+ // Default: return README
249
+ if (!args?.topic && !args?.file_path) {
250
+ const readme = readFileSync(join(docsPath, "README.md"), "utf-8");
251
+ return `${readme}\n\n---\nDocumentation version: ${version}`;
252
+ }
253
+ // Context-aware: return docs matching file pattern
254
+ if (args?.file_path) {
255
+ let topics = getDocsForFilePath(args.file_path);
256
+ // Filter out excluded topics
257
+ if (args.exclude_topics && args.exclude_topics.length > 0) {
258
+ topics = topics.filter((t) => !args.exclude_topics.includes(t));
251
259
  }
252
- // Context-aware: return docs matching file pattern
253
- if (args?.file_path) {
254
- const topics = getDocsForFilePath(args.file_path);
255
- if (topics.length === 0) {
256
- return `No documentation found for file pattern: ${args.file_path}\n\nAvailable topics: ${Object.keys(XANOSCRIPT_DOCS_V2).join(", ")}`;
257
- }
258
- const docs = topics.map((t) => {
259
- const config = XANOSCRIPT_DOCS_V2[t];
260
- const content = readFileSync(join(docsPath, config.file), "utf-8");
261
- return mode === "quick_reference"
262
- ? extractQuickReference(content, t)
263
- : content;
264
- });
265
- const header = `# XanoScript Documentation for: ${args.file_path}\n\nMatched topics: ${topics.join(", ")}\nMode: ${mode}\nVersion: ${version}\n\n---\n\n`;
266
- return header + docs.join("\n\n---\n\n");
260
+ if (topics.length === 0) {
261
+ throw new Error(`No documentation found for file pattern: ${args.file_path}\n\nAvailable topics: ${Object.keys(XANOSCRIPT_DOCS_V2).join(", ")}`);
267
262
  }
268
- // Topic-based: return specific doc
269
- if (args?.topic) {
270
- const config = XANOSCRIPT_DOCS_V2[args.topic];
271
- if (!config) {
272
- const availableTopics = Object.keys(XANOSCRIPT_DOCS_V2).join(", ");
273
- return `Error: Unknown topic "${args.topic}".\n\nAvailable topics: ${availableTopics}`;
274
- }
263
+ const docs = topics.map((t) => {
264
+ const config = XANOSCRIPT_DOCS_V2[t];
275
265
  const content = readFileSync(join(docsPath, config.file), "utf-8");
276
- const doc = mode === "quick_reference"
277
- ? extractQuickReference(content, args.topic)
266
+ return mode === "quick_reference"
267
+ ? extractQuickReference(content, t)
278
268
  : content;
279
- return `${doc}\n\n---\nDocumentation version: ${version}`;
280
- }
281
- return "Error: Invalid parameters";
269
+ });
270
+ const header = `# XanoScript Documentation for: ${args.file_path}\n\nMatched topics: ${topics.join(", ")}\nMode: ${mode}\nVersion: ${version}\n\n---\n\n`;
271
+ return header + docs.join("\n\n---\n\n");
282
272
  }
283
- catch (error) {
284
- const errorMessage = error instanceof Error ? error.message : String(error);
285
- return `Error reading XanoScript documentation: ${errorMessage}`;
273
+ // Topic-based: return specific doc
274
+ const config = XANOSCRIPT_DOCS_V2[args.topic];
275
+ if (!config) {
276
+ const availableTopics = Object.keys(XANOSCRIPT_DOCS_V2).join(", ");
277
+ throw new Error(`Unknown topic "${args.topic}".\n\nAvailable topics: ${availableTopics}`);
286
278
  }
279
+ const content = readFileSync(join(docsPath, config.file), "utf-8");
280
+ const doc = mode === "quick_reference"
281
+ ? extractQuickReference(content, args.topic)
282
+ : content;
283
+ return `${doc}\n\n---\nDocumentation version: ${version}`;
287
284
  }
288
285
  /**
289
286
  * Get available topic names
@@ -70,7 +70,12 @@ describe("xanoscript module", () => {
70
70
  expect(result).toContain("types");
71
71
  expect(result).toContain("database");
72
72
  expect(result).toContain("unit-testing");
73
- expect(result).toContain("addons");
73
+ // Niche topics should NOT be auto-included for apis
74
+ expect(result).not.toContain("addons");
75
+ expect(result).not.toContain("integrations");
76
+ expect(result).not.toContain("realtime");
77
+ expect(result).not.toContain("schema");
78
+ expect(result).not.toContain("streaming");
74
79
  });
75
80
  it("should match functions files", () => {
76
81
  const result = getDocsForFilePath("functions/utils/format.xs");
@@ -78,6 +83,12 @@ describe("xanoscript module", () => {
78
83
  expect(result).toContain("functions");
79
84
  expect(result).toContain("types");
80
85
  expect(result).toContain("database");
86
+ // Niche topics should NOT be auto-included for functions
87
+ expect(result).not.toContain("addons");
88
+ expect(result).not.toContain("integrations");
89
+ expect(result).not.toContain("realtime");
90
+ expect(result).not.toContain("schema");
91
+ expect(result).not.toContain("streaming");
81
92
  });
82
93
  it("should match tables files", () => {
83
94
  const result = getDocsForFilePath("tables/users.xs");
@@ -89,7 +100,8 @@ describe("xanoscript module", () => {
89
100
  expect(result).toContain("syntax");
90
101
  expect(result).toContain("tasks");
91
102
  expect(result).toContain("database");
92
- expect(result).toContain("integrations");
103
+ // integrations is now topic-only (not auto-included)
104
+ expect(result).not.toContain("integrations");
93
105
  });
94
106
  it("should match triggers files", () => {
95
107
  const result = getDocsForFilePath("triggers/table/users.xs");
@@ -126,7 +138,7 @@ describe("xanoscript module", () => {
126
138
  expect(result).toContain("branch");
127
139
  });
128
140
  it("should match workspace.xs", () => {
129
- const result = getDocsForFilePath("workspace.xs");
141
+ const result = getDocsForFilePath("workspace/workspace.xs");
130
142
  expect(result).toContain("syntax");
131
143
  expect(result).toContain("workspace");
132
144
  });
@@ -236,10 +248,8 @@ Even more content.
236
248
  const result = readXanoscriptDocsV2(DOCS_PATH, { topic: "syntax" });
237
249
  expect(result).toContain("Documentation version:");
238
250
  });
239
- it("should return error for unknown topic", () => {
240
- const result = readXanoscriptDocsV2(DOCS_PATH, { topic: "nonexistent" });
241
- expect(result).toContain('Error: Unknown topic "nonexistent"');
242
- expect(result).toContain("Available topics:");
251
+ it("should throw for unknown topic", () => {
252
+ expect(() => readXanoscriptDocsV2(DOCS_PATH, { topic: "nonexistent" })).toThrow('Unknown topic "nonexistent"');
243
253
  });
244
254
  it("should return context-aware docs for file_path", () => {
245
255
  const result = readXanoscriptDocsV2(DOCS_PATH, {
@@ -272,11 +282,37 @@ Even more content.
272
282
  });
273
283
  expect(quickResult).toContain("Mode: quick_reference");
274
284
  });
275
- it("should return error for invalid docs path", () => {
276
- const result = readXanoscriptDocsV2("/nonexistent/path", {
277
- topic: "syntax",
285
+ it("should default to quick_reference mode for file_path", () => {
286
+ const result = readXanoscriptDocsV2(DOCS_PATH, {
287
+ file_path: "apis/test.xs",
288
+ });
289
+ expect(result).toContain("Mode: quick_reference");
290
+ });
291
+ it("should default to full mode for topic", () => {
292
+ const result = readXanoscriptDocsV2(DOCS_PATH, { topic: "syntax" });
293
+ // Full mode returns the complete doc content, not quick_reference
294
+ expect(result).not.toContain("Mode: quick_reference");
295
+ });
296
+ it("should support exclude_topics with file_path", () => {
297
+ const result = readXanoscriptDocsV2(DOCS_PATH, {
298
+ file_path: "apis/users/create.xs",
299
+ exclude_topics: ["syntax", "quickstart"],
278
300
  });
279
- expect(result).toContain("Error reading XanoScript documentation:");
301
+ expect(result).toContain("Matched topics:");
302
+ expect(result).not.toContain("Matched topics: syntax");
303
+ // Verify excluded topics are not in the matched list
304
+ const matchLine = result.split("\n").find((l) => l.startsWith("Matched topics:"));
305
+ expect(matchLine).not.toContain("syntax");
306
+ expect(matchLine).not.toContain("quickstart");
307
+ });
308
+ it("should throw when all topics are excluded via exclude_topics", () => {
309
+ expect(() => readXanoscriptDocsV2(DOCS_PATH, {
310
+ file_path: "branch.xs",
311
+ exclude_topics: ["syntax", "cheatsheet", "quickstart", "debugging", "branch"],
312
+ })).toThrow("No documentation found");
313
+ });
314
+ it("should throw for invalid docs path", () => {
315
+ expect(() => readXanoscriptDocsV2("/nonexistent/path", { topic: "syntax" })).toThrow();
280
316
  });
281
317
  });
282
318
  describe("getTopicNames", () => {
@@ -6,7 +6,9 @@ applyTo: "**/*.xs"
6
6
 
7
7
  > **Purpose:** Quick reference for the 20 most common XanoScript patterns. For detailed documentation, use `xanoscript_docs({ topic: "<topic>" })`.
8
8
 
9
- ## Variable Declaration
9
+ ## Quick Reference
10
+
11
+ ### Variable Declaration
10
12
 
11
13
  ```xs
12
14
  var $name { value = "initial" }
@@ -15,7 +17,7 @@ var $items { value = [] }
15
17
  var $data { value = { key: "value" } }
16
18
  ```
17
19
 
18
- ## Conditionals
20
+ ### Conditionals
19
21
 
20
22
  ```xs
21
23
  conditional {
@@ -33,7 +35,7 @@ conditional {
33
35
 
34
36
  > **Note:** Use `elseif` (one word), not `else if`.
35
37
 
36
- ## Switch
38
+ ### Switch
37
39
 
38
40
  ```xs
39
41
  switch ($input.status) {
@@ -51,7 +53,7 @@ switch ($input.status) {
51
53
 
52
54
  > **Note:** `break` goes **after** the closing `}` of each `case` block. The `default` case does not need `break`.
53
55
 
54
- ## Loops
56
+ ### Loops
55
57
 
56
58
  ```xs
57
59
  // For each loop
@@ -81,7 +83,7 @@ var $names { value = $items|map:$$.name }
81
83
  var $active { value = $items|filter:$$.is_active }
82
84
  ```
83
85
 
84
- ## Database CRUD
86
+ ### Database CRUD
85
87
 
86
88
  ```xs
87
89
  // Get single record by field
@@ -113,7 +115,7 @@ db.edit "user" {
113
115
  db.del "user" { field_name = "id", field_value = $input.user_id }
114
116
  ```
115
117
 
116
- ## API Requests
118
+ ### API Requests
117
119
 
118
120
  ```xs
119
121
  api.request {
@@ -133,7 +135,7 @@ api.request {
133
135
  // $api_result.response.headers → Response headers
134
136
  ```
135
137
 
136
- ## Error Handling
138
+ ### Error Handling
137
139
 
138
140
  ```xs
139
141
  // Precondition (stops execution if false)
@@ -159,7 +161,7 @@ throw {
159
161
  }
160
162
  ```
161
163
 
162
- ## Error Types
164
+ ### Error Types
163
165
 
164
166
  | Type | HTTP Status | Use Case |
165
167
  |------|-------------|----------|
@@ -168,7 +170,7 @@ throw {
168
170
  | `notfound` | 404 | Resource doesn't exist |
169
171
  | `standard` | 500 | General errors |
170
172
 
171
- ## Common Filters
173
+ ### Common Filters
172
174
 
173
175
  ```xs
174
176
  // String
@@ -210,7 +212,7 @@ $num|round:2 // Round to 2 decimals
210
212
  $num|abs // Absolute value
211
213
  ```
212
214
 
213
- ## Authentication Check
215
+ ### Authentication Check
214
216
 
215
217
  ```xs
216
218
  precondition ($auth.id != null) {
@@ -219,7 +221,7 @@ precondition ($auth.id != null) {
219
221
  }
220
222
  ```
221
223
 
222
- ## Function Call
224
+ ### Function Call
223
225
 
224
226
  ```xs
225
227
  function.run "my_function" {
@@ -227,7 +229,7 @@ function.run "my_function" {
227
229
  } as $result
228
230
  ```
229
231
 
230
- ## String Concatenation
232
+ ### String Concatenation
231
233
 
232
234
  ```xs
233
235
  // Basic
@@ -237,7 +239,7 @@ var $msg { value = "Hello, " ~ $input.name ~ "!" }
237
239
  var $msg { value = ($status|to_text) ~ ": " ~ ($data|json_encode) }
238
240
  ```
239
241
 
240
- ## Common Type Names
242
+ ### Common Type Names
241
243
 
242
244
  | Use This | Not This |
243
245
  |----------|----------|
@@ -247,11 +249,11 @@ var $msg { value = ($status|to_text) ~ ": " ~ ($data|json_encode) }
247
249
  | `decimal` | float, number |
248
250
  | `type[]` | array, list |
249
251
 
250
- ## Reserved Variables (Cannot Use)
252
+ ### Reserved Variables (Cannot Use)
251
253
 
252
254
  `$response`, `$output`, `$input`, `$auth`, `$env`, `$db`, `$this`, `$result`, `$index`
253
255
 
254
- ## Input Block Syntax
256
+ ### Input Block Syntax
255
257
 
256
258
  `?` after the **type** = nullable, `?` after the **variable name** = optional (not required).
257
259
 
@@ -113,7 +113,7 @@ debug.stop
113
113
  function "process_order" {
114
114
  input { int order_id }
115
115
  stack {
116
- var $trace_id { value = |uuid }
116
+ security.create_uuid as $trace_id
117
117
 
118
118
  debug.log {
119
119
  label = "TRACE_START"
@@ -298,7 +298,7 @@ precondition ($input.email|contains:"@") {
298
298
  | `db.query` | Filtered list | `db.query "users" { where = $db.users.active == true } as $users` |
299
299
  | `db.add` | Insert | `db.add "users" { data = { name: "John" } } as $new` |
300
300
  | `db.edit` | Update | `db.edit "users" { field_name = "id" field_value = 1 data = { name: "Jane" } }` |
301
- | `db.delete` | Delete | `db.delete "users" { field_name = "id" field_value = 1 }` |
301
+ | `db.del` | Delete | `db.del "users" { field_name = "id" field_value = 1 }` |
302
302
 
303
303
  > **Full reference:** See `xanoscript_docs({ topic: "database" })` for joins, bulk operations, transactions, and more.
304
304
 
@@ -323,9 +323,11 @@ var $data {
323
323
  ### 4. Loop Through Array
324
324
 
325
325
  ```xs
326
- // Using each
327
- each ($items as $item) {
328
- debug.log { value = $item.name }
326
+ // Using foreach
327
+ foreach ($items) {
328
+ each as $item {
329
+ debug.log { value = $item.name }
330
+ }
329
331
  }
330
332
 
331
333
  // Using map filter
@@ -96,7 +96,7 @@ function "refresh_auth" {
96
96
  } as $new_token
97
97
 
98
98
  // Rotate refresh token
99
- var $new_refresh { value = |uuid }
99
+ security.create_uuid as $new_refresh
100
100
 
101
101
  db.edit "refresh_token" {
102
102
  field_name = "id"
@@ -120,7 +120,7 @@ function "refresh_auth" {
120
120
  function "create_session" {
121
121
  input { int user_id }
122
122
  stack {
123
- var $session_id { value = |uuid }
123
+ security.create_uuid as $session_id
124
124
 
125
125
  db.add "session" {
126
126
  data = {
@@ -107,34 +107,34 @@ function "add" {
107
107
  ### Value Assertions
108
108
 
109
109
  ```xs
110
- # Equality
110
+ // Equality
111
111
  expect.to_equal ($response.status) { value = "active" }
112
112
  expect.to_not_equal ($response.status) { value = "deleted" }
113
113
 
114
- # Boolean
114
+ // Boolean
115
115
  expect.to_be_true ($response.is_active)
116
116
  expect.to_be_false ($response.is_deleted)
117
117
 
118
- # Null
118
+ // Null
119
119
  expect.to_be_null ($response.deleted_at)
120
120
  expect.to_not_be_null ($response.created_at)
121
121
 
122
- # Defined
122
+ // Defined
123
123
  expect.to_be_defined ($response.id)
124
124
  expect.to_not_be_defined ($response.optional_field)
125
125
 
126
- # Empty
126
+ // Empty
127
127
  expect.to_be_empty ($response.errors)
128
128
  ```
129
129
 
130
130
  ### Comparison Assertions
131
131
 
132
132
  ```xs
133
- # Numeric comparisons
133
+ // Numeric comparisons
134
134
  expect.to_be_greater_than ($response.total) { value = 100 }
135
135
  expect.to_be_less_than ($response.stock) { value = 10 }
136
136
 
137
- # Range
137
+ // Range
138
138
  expect.to_be_within ($response.temperature) {
139
139
  min = 20
140
140
  max = 30
@@ -144,14 +144,14 @@ expect.to_be_within ($response.temperature) {
144
144
  ### String Assertions
145
145
 
146
146
  ```xs
147
- # Starts/ends with
147
+ // Starts/ends with
148
148
  expect.to_start_with ($response.name) { value = "John" }
149
149
  expect.to_end_with ($response.file) { value = ".pdf" }
150
150
 
151
- # Contains
151
+ // Contains
152
152
  expect.to_contain ($response.tags) { value = "featured" }
153
153
 
154
- # Regex match
154
+ // Regex match
155
155
  expect.to_match ($response.phone) { value = "^\\+1\\d{10}$" }
156
156
  ```
157
157
 
@@ -165,13 +165,13 @@ expect.to_be_in_the_future ($response.expires_at)
165
165
  ### Error Assertions
166
166
 
167
167
  ```xs
168
- # Expects any error
168
+ // Expects any error
169
169
  test "throws on invalid input" {
170
170
  input = { amount: -1 }
171
171
  expect.to_throw
172
172
  }
173
173
 
174
- # Expects specific error
174
+ // Expects specific error
175
175
  test "throws validation error" {
176
176
  input = { amount: -1 }
177
177
  expect.to_throw { value = "InvalidInputError" }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xano/developer-mcp",
3
- "version": "1.0.52",
3
+ "version": "1.0.54",
4
4
  "description": "MCP server and library for Xano development - XanoScript validation, Meta API, Run API, and CLI documentation",
5
5
  "type": "module",
6
6
  "main": "dist/lib.js",