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

# Usar herramientas MCP

> Conecta un servidor MCP al recurso de Respuestas de la API MKA1, limita las herramientas permitidas y, opcionalmente, requiere la aprobación del usuario final.

Utiliza herramientas MCP cuando quieras que la API de MKA1 llame herramientas de un servidor MCP externo durante una respuesta.
Define el servidor MCP en `tools`.
Limita qué herramientas puede llamar el modelo con `allowed_tools`.
Usa `require_approval` cuando quieras que tu aplicación se detenga y pida aprobación al usuario final antes de ejecutar la herramienta.

Utiliza `X-On-Behalf-Of` para identificar al usuario final de la API de MKA1.
Pasa las credenciales del servidor MCP upstream en la definición de la herramienta MCP.

## Llamar directamente a una herramienta MCP

Establece `require_approval` en `'never'` cuando la herramienta pueda ejecutarse de inmediato.

<CodeGroup>
  ```bash CLI theme={null}
  mka1 llm responses create --body '{
    "model": "meetkai:functionary-es-mini",
    "instructions": "Eres un asistente de gestión de proyectos con acceso a Linear vía MCP. Usa las herramientas de Linear cuando el usuario pregunte sobre tareas, bugs o proyectos. Mantén la respuesta final concisa.",
    "input": "Lista mi incidencia de Linear más reciente asignada a mí.",
    "store": true,
    "stream": false,
    "tools": [
      {
        "type": "mcp",
        "server_label": "Linear MCP",
        "server_description": "Accede a incidencias de Linear a través de MCP.",
        "server_url": "https://mcp.linear.app/mcp",
        "allowed_tools": ["issues.list"],
        "headers": {
          "Authorization": "Bearer <linear-api-key>"
        },
        "require_approval": "never"
      }
    ]
  }' \
    -H 'X-On-Behalf-Of: <end-user-id>'
  ```

  ```ts MKA1 SDK theme={null}
  import { SDK } from '@meetkai/mka1';
  import type * as components from '@meetkai/mka1/models/components';

  const mka1 = new SDK({
    bearerAuth: `Bearer ${YOUR_API_KEY}`,
  });

  const response = await mka1.llm.responses.create(
    {
      model: 'meetkai:functionary-es-mini',
      instructions:
        'Eres un asistente de gestión de proyectos con acceso a Linear vía MCP. Usa las herramientas de Linear cuando el usuario pregunte sobre tareas, bugs o proyectos. Mantén la respuesta final concisa.',
      input: 'Lista mi incidencia de Linear más reciente asignada a mí.',
      store: true,
      stream: false,
      tools: [
        {
          type: 'mcp',
          serverLabel: 'Linear MCP',
          serverDescription: 'Accede a incidencias de Linear a través de MCP.',
          serverUrl: 'https://mcp.linear.app/mcp',
          allowedTools: ['issues.list'],
          headers: {
            Authorization: `Bearer ${process.env.LINEAR_API_KEY}`,
          },
          requireApproval: 'never',
        },
      ],
    },
    { headers: { 'X-On-Behalf-Of': '<end-user-id>' } },
  );

  // Las llamadas a herramientas MCP aparecen como elementos function_call en la salida
  const mcpCalls = response.output.filter(
    (item): item is components.MCPToolCall => item.type === 'mcp_call',
  );

  const assistantText = response.output
    .filter(
      (item): item is components.OutputMessage =>
        item.type === 'message' && item.role === 'assistant',
    )
    .flatMap(item =>
      item.content.flatMap(content =>
        content.type === 'output_text' ? [content.text] : [],
      ),
    )
    .join('\n\n')
    .trim();

  console.log(assistantText);
  ```

  ```ts OpenAI SDK theme={null}
  import OpenAI from 'openai';

  const openai = new OpenAI({
    apiKey: '<mka1-api-key>',
    baseURL: 'https://apigw.mka1.com/api/v1/llm/',
    defaultHeaders: { 'X-On-Behalf-Of': '<end-user-id>' },
  });

  const response = await openai.responses.create({
    model: 'meetkai:functionary-es-mini',
    instructions:
      'Eres un asistente de gestión de proyectos con acceso a Linear vía MCP. Usa las herramientas de Linear cuando el usuario pregunte sobre tareas, bugs o proyectos. Mantén la respuesta final concisa.',
    input: 'Lista mi incidencia de Linear más reciente asignada a mí.',
    store: true,
    stream: false,
    tools: [
      {
        type: 'mcp',
        server_label: 'Linear MCP',
        server_description: 'Accede a incidencias de Linear a través de MCP.',
        server_url: 'https://mcp.linear.app/mcp',
        allowed_tools: ['issues.list'],
        headers: {
          Authorization: `Bearer ${process.env.LINEAR_API_KEY}`,
        },
        require_approval: 'never',
      },
    ],
  });

  // Las llamadas a herramientas MCP aparecen como elementos function_call en la salida
  const functionCall = response.output.find((item) => item.type === 'function_call');
  const message = response.output.find((item) => item.type === 'message');
  console.log(response.output_text);
  ```

  ```csharp C# SDK theme={null}
  using MeetKai.MKA1;
  using MeetKai.MKA1.Types.Components;

  var sdk = new SDK(
      bearerAuth: "Bearer <mka1-api-key>",
      serverUrl: "https://apigw.mka1.com"
  );

  var response = await sdk.Llm.Responses.CreateAsync(
      new ResponsesCreateRequest()
      {
          Model = "meetkai:functionary-es-mini",
          Input = ResponsesCreateRequestInput.CreateStr(
              "Lista mi incidencia de Linear más reciente asignada a mí."
          ),
      }
  );

  // Las herramientas MCP requieren un endpoint de servidor MCP en funcionamiento.
  // El SDK construye la misma forma de solicitud que los ejemplos de TypeScript y curl.
  Console.WriteLine(response);
  ```

  ```python Python SDK theme={null}
  from mka1 import SDK
  import os

  sdk = SDK(bearer_auth="Bearer YOUR_API_KEY")

  response = sdk.llm.responses.create(
      model="meetkai:functionary-es-mini",
      instructions="Eres un asistente de gestión de proyectos con acceso a Linear vía MCP. Usa las herramientas de Linear cuando el usuario pregunte sobre tareas, bugs o proyectos. Mantén la respuesta final concisa.",
      input="Lista mi incidencia de Linear más reciente asignada a mí.",
      store=True,
      stream=False,
      tools=[
          {
              "type": "mcp",
              "server_label": "Linear MCP",
              "server_description": "Accede a incidencias de Linear a través de MCP.",
              "server_url": "https://mcp.linear.app/mcp",
              "allowed_tools": ["issues.list"],
              "headers": {
                  "Authorization": f"Bearer {os.environ['LINEAR_API_KEY']}",
              },
              "require_approval": "never",
          },
      ],
  )

  print(response.output_text)
  ```

  ```bash bash theme={null}
  curl https://apigw.mka1.com/api/v1/llm/responses \
    --request POST \
    --header 'Content-Type: application/json' \
    --header 'Authorization: Bearer <mka1-api-key>' \
    --header 'X-On-Behalf-Of: <end-user-id>' \
    --data '{
      "model": "meetkai:functionary-es-mini",
      "instructions": "Eres un asistente de gestión de proyectos con acceso a Linear vía MCP. Usa las herramientas de Linear cuando el usuario pregunte sobre tareas, bugs o proyectos. Mantén la respuesta final concisa.",
      "input": "Lista mi incidencia de Linear más reciente asignada a mí.",
      "store": true,
      "stream": false,
      "tools": [
        {
          "type": "mcp",
          "server_label": "Linear MCP",
          "server_description": "Accede a incidencias de Linear a través de MCP.",
          "server_url": "https://mcp.linear.app/mcp",
          "allowed_tools": ["issues.list"],
          "headers": {
            "Authorization": "Bearer <linear-api-key>"
          },
          "require_approval": "never"
        }
      ]
    }'
  ```
</CodeGroup>

Este es el flujo más simple.
El modelo llama a la herramienta MCP permitida y devuelve el mensaje final del asistente en una sola solicitud.

El array de respuesta `output` contiene:

1. `function_call` — la llamada del modelo a la herramienta descubierta por MCP
2. `function_call_output` — los datos devueltos por el servidor MCP
3. `message` — la respuesta de texto del modelo resumiendo los resultados

## Requerir aprobación del usuario final

Establece `require_approval` en `'always'` cuando tu aplicación deba detenerse y esperar una decisión de aprobación.
En este flujo, crea la respuesta en modo background, haz polling y busca un elemento `mcp_approval_request` en `output`.

<CodeGroup>
  ```bash CLI theme={null}
  # Paso 1: Crear una respuesta en segundo plano con aprobación requerida
  mka1 llm responses create --body '{
    "model": "meetkai:functionary-es-mini",
    "instructions": "Eres un asistente de gestión de proyectos con acceso a Linear vía MCP.",
    "input": "Lista mi incidencia de Linear más reciente asignada a mí.",
    "background": true,
    "store": true,
    "stream": false,
    "tools": [
      {
        "type": "mcp",
        "server_label": "Linear MCP",
        "server_url": "https://mcp.linear.app/mcp",
        "allowed_tools": ["issues.list"],
        "headers": { "Authorization": "Bearer <linear-api-key>" },
        "require_approval": "always"
      }
    ]
  }'

  # Paso 2: Haz polling de la respuesta por id hasta que aparezca un mcp_approval_request
  mka1 llm responses get --response-id <response-id>

  # Paso 3: Envía la aprobación para continuar
  mka1 llm responses create --body '{
    "model": "meetkai:functionary-es-mini",
    "previous_response_id": "<response-id>",
    "input": [
      {
        "type": "mcp_approval_response",
        "approval_request_id": "<approval-request-id>",
        "approve": true
      }
    ],
    "store": true,
    "stream": false
  }'
  ```

  ```ts MKA1 SDK theme={null}
  import { SDK } from '@meetkai/mka1';
  import type * as components from '@meetkai/mka1/models/components';

  const mka1 = new SDK({
    bearerAuth: `Bearer ${YOUR_API_KEY}`,
  });

  // Paso 1: Crear una respuesta en segundo plano con aprobación requerida
  let pendingResponse = await mka1.llm.responses.create(
    {
      model: 'meetkai:functionary-es-mini',
      instructions:
        'Eres un asistente de gestión de proyectos con acceso a Linear vía MCP. Usa las herramientas de Linear cuando el usuario pregunte sobre tareas, bugs o proyectos. Mantén la respuesta final concisa.',
      input: 'Lista mi incidencia de Linear más reciente asignada a mí.',
      background: true,
      store: true,
      stream: false,
      tools: [
        {
          type: 'mcp',
          serverLabel: 'Linear MCP',
          serverDescription: 'Accede a incidencias de Linear a través de MCP.',
          serverUrl: 'https://mcp.linear.app/mcp',
          allowedTools: ['issues.list'],
          headers: {
            Authorization: `Bearer ${process.env.LINEAR_API_KEY}`,
          },
          requireApproval: 'always',
        },
      ],
    },
    { headers: { 'X-On-Behalf-Of': '<end-user-id>' } },
  );

  // Paso 2: Haz polling hasta que aparezca una solicitud de aprobación
  let approvalRequest: components.MCPApprovalRequest | undefined;

  while (
    pendingResponse.status === 'queued' ||
    pendingResponse.status === 'in_progress'
  ) {
    approvalRequest = pendingResponse.output.find(
      (item): item is components.MCPApprovalRequest =>
        item.type === 'mcp_approval_request',
    );

    if (approvalRequest) break;

    await new Promise(resolve => setTimeout(resolve, 1000));

    pendingResponse = await mka1.llm.responses.get(
      { responseId: pendingResponse.id },
      { headers: { 'X-On-Behalf-Of': '<end-user-id>' } },
    );
  }

  if (!approvalRequest) {
    throw new Error(`No se encontró solicitud de aprobación. La respuesta terminó con ${pendingResponse.status}.`);
  }

  // Paso 3: Muestra al usuario lo que el modelo quiere hacer
  console.log('Servidor:', approvalRequest.serverLabel);
  console.log('Herramienta:', approvalRequest.name);
  console.log('Argumentos:', approvalRequest.arguments);

  // Paso 4: Envía la aprobación (o denegación) para continuar
  const approve = true; // Reemplaza con la decisión de tu UI

  const continuedResponse = await mka1.llm.responses.create(
    {
      model: 'meetkai:functionary-es-mini',
      previousResponseId: pendingResponse.id,
      input: [
        {
          type: 'mcp_approval_response',
          approvalRequestId: approvalRequest.id,
          approve,
        },
      ],
      store: true,
      stream: false,
    },
    { headers: { 'X-On-Behalf-Of': '<end-user-id>' } },
  );

  const assistantText = continuedResponse.output
    .filter(
      (item): item is components.OutputMessage =>
        item.type === 'message' && item.role === 'assistant',
    )
    .flatMap(item =>
      item.content.flatMap(content =>
        content.type === 'output_text' ? [content.text] : [],
      ),
    )
    .join('\n\n')
    .trim();

  console.log(assistantText);
  ```

  ```ts OpenAI SDK theme={null}
  import OpenAI from 'openai';

  const openai = new OpenAI({
    apiKey: '<mka1-api-key>',
    baseURL: 'https://apigw.mka1.com/api/v1/llm/',
    defaultHeaders: { 'X-On-Behalf-Of': '<end-user-id>' },
  });

  // Paso 1: Crear una respuesta en segundo plano con aprobación requerida
  let pendingResponse = await openai.responses.create({
    model: 'meetkai:functionary-es-mini',
    instructions:
      'Eres un asistente de gestión de proyectos con acceso a Linear vía MCP. Usa las herramientas de Linear cuando el usuario pregunte sobre tareas, bugs o proyectos. Mantén la respuesta final concisa.',
    input: 'Lista mi incidencia de Linear más reciente asignada a mí.',
    background: true,
    store: true,
    stream: false,
    tools: [
      {
        type: 'mcp',
        server_label: 'Linear MCP',
        server_description: 'Accede a incidencias de Linear a través de MCP.',
        server_url: 'https://mcp.linear.app/mcp',
        allowed_tools: ['issues.list'],
        headers: {
          Authorization: `Bearer ${process.env.LINEAR_API_KEY}`,
        },
        require_approval: 'always',
      },
    ],
  });

  // Paso 2: Haz polling hasta que aparezca una solicitud de aprobación
  let approvalRequest;

  while (
    pendingResponse.status === 'queued' ||
    pendingResponse.status === 'in_progress'
  ) {
    approvalRequest = pendingResponse.output.find(
      (item) => item.type === 'mcp_approval_request',
    );

    if (approvalRequest) break;

    await new Promise(resolve => setTimeout(resolve, 1000));
    pendingResponse = await openai.responses.retrieve(pendingResponse.id);
  }

  if (!approvalRequest) {
    throw new Error(`No se encontró solicitud de aprobación. La respuesta terminó con ${pendingResponse.status}.`);
  }

  // Paso 3: Muestra al usuario lo que el modelo quiere hacer
  console.log('Servidor:', approvalRequest.server_label);
  console.log('Herramienta:', approvalRequest.name);
  console.log('Argumentos:', approvalRequest.arguments);

  // Paso 4: Envía la aprobación (o denegación) para continuar
  const approve = true; // Reemplaza con la decisión de tu UI

  const continuedResponse = await openai.responses.create({
    model: 'meetkai:functionary-es-mini',
    previous_response_id: pendingResponse.id,
    input: [
      {
        type: 'mcp_approval_response',
        approval_request_id: approvalRequest.id,
        approve,
      },
    ],
    store: true,
    stream: false,
  });

  console.log(continuedResponse.output_text);
  ```

  ```csharp C# SDK theme={null}
  using MeetKai.MKA1;
  using MeetKai.MKA1.Types.Components;

  var sdk = new SDK(
      bearerAuth: "Bearer <mka1-api-key>",
      serverUrl: "https://apigw.mka1.com"
  );

  // El flujo de aprobación MCP requiere un servidor MCP en funcionamiento.
  // El SDK puede construir solicitudes en segundo plano con herramientas MCP.
  var request = new ResponsesCreateRequest()
  {
      Model = "meetkai:functionary-es-mini",
      Input = ResponsesCreateRequestInput.CreateStr("Ejecuta la herramienta aprobada."),
      Background = true,
  };

  Console.WriteLine(request);
  ```

  ```python Python SDK theme={null}
  import os
  import time

  # Paso 1: Crear una respuesta en segundo plano con aprobación requerida
  pending = sdk.llm.responses.create(
      model="meetkai:functionary-es-mini",
      instructions="Eres un asistente de gestión de proyectos con acceso a Linear vía MCP. Usa las herramientas de Linear cuando el usuario pregunte sobre tareas, bugs o proyectos. Mantén la respuesta final concisa.",
      input="Lista mi incidencia de Linear más reciente asignada a mí.",
      background=True,
      store=True,
      stream=False,
      tools=[
          {
              "type": "mcp",
              "server_label": "Linear MCP",
              "server_description": "Accede a incidencias de Linear a través de MCP.",
              "server_url": "https://mcp.linear.app/mcp",
              "allowed_tools": ["issues.list"],
              "headers": {
                  "Authorization": f"Bearer {os.environ['LINEAR_API_KEY']}",
              },
              "require_approval": "always",
          },
      ],
  )

  # Paso 2: Haz polling hasta que aparezca una solicitud de aprobación
  approval_request = None
  while pending.status in ("queued", "in_progress"):
      for item in pending.output:
          if item.type == "mcp_approval_request":
              approval_request = item
              break
      if approval_request:
          break
      time.sleep(1)
      pending = sdk.llm.responses.get(response_id=pending.id)

  # Paso 3: Muestra al usuario lo que el modelo quiere hacer
  print("Servidor:", approval_request.server_label)
  print("Herramienta:", approval_request.name)
  print("Argumentos:", approval_request.arguments)

  # Paso 4: Envía la aprobación (o denegación) para continuar
  continued = sdk.llm.responses.create(
      model="meetkai:functionary-es-mini",
      previous_response_id=pending.id,
      input=[
          {
              "type": "mcp_approval_response",
              "approval_request_id": approval_request.id,
              "approve": True,
          },
      ],
      store=True,
      stream=False,
  )

  print(continued.output_text)
  ```

  ```bash bash theme={null}
  # Paso 1: Crear respuesta en segundo plano con aprobación requerida
  RESPONSE=$(curl -s https://apigw.mka1.com/api/v1/llm/responses \
    --request POST \
    --header 'Content-Type: application/json' \
    --header 'Authorization: Bearer <mka1-api-key>' \
    --header 'X-On-Behalf-Of: <end-user-id>' \
    --data '{
      "model": "meetkai:functionary-es-mini",
      "instructions": "Eres un asistente de gestión de proyectos con acceso a Linear vía MCP.",
      "input": "Lista mi incidencia de Linear más reciente asignada a mí.",
      "background": true,
      "store": true,
      "stream": false,
      "tools": [
        {
          "type": "mcp",
          "server_label": "Linear MCP",
          "server_url": "https://mcp.linear.app/mcp",
          "allowed_tools": ["issues.list"],
          "headers": { "Authorization": "Bearer <linear-api-key>" },
          "require_approval": "always"
        }
      ]
    }')

  RESPONSE_ID=$(echo "$RESPONSE" | jq -r '.id')

  # Paso 2: Haz polling hasta que aparezca la solicitud de aprobación
  while true; do
    RESPONSE=$(curl -s "https://apigw.mka1.com/api/v1/llm/responses/$RESPONSE_ID" \
      --header 'Authorization: Bearer <mka1-api-key>' \
      --header 'X-On-Behalf-Of: <end-user-id>')

    APPROVAL_ID=$(echo "$RESPONSE" | jq -r '.output[] | select(.type == "mcp_approval_request") | .id')
    if [ -n "$APPROVAL_ID" ] && [ "$APPROVAL_ID" != "null" ]; then break; fi
    sleep 1
  done

  # Paso 3: Envía la aprobación para continuar
  curl https://apigw.mka1.com/api/v1/llm/responses \
    --request POST \
    --header 'Content-Type: application/json' \
    --header 'Authorization: Bearer <mka1-api-key>' \
    --header 'X-On-Behalf-Of: <end-user-id>' \
    --data "{
      \"model\": \"meetkai:functionary-es-mini\",
      \"previous_response_id\": \"$RESPONSE_ID\",
      \"input\": [
        {
          \"type\": \"mcp_approval_response\",
          \"approval_request_id\": \"$APPROVAL_ID\",
          \"approve\": true
        }
      ],
      \"store\": true,
      \"stream\": false
    }"
  ```
</CodeGroup>

Si el usuario final rechaza la llamada a la herramienta, envía `approve: false`.
También puedes incluir un campo `reason` en el elemento `mcp_approval_response`.

Para interfaces de aprobación, muestra:

* `server_label` — qué servidor MCP se está usando
* `name` — qué herramienta quiere llamar el modelo
* `arguments` — qué argumentos planea enviar

## Referencia de definición de herramienta MCP

| Parámetro            | Tipo                    | Predeterminado | Descripción                                                                 |
| -------------------- | ----------------------- | -------------- | --------------------------------------------------------------------------- |
| `type`               | `"mcp"`                 | —              | Requerido. Identifica esto como una herramienta MCP.                        |
| `server_label`       | string                  | —              | Requerido. Nombre para mostrar del servidor MCP.                            |
| `server_url`         | string                  | —              | URL del endpoint del servidor MCP.                                          |
| `server_description` | string                  | —              | Descripción opcional del propósito del servidor.                            |
| `allowed_tools`      | string\[]               | —              | Limita qué herramientas puede llamar el modelo.                             |
| `headers`            | object                  | —              | Cabeceras a pasar al servidor MCP (por ejemplo, tokens de autenticación).   |
| `require_approval`   | `"always"` \| `"never"` | `"always"`     | Si se debe pausar para aprobación del usuario final antes de llamar.        |
| `connector_id`       | string                  | —              | Usa un conector preconfigurado en vez de una URL de servidor personalizada. |

Las credenciales pasadas en `headers` se ocultan automáticamente en las respuestas almacenadas y en los eventos de streaming.

## Próximos pasos

* Consulta [generar una respuesta](/es/docs/generate-a-response) para el flujo básico de Respuestas
* Consulta [respuestas en segundo plano](/es/docs/background-responses) para patrones de polling y streaming
* Consulta [conversaciones](/es/docs/conversations) si quieres mantener el mismo usuario final en un hilo más largo
* Revisa la [referencia de la API](/es/api-reference/introduction) para el esquema completo de Respuestas
