Skip to main content
With app() you group multiple related operations in a single deployment. Your AI agents discover each tool individually via MCP, and each has its own HTTP route. Pattern: app() + multiple define() + .describe() on each field + shared config + ctx.env.get() for secrets.
index.ts

Local testing

Start the server with jelou functions dev and test each tool:
If you send an invalid input, you receive a 400 with the error details:

Why it works this way

  • Automatic routes — the keys createContact, searchContacts, deleteContact generate /create-contact, /search-contacts, /delete-contact.
  • GET vs POSTsearchContacts uses config: { methods: ["GET"] } to receive parameters as query strings. The others use POST by default.
  • description matters — each tool has a specific description that tells the AI agent exactly what it does and what it returns. “Searches contacts by name or email” is much better than “Searches contacts”.
  • Shared configcors and timeout are defined once in app() and apply to all tools. Each tool can override them if needed.
  • Centralized secrets — all 3 tools use ctx.env.get("CRM_API_KEY"). You configure the secret once with jelou secrets set.
  • Unified MCPcurl http://localhost:3000/mcp returns the 3 tools as independent tools the agent can invoke.