Pular para o conteúdo principal

Geração automática de ferramentas MCP

Quando você cria uma função com define(), ela é automaticamente exposta como uma ferramenta MCP (Model Context Protocol). Seus agentes de IA podem descobrir e invocar sua função como uma ferramenta sem configuração adicional.

Exemplo

Para esta função:
index.ts
import { define, z } from "@jelou/functions";

export default define({
  name: "query-balance",
  description: "Queries a customer's balance by phone number",
  input: z.object({
    phone: z.string().min(10).describe("Phone number with country code"),
  }),
  output: z.object({
    name: z.string(),
    balance: z.number(),
    currency: z.string(),
  }),
  handler: async (input, ctx) => {
    ctx.log("Querying balance", { phone: input.phone });
    return { name: "Maria Garcia", balance: 150.00, currency: "USD" };
  },
});
O endpoint /mcp expõe este schema:
{
  "name": "query-balance",
  "description": "Queries a customer's balance by phone number",
  "inputSchema": {
    "type": "object",
    "properties": {
      "phone": {
        "type": "string",
        "minLength": 10,
        "description": "Phone number with country code"
      }
    },
    "required": ["phone"]
  }
}

O campo description: o mais importante para MCP

O campo description do seu define() é o que o agente de IA lê para decidir quando invocar sua ferramenta. Se a descrição for vaga, o agente não saberá quando usá-la — ou pior, a usará no momento errado.
VagoEspecíficoPor que importa
"Handles users""Looks up a user by email or phone and returns their profile with balance"O agente sabe exatamente quais dados pode obter
"Sends message""Sends a WhatsApp message to a number with country code (e.g.: 593…)"O agente sabe o canal e o formato esperado
"Queries API""Queries the status of a shipment by tracking number in the Servientrega API"O agente sabe o provedor e quais dados precisa

Anotações .describe() nos campos

As anotações .describe() do Zod se tornam descrições de parâmetros na ferramenta MCP. Isso é o que os agentes de IA veem ao descobrir sua função:
input: z.object({
  phone: z.string().min(10).describe("Number with country code, e.g.: 593987654321"),
  type: z.enum(["prepaid", "postpaid"]).describe("Customer's plan type"),
  includeHistory: z.boolean().default(false).describe("Whether to include the last 5 transactions"),
})
Escreva descrições claras e específicas no .describe(). Os agentes de IA usam essas descrições para decidir quais valores passar para sua função.

Testando o endpoint MCP

Inicie o servidor local com jelou dev e consulte o schema MCP:
curl http://localhost:3000/mcp
Invoque a função diretamente:
curl -X POST http://localhost:3000 \
  -H "Content-Type: application/json" \
  -d '{"phone": "593987654321"}'
Em produção:
curl https://query-balance.fn.jelou.ai/mcp

Desativando o MCP

Se sua função não deve ser descoberta como ferramenta (por exemplo, um webhook que só recebe callbacks), desative o MCP:
config: { mcp: false }
Quando o MCP está desativado, o endpoint /mcp retorna 404.

Como os agentes usam

Quando você configura um agente de IA no Jelou Brain Studio e atribui funções como ferramentas, o agente:
  1. Descobre as ferramentas disponíveis via o endpoint /mcp
  2. Lê o nome, a descrição e o schema de entrada
  3. Decide quando invocar a ferramenta com base na conversa do usuário
  4. Envia parâmetros validados para sua função
  5. Recebe a resposta e a incorpora à conversa
Tudo isso acontece automaticamente — você só precisa escrever a função com define() e atribuí-la ao agente.

MCP multi-tool

Quando você usa app(), um único servidor MCP em /mcp registra automaticamente todas as ferramentas. Cada ferramenta aparece como uma ferramenta independente com seu nome, descrição e schema. Para excluir uma ferramenta específica do registro MCP, use mcp: false na sua config:
import { app, define, z } from "@jelou/functions";

export default app({
  tools: {
    queryBalance: define({
      description: "Queries a customer's balance",
      input: z.object({ phone: z.string().min(10) }),
      handler: async (input) => ({ balance: 150.00 }),
    }),
    paymentWebhook: define({
      description: "Receives payment callbacks",
      input: z.object({ transactionId: z.string() }),
      config: { mcp: false },
      handler: async (input) => ({ received: true }),
    }),
  },
});
Neste exemplo, os agentes de IA descobrem queryBalance via MCP, mas paymentWebhook só é acessível via HTTP direto em /payment-webhook.
Consulte o guia completo de multi-tool para mais detalhes sobre rotas geradas automaticamente e combinação de config.