# Servidor ACP de CLI de Copilot

Obtenga información sobre el servidor de protocolo de cliente del agente CLI de GitHub Copilot.

> \[!NOTE]
> La compatibilidad con ACP en CLI de GitHub Copilot está en versión preliminar pública y está sujeta a cambios.

## Visión general

El Protocolo de cliente del agente (ACP) es un protocolo que normaliza la comunicación entre clientes (como editores de código e IDE) y agentes (como CLI de Copilot). Para obtener más información sobre este protocolo, consulte la [introducción oficial](https://agentclientprotocol.com/get-started/introduction).

## Casos de uso

* **Integraciones de IDE:** Incorpore Copilot soporte en cualquier editor o en cualquier entorno de desarrollo.
* **Canalizaciones de CI/CD:** orqueste tareas de codificación de agente en flujos de trabajo automatizados.
* **Portales personalizados:** Cree interfaces especializadas para los flujos de trabajo específicos de los desarrolladores.
* **Sistemas multiagente:** Coordinarse Copilot con otros agentes de IA mediante un protocolo estándar.

## Iniciar el servidor ACP

Use la `--acp` opción del `copilot` comando para iniciar el servidor ACP de la CLI. Puede especificar el modo de transporte con las `--stdio` opciones o `--port` . Si no se especifica ningún modo de transporte, el servidor tiene como valor predeterminado el modo stdio.

El modo ACP permite que las sesiones con un proveedor`COPILOT_PROVIDER_*` de bring-your-own-key (BYOK) configurado (variables de entorno) se ejecuten sin GitHub inicio de sesión y coincidan con el comportamiento del `-p`modo /interactivo.

### Opciones aplicadas a cada sesión

La solicitud ACP `session/new` solo permite que un cliente establezca algunos parámetros de sesión, como el directorio de trabajo y los servidores MCP que se van a usar. No incluye filtros de herramientas ni ajustes de razonamiento. Para configurarlos, pase las opciones correspondientes al **iniciar el servidor**. El servidor almacena los valores y los aplica como configuración inicial para cada sesión que crea o carga, para cualquier cliente que se conecte. El cliente que se conecta no elige estos valores; los elige quien inicia el servidor.

| Opción de servidor                           | Valor aceptado                                                       | Efecto en cada sesión                                  |
| -------------------------------------------- | -------------------------------------------------------------------- | ------------------------------------------------------ |
| `--available-tools=TOOL ...`                 | Lista entrecomillada y separada por comas de nombres de herramientas | La sesión solo puede usar las herramientas enumeradas. |
| `--excluded-tools=TOOL ...`                  | Lista entrecomillada y separada por comas de nombres de herramientas | Las herramientas enumeradas se quitan de la sesión.    |
| `--effort=LEVEL`, `--reasoning-effort=LEVEL` |                                                                      |                                                        |
| `low`, `medium`, `high`, `xhigh` o `max`     | Establece el esfuerzo inicial de razonamiento de la sesión.          |                                                        |

Por ejemplo, este comando inicia un servidor cuyas sesiones todas utilizan el nivel máximo de esfuerzo de razonamiento y exponen solo las herramientas `bash` y `view`:

```bash
copilot --acp --port 3000 --effort=max --available-tools="bash,view"
```

Todas las sesiones que el cliente conectado abre en ese servidor heredan esa configuración. Dado que los valores se fijan cuando se inicia el servidor, un cliente no puede cambiarlos por sesión a través de `session/new`.

### modo stdio

El modo stdio se deduce de forma predeterminada cuando se inicia el servidor ACP. También puede usar la `--stdio` opción para la desambiguación.

```bash
copilot --acp --stdio
```

### Modo TCP

Si la `--port` opción se proporciona en combinación con la `--acp` opción , el servidor se inicia en modo TCP.

```bash
copilot --acp --port 3000
```

### Elección entre stdio y TCP

Ambos modos de transporte llevan los mismos mensajes ACP, codificados como JSON delimitado por nueva línea (NDJSON). Solo difieren en cómo se conecta un cliente al servidor y cómo se administra el ciclo de vida del servidor. Los dos modos son mutuamente excluyentes: pasar a la vez `--stdio` y `--port` se rechaza.

| Aspecto                        | modo stdio                                                                                                                                                                  | Modo TCP                                                                                                                                                                            |
| ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Cómo se conecta el cliente** | El cliente lanza `copilot --acp` como un proceso hijo e intercambia mensajes a través de la entrada estándar y la salida estándar del proceso.                              | El servidor abre un agente de escucha TCP al que se conectan los clientes a través de un socket de red. De forma predeterminada, se vincula a la dirección de loopback `127.0.0.1`. |
| **Número de clientes**         | Un solo cliente: el proceso que generó el servidor y posee la canalización.                                                                                                 | El agente de escucha acepta conexiones de socket, cada una de las cuales se administra como su propia conexión de agente.                                                           |
| **Ciclo de vida**              | Vinculado al proceso principal. Cuando se cierra el flujo de entrada —porque el proceso principal finaliza o cierra la canalización— el servidor se cierra automáticamente. | Independiente de cualquier cliente único. El servidor sigue escuchando en el puerto hasta que se detiene, por ejemplo, con <kbd>Ctrl</kbd>+<kbd>C</kbd>.                            |
| **Salida estándar**            | Reservado para el flujo de protocolo NDJSON, por lo que no se puede usar para registros u otro texto.                                                                       | Gratis para otro uso, ya que el tráfico de protocolo viaja a través del socket.                                                                                                     |

Cuándo usar cada modo:

* Use **el modo stdio** cuando un editor, un IDE o un script inicie CLI de Copilot directamente como subproceso. Este es el valor predeterminado y la configuración recomendada para la integración del IDE, ya que el transporte se establece automáticamente cuando el proceso se inicia y se descompone cuando se cierra.
* Use **el modo TCP** cuando un cliente necesite llegar al servidor a través de un socket en lugar de una canalización, por ejemplo, desde un proceso o contenedor independiente, o al conectarse a un servidor de larga duración en un puerto conocido.

## Ejemplo: integración con el servidor ACP

El ejemplo siguiente es una aplicación cliente que usa Copilot mediante la interacción con CLI de GitHub Copilotel servidor ACP. Inicia el servidor ACP en modo stdio, abre una sesión, le pide que escriba un mensaje, lo envíe e imprima la respuesta transmitida.

Hay un ecosistema creciente de bibliotecas para interactuar con servidores ACP mediante programación. En este ejemplo se usa la [biblioteca TypeScript ACP](https://agentclientprotocol.com/libraries/typescript).

Para ejecutar este ejemplo, necesita las siguientes dependencias:

* [Node.js](https://nodejs.org) versión 18 o posterior.
* CLI de GitHub Copilot, instalado y autenticado con GitHub o configurado con un proveedor BYOK (consulte [Inicio del servidor ACP](#starting-the-acp-server)).
* El `@agentclientprotocol/sdk` paquete, que proporciona la biblioteca TypeScript ACP. Instálela mediante la ejecución de `npm install @agentclientprotocol/sdk`.

```typescript copy
import * as acp from "@agentclientprotocol/sdk";
import { spawn } from "node:child_process";
import { Readable, Writable } from "node:stream";
import * as readline from "node:readline/promises";

async function main() {
  const executable = process.env.COPILOT_CLI_PATH ?? "copilot";

  // ACP uses standard input/output (stdin/stdout) for transport; we pipe these for the NDJSON stream.
  const copilotProcess = spawn(executable, ["--acp", "--stdio"], {
    stdio: ["pipe", "pipe", "inherit"],
  });

  if (!copilotProcess.stdin || !copilotProcess.stdout) {
    throw new Error("Failed to start Copilot ACP process with piped stdio.");
  }

  // Create ACP streams (NDJSON over stdio)
  const output = Writable.toWeb(copilotProcess.stdin) as WritableStream<Uint8Array>;
  const input = Readable.toWeb(copilotProcess.stdout) as ReadableStream<Uint8Array>;
  const stream = acp.ndJsonStream(output, input);

  const client: acp.Client = {
    async requestPermission(params) {
      // This example should not trigger tool calls; if it does, refuse.
      return { outcome: { outcome: "cancelled" } };
    },

    async sessionUpdate(params) {
      const update = params.update;

      if (update.sessionUpdate === "agent_message_chunk" && update.content.type === "text") {
        process.stdout.write(update.content.text);
      }
    },
  };

  const connection = new acp.ClientSideConnection((_agent) => client, stream);

  await connection.initialize({
    protocolVersion: acp.PROTOCOL_VERSION,
    clientCapabilities: {},
  });

  const sessionResult = await connection.newSession({
    cwd: process.cwd(),
    mcpServers: [],
  });

  process.stdout.write("Session started!\n");

  // Ask the user to enter a prompt instead of using a hard-coded one.
  const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
  });
  const promptText = await rl.question("Enter a prompt: ");
  rl.close();

  const promptResult = await connection.prompt({
    sessionId: sessionResult.sessionId,
    prompt: [{ type: "text", text: promptText }],
  });

  process.stdout.write("\n");

  if (promptResult.stopReason !== "end_turn") {
    process.stderr.write(`Prompt finished with stopReason=${promptResult.stopReason}\n`);
  }

  // Best-effort cleanup
  copilotProcess.stdin.end();
  copilotProcess.kill("SIGTERM");
  await new Promise<void>((resolve) => {
    copilotProcess.once("exit", () => resolve());
    setTimeout(() => resolve(), 2000);
  });
}

main().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});
```

Para ejecutar el ejemplo:

1. Guarde el código anterior en un archivo denominado `acp-client.ts`.
2. Ejecute el archivo con `npx tsx`, que ejecuta TypeScript directamente sin un paso de compilación independiente:

   ```bash
   npx tsx acp-client.ts
   ```

## Uso de comandos de barra

CLI de GitHub CopilotLos comandos de barra diagonal integrados se pueden ejecutar a través de ACP. Para invocar uno, envíalo como una solicitud normal cuyo texto sea el comando, pasado como un único bloque de contenido de texto; por ejemplo, `/context` o `/session info`. El servidor reconoce el comando y lo ejecuta directamente: comandos informativos como `/usage` o `/context` devuelven su salida sin invocar el modelo, mientras que comandos de acción como `/plan` o `/review` inician la tarea del agente correspondiente. En cualquier caso, el texto del comando no se envía al modelo como una pregunta.

### Detección de comandos disponibles

El servidor anuncia los comandos que admite a través de la notificación de sesión ACP `available_commands_update` estándar. Se envía después de que se cree o se cargue una sesión, y de nuevo cada vez que cambie el conjunto de habilidades; por ejemplo, cuando las habilidades terminen de cargarse. Esta lista anunciada es el conjunto de comandos autoritativo y siempre actual que se puede ejecutar a través de ACP y los clientes suelen exponerlo en un menú de comandos.

La lista anunciada contiene:

* **Comandos integrados**, como `/compact`, `/context`, `/usage`, `/env`, `/model`, `/mcp`, `/plan`, `/review`, `/research`, `/session` y `/rename`.
* **Aptitudes habilitadas, invocables por el usuario**, que aparecen como `/SKILL-NAME` comandos.

Los comandos que registra el propio cliente no se le anuncian.

### Acceso a la lista desde el cliente

Dado que la lista llega como una notificación en lugar de en respuesta a una solicitud, no hay ningún método para capturarla a petición. El cliente accede a él controlando la `session/update` notificación y reaccionando a las actualizaciones cuyo tipo es `available_commands_update`. Cada entrada tiene un `name` (sin la barra diagonal inicial), un `description` y un `input.hint` opcional que describe los argumentos del comando. La notificación se vuelve a enviar cada vez que cambia el conjunto, por lo que cada una de ellas se trata como un reemplazo completo de cualquier lista que haya almacenado en caché.

El controlador siguiente `sessionUpdate` captura los comandos anunciados, ampliando el `client` objeto del ejemplo mostrado anteriormente.

```typescript copy
// Track the latest advertised commands for the session.
let availableCommands: acp.AvailableCommand[] = [];

const client: acp.Client = {
  async sessionUpdate(params) {
    const update = params.update;

    if (update.sessionUpdate === "available_commands_update") {
      // This notification is a full snapshot—replace any cached list.
      availableCommands = update.availableCommands;
      for (const command of availableCommands) {
        // command.name has no leading slash; invoke it by sending "/<name>" as a prompt.
        console.log(`/${command.name} — ${command.description}`);
      }
      return;
    }

    // ...handle other updates, such as agent_message_chunk
  },

  // ...other client methods, such as requestPermission
};
```

Para ejecutar uno de los comandos anunciados, envíe su nombre como una solicitud en un único bloque de contenido de texto (por ejemplo, `{ type: "text", text: "/context" }`), como se describe en [Uso de comandos de barra diagonal](#using-slash-commands).

### Comandos que no se pueden usar a través de ACP

Los comandos de barra diagonal que dependen de la interfaz de terminal interactiva no son administrados por el servidor ACP. Esto incluye comandos que abren un selector, un cuadro de diálogo o una vista de pantalla completa, como `/diff`, `/resume`, `/theme`, `/settings`, `/login`, `/help`, `/tasks`y `/undo`. Como regla, si un comando no aparece en la `available_commands_update` lista, no se ejecutará a través de ACP: el servidor trata el texto como una solicitud normal y lo reenvía al modelo en lugar de ejecutarlo.

Dado que los clientes ACP no tienen selectores interactivos, un comando integrado que normalmente abriría un submenú en su lugar devuelve sus opciones como texto. Proporcione explícitamente el subcomando para obtener un resultado directo, por ejemplo, `/session info` o `/mcp list` en lugar de `/session` o `/mcp` por sí mismo.

Para obtener una lista completa de los comandos de barra diagonal para CLI de Copilot, vea [Referencia de comandos de la CLI de GitHub Copilot](/es/copilot/reference/copilot-cli-reference/cli-command-reference#slash-commands-in-the-interactive-interface).

## Lectura adicional

* [Documentación oficial de ACP](https://agentclientprotocol.com/protocol/overview)