@xano/developer-mcp 1.0.0 → 1.0.2

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.
Files changed (46) hide show
  1. package/README.md +96 -31
  2. package/dist/index.js +335 -222
  3. package/dist/templates/init-workspace.d.ts +10 -0
  4. package/dist/templates/init-workspace.js +292 -0
  5. package/dist/templates/xanoscript-index.d.ts +9 -0
  6. package/dist/templates/xanoscript-index.js +61 -0
  7. package/package.json +4 -2
  8. package/xanoscript_docs/README.md +107 -1
  9. package/xanoscript_docs/agents.md +329 -0
  10. package/xanoscript_docs/apis.md +343 -0
  11. package/xanoscript_docs/database.md +417 -0
  12. package/xanoscript_docs/ephemeral.md +333 -0
  13. package/xanoscript_docs/frontend.md +291 -0
  14. package/xanoscript_docs/functions.md +232 -2035
  15. package/xanoscript_docs/integrations.md +439 -0
  16. package/xanoscript_docs/mcp-servers.md +190 -0
  17. package/xanoscript_docs/plan.md +192 -0
  18. package/xanoscript_docs/syntax.md +314 -0
  19. package/xanoscript_docs/tables.md +270 -0
  20. package/xanoscript_docs/tasks.md +254 -0
  21. package/xanoscript_docs/testing.md +335 -0
  22. package/xanoscript_docs/tools.md +305 -0
  23. package/xanoscript_docs/types.md +297 -0
  24. package/xanoscript_docs/version.json +2 -1
  25. package/xanoscript_docs/api_query_examples.md +0 -1255
  26. package/xanoscript_docs/api_query_guideline.md +0 -129
  27. package/xanoscript_docs/build_from_lovable.md +0 -715
  28. package/xanoscript_docs/db_query_guideline.md +0 -427
  29. package/xanoscript_docs/ephemeral_environment_guideline.md +0 -529
  30. package/xanoscript_docs/expression_guideline.md +0 -1086
  31. package/xanoscript_docs/frontend_guideline.md +0 -67
  32. package/xanoscript_docs/function_examples.md +0 -1406
  33. package/xanoscript_docs/function_guideline.md +0 -130
  34. package/xanoscript_docs/input_guideline.md +0 -227
  35. package/xanoscript_docs/mcp_server_examples.md +0 -36
  36. package/xanoscript_docs/mcp_server_guideline.md +0 -69
  37. package/xanoscript_docs/query_filter.md +0 -489
  38. package/xanoscript_docs/table_examples.md +0 -586
  39. package/xanoscript_docs/table_guideline.md +0 -137
  40. package/xanoscript_docs/task_examples.md +0 -511
  41. package/xanoscript_docs/task_guideline.md +0 -103
  42. package/xanoscript_docs/tips_and_tricks.md +0 -144
  43. package/xanoscript_docs/tool_examples.md +0 -69
  44. package/xanoscript_docs/tool_guideline.md +0 -139
  45. package/xanoscript_docs/unit_testing_guideline.md +0 -328
  46. package/xanoscript_docs/workspace.md +0 -17
@@ -0,0 +1,329 @@
1
+ ---
2
+ applyTo: "agents/**/*.xs"
3
+ ---
4
+
5
+ # Agents
6
+
7
+ AI-powered agents that use LLMs to perform tasks autonomously.
8
+
9
+ ## Quick Reference
10
+
11
+ ```xs
12
+ agent "<name>" {
13
+ canonical = "<unique-id>"
14
+ description = "What this agent does"
15
+ llm = {
16
+ type: "<provider>"
17
+ system_prompt: "Agent instructions"
18
+ prompt: "{{ $args.message }}"
19
+ max_steps: 5
20
+ }
21
+ tools = [{ name: "<tool-name>" }]
22
+ }
23
+ ```
24
+
25
+ ### LLM Providers
26
+ | Provider | Type Value |
27
+ |----------|------------|
28
+ | Xano Free (Gemini) | `xano-free` |
29
+ | Google Gemini | `google-genai` |
30
+ | OpenAI | `openai` |
31
+ | Anthropic | `anthropic` |
32
+
33
+ ---
34
+
35
+ ## Basic Structure
36
+
37
+ ```xs
38
+ agent "Customer Support" {
39
+ canonical = "support-agent-v1"
40
+ description = "Handles customer inquiries"
41
+ llm = {
42
+ type: "xano-free"
43
+ system_prompt: "You are a helpful customer support agent."
44
+ prompt: "{{ $args.user_message }}"
45
+ max_steps: 5
46
+ temperature: 0.7
47
+ }
48
+ tools = [
49
+ { name: "get_order_status" },
50
+ { name: "create_ticket" }
51
+ ]
52
+ }
53
+ ```
54
+
55
+ ---
56
+
57
+ ## Calling Agents
58
+
59
+ ```xs
60
+ ai.agent.run "Customer Support" {
61
+ args = {}|set:"user_message":$input.message
62
+ allow_tool_execution = true
63
+ } as $response
64
+ ```
65
+
66
+ ---
67
+
68
+ ## LLM Configuration
69
+
70
+ ### Common Properties
71
+
72
+ ```xs
73
+ llm = {
74
+ type: "<provider>" # Required
75
+ system_prompt: "..." # Agent persona and rules
76
+ prompt: "{{ $args.input }}" # User input template
77
+ max_steps: 5 # Max LLM calls per run
78
+ }
79
+ ```
80
+
81
+ ### Dynamic Variables
82
+ - `{{ $args.<name> }}` - Runtime arguments
83
+ - `{{ $env.<name> }}` - Environment variables (for API keys)
84
+
85
+ ---
86
+
87
+ ## Provider Configurations
88
+
89
+ ### Xano Free (for testing)
90
+ ```xs
91
+ llm = {
92
+ type: "xano-free"
93
+ system_prompt: "You are a helpful assistant."
94
+ prompt: "{{ $args.message }}"
95
+ max_steps: 3
96
+ temperature: 0
97
+ search_grounding: false # Google Search grounding
98
+ }
99
+ ```
100
+
101
+ ### Google Gemini
102
+ ```xs
103
+ llm = {
104
+ type: "google-genai"
105
+ api_key: "{{ $env.GEMINI_API_KEY }}"
106
+ model: "gemini-2.5-flash"
107
+ system_prompt: "You are a helpful assistant."
108
+ prompt: "{{ $args.message }}"
109
+ max_steps: 5
110
+ temperature: 0.2
111
+ thinking_tokens: 10000 # Extended thinking
112
+ include_thoughts: true
113
+ }
114
+ ```
115
+
116
+ ### OpenAI
117
+ ```xs
118
+ llm = {
119
+ type: "openai"
120
+ api_key: "{{ $env.OPENAI_API_KEY }}"
121
+ model: "gpt-5-mini"
122
+ system_prompt: "You are a helpful assistant."
123
+ prompt: "{{ $args.message }}"
124
+ max_steps: 5
125
+ temperature: 0.8
126
+ reasoning_effort: "medium" # low, medium, high
127
+ }
128
+ ```
129
+
130
+ **OpenAI-Compatible APIs:**
131
+ ```xs
132
+ llm = {
133
+ type: "openai"
134
+ api_key: "{{ $env.GROQ_API_KEY }}"
135
+ baseURL: "https://api.groq.com/openai/v1"
136
+ model: "llama-3.3-70b-versatile"
137
+ compatibility: "compatible" # Required for non-OpenAI
138
+ ...
139
+ }
140
+ ```
141
+
142
+ Supported: Groq, Mistral, OpenRouter, X.AI
143
+
144
+ ### Anthropic Claude
145
+ ```xs
146
+ llm = {
147
+ type: "anthropic"
148
+ api_key: "{{ $env.ANTHROPIC_API_KEY }}"
149
+ model: "claude-sonnet-4-5-20250929"
150
+ system_prompt: "You are a helpful assistant."
151
+ prompt: "{{ $args.message }}"
152
+ max_steps: 8
153
+ temperature: 0.3
154
+ send_reasoning: true # Include thinking blocks
155
+ }
156
+ ```
157
+
158
+ ---
159
+
160
+ ## Structured Outputs
161
+
162
+ Force JSON response format (disables tools):
163
+
164
+ ```xs
165
+ agent "Classifier" {
166
+ canonical = "classifier-v1"
167
+ llm = {
168
+ type: "openai"
169
+ api_key: "{{ $env.OPENAI_API_KEY }}"
170
+ model: "gpt-5-mini"
171
+ system_prompt: "Classify the sentiment of the text."
172
+ prompt: "{{ $args.text }}"
173
+ structured_outputs: true
174
+
175
+ output {
176
+ enum sentiment { values = ["positive", "negative", "neutral"] }
177
+ decimal confidence filters=min:0|max:1
178
+ text reasoning?
179
+ }
180
+ }
181
+ tools = []
182
+ }
183
+ ```
184
+
185
+ ---
186
+
187
+ ## Tools
188
+
189
+ Reference tools by name from `tools/` directory:
190
+
191
+ ```xs
192
+ tools = [
193
+ { name: "get_user_by_email" },
194
+ { name: "update_order_status" },
195
+ { name: "send_notification" }
196
+ ]
197
+ ```
198
+
199
+ **Important:** Do not describe tools in system_prompt or prompt. Tool descriptions are automatically provided to the LLM.
200
+
201
+ ---
202
+
203
+ ## Prompting
204
+
205
+ ### Using Twig Templates
206
+ ```xs
207
+ llm = {
208
+ prompt: """
209
+ User ID: {{ $args.user_id }}
210
+ Request: {{ $args.message }}
211
+
212
+ {% if $args.is_priority %}
213
+ This is a priority customer. Respond within 5 minutes.
214
+ {% endif %}
215
+ """
216
+ }
217
+ ```
218
+
219
+ ### Available Variables
220
+ ```xs
221
+ {{ $args.any_arg }} # Runtime arguments
222
+ {{ $env.MY_VAR }} # Environment variables
223
+ {{ "now"|date("Y-m-d") }} # Current date
224
+ ```
225
+
226
+ ---
227
+
228
+ ## Complete Examples
229
+
230
+ ### Task Manager Agent
231
+ ```xs
232
+ agent "Task Manager" {
233
+ canonical = "task-mgr-v1"
234
+ description = "Manages user tasks"
235
+ llm = {
236
+ type: "google-genai"
237
+ api_key: "{{ $env.GEMINI_API_KEY }}"
238
+ model: "gemini-2.5-flash"
239
+ system_prompt: """
240
+ You help users manage their tasks. You can:
241
+ - Add new tasks
242
+ - Mark tasks complete
243
+ - List pending tasks
244
+ Always confirm actions with the user.
245
+ """
246
+ prompt: "User {{ $args.user_id }}: {{ $args.message }}"
247
+ max_steps: 5
248
+ temperature: 0.2
249
+ }
250
+ tools = [
251
+ { name: "add_task" },
252
+ { name: "complete_task" },
253
+ { name: "list_tasks" }
254
+ ]
255
+ }
256
+ ```
257
+
258
+ ### Code Review Agent
259
+ ```xs
260
+ agent "Code Reviewer" {
261
+ canonical = "code-review-v1"
262
+ llm = {
263
+ type: "anthropic"
264
+ api_key: "{{ $env.ANTHROPIC_API_KEY }}"
265
+ model: "claude-sonnet-4-5-20250929"
266
+ system_prompt: """
267
+ You are an expert code reviewer. Analyze code for:
268
+ - Bugs and potential issues
269
+ - Security vulnerabilities
270
+ - Performance problems
271
+ - Code style and best practices
272
+ Provide specific, actionable feedback.
273
+ """
274
+ prompt: """
275
+ Language: {{ $args.language }}
276
+ Code:
277
+ ```
278
+ {{ $args.code }}
279
+ ```
280
+ """
281
+ max_steps: 3
282
+ temperature: 0.1
283
+ send_reasoning: true
284
+ }
285
+ tools = []
286
+ }
287
+ ```
288
+
289
+ ### Multi-Tool Research Agent
290
+ ```xs
291
+ agent "Research Assistant" {
292
+ canonical = "research-v1"
293
+ llm = {
294
+ type: "openai"
295
+ api_key: "{{ $env.OPENAI_API_KEY }}"
296
+ model: "gpt-5"
297
+ system_prompt: """
298
+ You are a research assistant. Use your tools to:
299
+ 1. Search for relevant information
300
+ 2. Analyze data
301
+ 3. Compile findings into clear summaries
302
+ Always cite your sources.
303
+ """
304
+ prompt: "Research topic: {{ $args.topic }}"
305
+ max_steps: 10
306
+ temperature: 0.5
307
+ reasoning_effort: "high"
308
+ }
309
+ tools = [
310
+ { name: "web_search" },
311
+ { name: "fetch_article" },
312
+ { name: "analyze_data" },
313
+ { name: "save_findings" }
314
+ ]
315
+ }
316
+ ```
317
+
318
+ ---
319
+
320
+ ## Best Practices
321
+
322
+ 1. **Clear system prompts** - Define persona, capabilities, and constraints
323
+ 2. **Use appropriate temperature** - Low for factual, higher for creative
324
+ 3. **Limit max_steps** - Prevent infinite loops (3-10 typical)
325
+ 4. **Don't repeat tool descriptions** - They're auto-injected
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
@@ -0,0 +1,343 @@
1
+ ---
2
+ applyTo: "apis/**/*.xs"
3
+ ---
4
+
5
+ # APIs
6
+
7
+ HTTP endpoint definitions in XanoScript.
8
+
9
+ ## Quick Reference
10
+
11
+ ```xs
12
+ query "<path>" verb=<METHOD> {
13
+ description = "What this endpoint does"
14
+ auth = "<table>" # Optional: require authentication
15
+ input { ... }
16
+ stack { ... }
17
+ response = $result
18
+ }
19
+ ```
20
+
21
+ ### HTTP Methods
22
+ `GET`, `POST`, `PUT`, `PATCH`, `DELETE`
23
+
24
+ ### File Structure
25
+ ```
26
+ apis/
27
+ ├── users/ # API group
28
+ │ ├── list.xs # GET /users
29
+ │ ├── create.xs # POST /users
30
+ │ └── {id}.xs # GET/PATCH/DELETE /users/{id}
31
+ └── products/
32
+ └── search.xs
33
+ ```
34
+
35
+ ---
36
+
37
+ ## Basic Structure
38
+
39
+ ```xs
40
+ query "products" verb=GET {
41
+ description = "List all products"
42
+ input {
43
+ int page?=1 filters=min:1
44
+ int per_page?=20 filters=min:1|max:100
45
+ }
46
+ stack {
47
+ db.query "product" {
48
+ return = { type: "list", paging: { page: $input.page, per_page: $input.per_page } }
49
+ } as $products
50
+ }
51
+ response = $products
52
+ }
53
+ ```
54
+
55
+ ---
56
+
57
+ ## Authentication
58
+
59
+ ### Public Endpoint (default)
60
+ ```xs
61
+ query "status" verb=GET {
62
+ stack { }
63
+ response = { status: "ok" }
64
+ }
65
+ ```
66
+
67
+ ### Authenticated Endpoint
68
+ ```xs
69
+ query "profile" verb=GET {
70
+ auth = "user" # Requires valid JWT
71
+ stack {
72
+ db.get "user" {
73
+ field_name = "id"
74
+ field_value = $auth.id # User ID from token
75
+ } as $user
76
+ }
77
+ response = $user
78
+ }
79
+ ```
80
+
81
+ When `auth` is set:
82
+ - Endpoint requires Bearer token in `Authorization` header
83
+ - `$auth.id` contains authenticated user's ID
84
+ - Invalid/missing token returns 401
85
+
86
+ ---
87
+
88
+ ## Path Parameters
89
+
90
+ Use `{param}` in the path:
91
+
92
+ ```xs
93
+ query "users/{user_id}" verb=GET {
94
+ auth = "user"
95
+ input {
96
+ int user_id { table = "user" }
97
+ }
98
+ stack {
99
+ db.get "user" {
100
+ field_name = "id"
101
+ field_value = $input.user_id
102
+ } as $user
103
+ }
104
+ response = $user
105
+ }
106
+ ```
107
+
108
+ ---
109
+
110
+ ## CRUD Examples
111
+
112
+ ### List (GET)
113
+ ```xs
114
+ query "products" verb=GET {
115
+ input {
116
+ text category? filters=trim|lower
117
+ int page?=1
118
+ int per_page?=20
119
+ }
120
+ stack {
121
+ db.query "product" {
122
+ where = $db.product.category ==? $input.category
123
+ sort = { created_at: "desc" }
124
+ return = { type: "list", paging: { page: $input.page, per_page: $input.per_page } }
125
+ } as $products
126
+ }
127
+ response = $products
128
+ }
129
+ ```
130
+
131
+ ### Create (POST)
132
+ ```xs
133
+ query "products" verb=POST {
134
+ auth = "user"
135
+ input {
136
+ text name filters=trim
137
+ text description? filters=trim
138
+ decimal price filters=min:0
139
+ int category_id { table = "category" }
140
+ }
141
+ stack {
142
+ db.add "product" {
143
+ data = {
144
+ name: $input.name,
145
+ description: $input.description,
146
+ price: $input.price,
147
+ category_id: $input.category_id,
148
+ created_by: $auth.id
149
+ }
150
+ } as $product
151
+ }
152
+ response = $product
153
+ }
154
+ ```
155
+
156
+ ### Read (GET with ID)
157
+ ```xs
158
+ query "products/{product_id}" verb=GET {
159
+ input {
160
+ int product_id { table = "product" }
161
+ }
162
+ stack {
163
+ db.get "product" {
164
+ field_name = "id"
165
+ field_value = $input.product_id
166
+ } as $product
167
+
168
+ precondition ($product != null) {
169
+ error_type = "notfound"
170
+ error = "Product not found"
171
+ }
172
+ }
173
+ response = $product
174
+ }
175
+ ```
176
+
177
+ ### Update (PATCH)
178
+ ```xs
179
+ query "products/{product_id}" verb=PATCH {
180
+ auth = "user"
181
+ input {
182
+ int product_id { table = "product" }
183
+ text name? filters=trim
184
+ text description? filters=trim
185
+ decimal price? filters=min:0
186
+ }
187
+ stack {
188
+ var $updates { value = {} }
189
+
190
+ conditional {
191
+ if ($input.name != null) {
192
+ var.update $updates { value = $updates|set:"name":$input.name }
193
+ }
194
+ }
195
+ conditional {
196
+ if ($input.price != null) {
197
+ var.update $updates { value = $updates|set:"price":$input.price }
198
+ }
199
+ }
200
+
201
+ db.patch "product" {
202
+ field_name = "id"
203
+ field_value = $input.product_id
204
+ data = $updates
205
+ } as $product
206
+ }
207
+ response = $product
208
+ }
209
+ ```
210
+
211
+ ### Delete (DELETE)
212
+ ```xs
213
+ query "products/{product_id}" verb=DELETE {
214
+ auth = "user"
215
+ input {
216
+ int product_id { table = "product" }
217
+ }
218
+ stack {
219
+ db.del "product" {
220
+ field_name = "id"
221
+ field_value = $input.product_id
222
+ }
223
+ }
224
+ response = { success: true }
225
+ }
226
+ ```
227
+
228
+ ---
229
+
230
+ ## Response Types
231
+
232
+ ### JSON (default)
233
+ ```xs
234
+ response = $data
235
+ ```
236
+
237
+ ### HTML
238
+ ```xs
239
+ stack {
240
+ util.set_header {
241
+ value = "Content-Type: text/html; charset=utf-8"
242
+ duplicates = "replace"
243
+ }
244
+
245
+ util.template_engine {
246
+ value = """
247
+ <html>
248
+ <body><h1>{{ $var.title }}</h1></body>
249
+ </html>
250
+ """
251
+ } as $html
252
+ }
253
+ response = $html
254
+ ```
255
+
256
+ ### Streaming
257
+ ```xs
258
+ stack {
259
+ api.stream { value = $processed_data }
260
+ }
261
+ response = null
262
+ ```
263
+
264
+ ---
265
+
266
+ ## Custom Headers
267
+
268
+ ```xs
269
+ stack {
270
+ util.set_header {
271
+ value = "X-Custom-Header: value"
272
+ duplicates = "replace"
273
+ }
274
+
275
+ util.set_header {
276
+ value = "Set-Cookie: session=abc123; HttpOnly; Secure"
277
+ duplicates = "add"
278
+ }
279
+ }
280
+ ```
281
+
282
+ ---
283
+
284
+ ## Error Handling
285
+
286
+ ### Preconditions
287
+ ```xs
288
+ stack {
289
+ precondition ($input.amount > 0) {
290
+ error_type = "inputerror"
291
+ error = "Amount must be positive"
292
+ }
293
+
294
+ precondition ($user != null) {
295
+ error_type = "notfound"
296
+ error = "User not found"
297
+ }
298
+
299
+ precondition ($user.id == $auth.id) {
300
+ error_type = "accessdenied"
301
+ error = "Not authorized"
302
+ }
303
+ }
304
+ ```
305
+
306
+ ### Error Types
307
+ | Type | HTTP Status |
308
+ |------|-------------|
309
+ | `inputerror` | 400 Bad Request |
310
+ | `accessdenied` | 403 Forbidden |
311
+ | `notfound` | 404 Not Found |
312
+ | `standard` | 500 Internal Server Error |
313
+
314
+ ---
315
+
316
+ ## Pagination Response Format
317
+
318
+ When using `return = { type: "list", paging: {...} }`:
319
+
320
+ ```json
321
+ {
322
+ "itemsReceived": 20,
323
+ "curPage": 1,
324
+ "nextPage": 2,
325
+ "prevPage": null,
326
+ "offset": 0,
327
+ "perPage": 20,
328
+ "items": [...]
329
+ }
330
+ ```
331
+
332
+ ---
333
+
334
+ ## Best Practices
335
+
336
+ 1. **RESTful design** - Use appropriate HTTP methods
337
+ 2. **Consistent naming** - Use lowercase, hyphens for multi-word paths
338
+ 3. **Authenticate sensitive operations** - Always auth for writes
339
+ 4. **Validate inputs** - Use filters and preconditions
340
+ 5. **Return appropriate errors** - Use correct error types
341
+ 6. **Paginate lists** - Never return unbounded lists
342
+ 7. **Document with description** - Explain what endpoint does
343
+ 8. **Group related endpoints** - Organize by resource in api groups