@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 +16 -0
- package/dist/index.js +35 -0
- package/dist/templates/xanoscript-index.js +7 -0
- package/package.json +1 -1
- package/xanoscript_docs/README.md +38 -5
- package/xanoscript_docs/addons.md +285 -0
- package/xanoscript_docs/agents.md +84 -0
- package/xanoscript_docs/database.md +160 -0
- package/xanoscript_docs/debugging.md +342 -0
- package/xanoscript_docs/functions.md +172 -0
- package/xanoscript_docs/integrations.md +376 -7
- package/xanoscript_docs/performance.md +407 -0
- package/xanoscript_docs/realtime.md +382 -0
- package/xanoscript_docs/schema.md +292 -0
- package/xanoscript_docs/security.md +550 -0
- package/xanoscript_docs/streaming.md +318 -0
- package/xanoscript_docs/syntax.md +267 -0
- package/xanoscript_docs/types.md +66 -21
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
|
@@ -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
|
-
|
|
|
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
|
|
117
|
-
|
|
|
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
|