.describe() le dices al agente qué hace cada parámetro.
Patrón: name + description claros + .describe() en cada campo + MCP activo (default).
index.ts
Copy
Ask AI
import { define, z } from "@jelou/functions";
export default define({
name: "search-products",
description: "Busca productos en el catálogo por nombre, categoría o rango de precio",
input: z.object({
query: z.string().min(1).describe("Término de búsqueda: nombre del producto o palabras clave"),
category: z.string().optional().describe("Filtrar por categoría: electronics, clothing, home, food"),
minPrice: z.number().optional().describe("Precio mínimo en USD"),
maxPrice: z.number().optional().describe("Precio máximo en USD"),
limit: z.number().default(5).describe("Cantidad máxima de resultados (1-20)"),
}),
output: z.object({
results: z.array(z.object({
id: z.string(),
name: z.string(),
price: z.number(),
category: z.string(),
inStock: z.boolean(),
})),
total: z.number(),
}),
handler: async (input, ctx) => {
ctx.log("Búsqueda de productos", {
query: input.query,
category: input.category,
company: ctx.company.id,
});
const apiKey = ctx.env.get("CATALOG_API_KEY");
const params = new URLSearchParams({ q: input.query });
if (input.category) params.set("category", input.category);
if (input.minPrice) params.set("min_price", String(input.minPrice));
if (input.maxPrice) params.set("max_price", String(input.maxPrice));
params.set("limit", String(input.limit));
const res = await fetch(
`https://catalog.example.com/api/search?${params}`,
{ headers: { Authorization: `Bearer ${apiKey}` } },
);
const data = await res.json();
return {
results: data.items.map((item: any) => ({
id: item.id,
name: item.name,
price: item.price,
category: item.category,
inStock: item.stock > 0,
})),
total: data.total,
};
},
});
Prueba local
Copy
Ask AI
curl -X POST http://localhost:3000 \
-H "Content-Type: application/json" \
-d '{"query": "laptop", "category": "electronics", "maxPrice": 1500}'
Por qué funciona así
nameydescriptionson lo que el agente IA ve para decidir cuándo usar esta herramienta..describe()en cada campo genera las descripciones de parámetros en el esquema MCP.- El esquema
outputdocumenta qué estructura devuelve la función. - MCP está activo por defecto (
config.mcp: true), así que el endpoint/mcpexpone automáticamente el tool. - Un agente IA puede llamar esta función cuando un usuario pregunta “¿tienen laptops por menos de $1500?”.