Skip to main content
You expose a function as an MCP tool for AI agents to invoke. With .describe() you tell the agent what each parameter does. Pattern: clear name + description + .describe() on each field + MCP active (default).
index.ts
import { define, z } from "@jelou/functions";

export default define({
  name: "search-products",
  description: "Searches the product catalog by name, category, or price range",
  input: z.object({
    query: z.string().min(1).describe("Search term: product name or keywords"),
    category: z.string().optional().describe("Filter by category: electronics, clothing, home, food"),
    minPrice: z.number().optional().describe("Minimum price in USD"),
    maxPrice: z.number().optional().describe("Maximum price in USD"),
    limit: z.number().default(5).describe("Maximum number of results (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("Product search", {
      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,
    };
  },
});

Local testing

curl -X POST http://localhost:3000 \
  -H "Content-Type: application/json" \
  -d '{"query": "laptop", "category": "electronics", "maxPrice": 1500}'

Why it works this way

  • name and description are what the AI agent sees to decide when to use this tool.
  • .describe() on each field generates the parameter descriptions in the MCP schema.
  • The output schema documents what structure the function returns.
  • MCP is active by default (config.mcp: true), so the /mcp endpoint automatically exposes the tool.
  • An AI agent can call this function when a user asks “do you have laptops under $1500?”.