> ## Documentation Index
> Fetch the complete documentation index at: https://docs.jelou.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# MCP

> Cómo Jelou Functions genera automáticamente herramientas MCP para que tus agentes IA invoquen funciones como tools.

## Auto-generación de herramientas MCP

Cuando creas una función con `define()`, se expone automáticamente como una herramienta [MCP](https://modelcontextprotocol.io/) (Model Context Protocol). Tus agentes IA pueden descubrir e invocar tu función como un tool sin configuración adicional.

## Ejemplo

Para esta función:

```typescript index.ts theme={null}
import { define, z } from "@jelou/functions";

export default define({
  name: "consultar-saldo",
  description: "Consulta el saldo de un cliente por número de teléfono",
  input: z.object({
    telefono: z.string().min(10).describe("Número de teléfono con código de país"),
  }),
  output: z.object({
    nombre: z.string(),
    saldo: z.number(),
    moneda: z.string(),
  }),
  handler: async (input, ctx) => {
    ctx.log("Consultando saldo", { telefono: input.telefono });
    return { nombre: "María García", saldo: 150.00, moneda: "USD" };
  },
});
```

El endpoint `/mcp` expone este esquema:

```json theme={null}
{
  "name": "consultar-saldo",
  "description": "Consulta el saldo de un cliente por número de teléfono",
  "inputSchema": {
    "type": "object",
    "properties": {
      "telefono": {
        "type": "string",
        "minLength": 10,
        "description": "Número de teléfono con código de país"
      }
    },
    "required": ["telefono"]
  }
}
```

## El campo `description`: lo más importante para MCP

<Warning>
  El campo `description` de tu `define()` es lo que el agente IA lee para decidir **cuándo** invocar tu herramienta. Si la descripción es vaga, el agente no sabrá cuándo usarla — o peor, la usará en el momento incorrecto.
</Warning>

| ❌ Vaga              | ✅ Específica                                                                     | Por qué importa                                       |
| ------------------- | -------------------------------------------------------------------------------- | ----------------------------------------------------- |
| `"Maneja usuarios"` | `"Busca un usuario por email o teléfono y retorna su perfil con saldo"`          | El agente sabe exactamente qué datos puede obtener    |
| `"Envía mensaje"`   | `"Envía un mensaje de WhatsApp a un número con código de país (ej: 593…)"`       | El agente sabe el canal y el formato esperado         |
| `"Consulta API"`    | `"Consulta el estado de un envío por tracking number en la API de Servientrega"` | El agente sabe para qué proveedor y qué dato necesita |

### Anotaciones `.describe()` en campos

Las anotaciones `.describe()` de Zod se convierten en descripciones de parámetros del tool MCP. Esto es lo que ven los agentes IA cuando descubren tu función:

```typescript theme={null}
input: z.object({
  telefono: z.string().min(10).describe("Número con código de país, ej: 593987654321"),
  tipo: z.enum(["prepago", "pospago"]).describe("Tipo de plan del cliente"),
  incluirHistorial: z.boolean().default(false).describe("Si incluir las últimas 5 transacciones"),
})
```

<Tip>
  Escribe descripciones claras y específicas en `.describe()`. Los agentes IA usan estas descripciones para decidir qué valores pasar a tu función.
</Tip>

## Probar el endpoint MCP

Inicia el servidor local con `jelou functions dev` y consulta el esquema MCP:

<CodeGroup>
  ```bash curl theme={null}
  curl http://localhost:3000/mcp
  ```

  ```json Respuesta theme={null}
  {
    "tools": [
      {
        "name": "consultar-saldo",
        "description": "Consulta el saldo de un cliente por número de teléfono",
        "inputSchema": {
          "type": "object",
          "properties": {
            "telefono": {
              "type": "string",
              "minLength": 10,
              "description": "Número de teléfono con código de país"
            }
          },
          "required": ["telefono"]
        }
      }
    ]
  }
  ```
</CodeGroup>

Invoca la función directamente:

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST http://localhost:3000 \
    -H "Content-Type: application/json" \
    -d '{"telefono": "593987654321"}'
  ```

  ```json Respuesta 200 theme={null}
  {
    "nombre": "María García",
    "saldo": 150.00,
    "moneda": "USD"
  }
  ```
</CodeGroup>

En producción:

```bash theme={null}
curl https://consultar-saldo.fn.jelou.ai/mcp \
  -H "X-Jelou-Token: jfn_rt_abc123..."
```

<Warning>
  En producción, el endpoint `/mcp` requiere el header `X-Jelou-Token`. Sin token, recibirás `401 Unauthorized`. Solo `/__health` y `/openapi.json` son públicos sin token.
</Warning>

## Desactivar MCP

Si tu función no debe ser descubierta como herramienta (por ejemplo, un webhook que solo recibe callbacks), desactiva MCP:

```typescript theme={null}
config: { mcp: false }
```

Cuando MCP está desactivado, el endpoint `/mcp` retorna 404.

## ¿Cómo lo usan los agentes?

Cuando configuras un agente IA en Jelou Brain Studio y le asignas funciones como tools, el agente:

1. Descubre las herramientas disponibles vía el endpoint `/mcp`
2. Lee el nombre, descripción y esquema de entrada
3. Decide cuándo invocar la herramienta basándose en la conversación del usuario
4. Envía los parámetros validados a tu función
5. Recibe la respuesta y la incorpora a la conversación

Todo esto sucede automáticamente — solo necesitas escribir la función con `define()` y asignarla al agente.

## Multi-tool MCP

Cuando usas `app()`, un solo servidor MCP en `/mcp` registra automáticamente todos los tools. Cada tool aparece como una herramienta independiente con su nombre, descripción y esquema.

Para excluir un tool específico del registro MCP, usa `mcp: false` en su config:

```typescript theme={null}
import { app, define, z } from "@jelou/functions";

export default app({
  tools: {
    consultarSaldo: define({
      description: "Consulta el saldo de un cliente",
      input: z.object({ telefono: z.string().min(10) }),
      handler: async (input) => ({ saldo: 150.00 }),
    }),
    webhookPagos: define({
      description: "Recibe callbacks de pagos",
      input: z.object({ transactionId: z.string() }),
      config: { mcp: false },
      handler: async (input) => ({ received: true }),
    }),
  },
});
```

En este ejemplo, los agentes IA descubren `consultarSaldo` vía MCP pero `webhookPagos` solo es accesible por HTTP directo en `/webhook-pagos`.

<Tip>
  Consulta la [guía completa de multi-tool](/guides/functions/multi-tool) para más detalles sobre rutas auto-generadas y combinación de config.
</Tip>

<Card title="Conectar en Brain Studio" icon="puzzle-piece" href="/guides/functions/brain">
  Guía paso a paso para configurar tu función como servidor MCP externo en Brain Studio.
</Card>
