Vent
Haz que tus agentes reporten sus propios errores
Documentación
vent-mcp
Permite que tu agente se queje antes de que el mismo corte de papel se convierta en el error de mañana.
vent-mcp es un pequeño servidor MCP STDIO que les da a los agentes un lugar no destructivo
para enviar comentarios accionables mientras trabajan. Los agentes pueden reportar trabajo
bloqueado, fallos repetidos, capacidades faltantes, flujos de trabajo confusos o
fricción operativa sin interrumpir el flujo de la tarea.
El crate se llama vent-mcp; el binario instalado se llama vent. La superficie
de biblioteca de Rust soporta ese binario y no es una API de integración estable.
La idea combina bien con la charla de Benjamin Verbeek, The agent that files its own bug reports y la publicación oficial del blog de Lovable.
Inicio rápido
Usa esta ruta cuando quieras que vent esté disponible para un cliente MCP local y un registro
JSONL de comentarios por defecto.
Prerrequisitos
- Rust 1.88 o más reciente y Cargo, al instalar desde crates.io o desde el código fuente.
- Un cliente MCP que pueda ejecutar un servidor STDIO local, como Codex o Claude.
Instalar
cargo install vent-mcp
Esto instala el binario vent con las características cli y webhook por defecto.
Crear la configuración por defecto
Ejecuta:
vent list
En la primera ejecución, vent crea una configuración por defecto en
$XDG_CONFIG_HOME/vent-mcp/config.toml o
~/.config/vent-mcp/config.toml. La configuración por defecto contiene un canal feedback
y un sumidero JSONL local.
Salida esperada:
feedback (default) - Blocked work, repeated failures, or confusing workflows. Avoid routine progress updates.
Los eventos JSONL se escriben en vents.jsonl junto al archivo de configuración, a menos que establezcas
[logging].jsonl_dir.
Registrar el servidor MCP
Si vent está en tu PATH, agrégalo como un servidor MCP STDIO local:
codex mcp add vent -- vent
claude mcp add --transport stdio vent -- vent
Usa una ruta absoluta a vent si tu cliente MCP no hereda el PATH de tu shell.
Instalación
Cargo
cargo install vent-mcp
Lanzamientos de GitHub
Descarga un archivo precompilado desde la página de
GitHub Releases, extráelo
y coloca vent en tu PATH.
Desde el código fuente
git clone https://github.com/bnomei/vent-mcp.git
cd vent-mcp
cargo build --release
El binario se escribe en target/release/vent.
Compilaciones por características
Compila sin dependencias de webhook y HTTP:
cargo build --release --no-default-features
Compila solo la entrega JSONL mientras se mantiene la CLI del shell:
cargo build --release --no-default-features --features cli
Cuando la característica cli está deshabilitada, el binario solo acepta una invocación
de servidor MCP sin argumentos. Cualquier argumento de CLI sale con un error.
CLI
Sin argumentos, vent inicia el servidor MCP STDIO:
vent
Usa el mismo binario desde un shell cuando la característica cli está habilitada:
vent list
vent "The queue changed mid-run."
vent --channel automation "The failing check output was hard to correlate."
vent --mcp
La entrega exitosa por CLI imprime el id del evento y el canal:
vented aZ8pQ2xK to feedback
El texto del mensaje se recorta antes de la entrega. Los mensajes vacíos y los canales desconocidos se rechazan antes de que cualquier sumidero reciba un evento.
Herramientas MCP
vent-mcp expone una pequeña superficie de herramientas:
| Herramienta | Propósito |
|---|---|
vent | Enviar comentarios accionables al canal por defecto configurado o a un canal con nombre. |
list_channels | Listar los nombres y descripciones de canales configurados cuando hay múltiples canales disponibles. |
Cuando la configuración contiene solo el canal por defecto, list_channels está oculta y
el esquema de entrada de vent solo contiene message. Cuando existen múltiples canales,
list_channels se expone y vent acepta un channel opcional.
Ejemplo de entrada de vent con múltiples canales:
{
"message": "The failing check output was hard to correlate with the changed file.",
"channel": "automation"
}
La respuesta de vent es un acuse de recibo:
{
"ok": true,
"eventId": "aZ8pQ2xK",
"channel": "automation"
}
Si la entrega falla, ok es false y error contiene el primer fallo del sumidero.
El eventId es un id de rastreo corto, no una clave de deduplicación. Los agentes no deben
enviar quejas repetidas para el mismo problema a menos que tengan nueva evidencia de la causa raíz.
Configuración
vent resuelve la configuración en este orden:
VENT_MCP_CONFIG$XDG_CONFIG_HOME/vent-mcp/config.toml~/.config/vent-mcp/config.toml
Las configuraciones XDG implícitas o del directorio de inicio se crean cuando faltan. Si
VENT_MCP_CONFIG apunta a un archivo que no existe, el inicio falla en lugar de crearlo.
Comienza con configs/config.sample.toml o la configuración por defecto generada.
Configuración mínima
default_channel = "feedback"
[[channels]]
name = "feedback"
description = "Blocked work, repeated failures, or confusing workflows. Avoid routine progress updates."
sinks = ["log"]
[[sinks]]
type = "jsonl"
name = "log"
Referencia de configuración
| Configuración | Requerida | Descripción |
|---|---|---|
default_channel | Sí | Canal usado cuando los llamadores omiten channel. Debe coincidir con una entrada [[channels]]. |
[logging].jsonl_dir | No | Directorio para vents.jsonl. Los valores vacíos u omitidos usan el directorio de configuración. ~ y ~/... se expanden desde HOME. |
[[channels]].name | Sí | Nombre del canal que los agentes pueden elegir. Los nombres deben ser letras ASCII minúsculas, dígitos, guiones bajos o guiones, hasta 64 caracteres. |
[[channels]].description | Sí | Descripción corta expuesta a los clientes MCP y a vent list. |
[[channels]].sinks | Sí | Uno o más nombres de sumideros. Cada sumidero referenciado debe existir. Un canal puede referenciar como máximo un sumidero JSONL. |
[[sinks]].type | Sí | jsonl o, con la característica webhook, webhook. |
[[sinks]].name | Sí | Nombre único del sumidero referenciado por los canales. |
[[sinks]].url | Solo webhook | Extremo HTTP o HTTPS. |
[[sinks]].provider | No | Mapa de proveedor integrado o personalizado. Omítelo o usa raw para enviar el JSON canónico del evento. |
[[sinks]].headers | No | Encabezados de webhook respaldados por variables de entorno. Los valores de los encabezados se leen cuando se envía el evento. |
[[sinks]].timeout_ms | Solo webhook | Tiempo de espera positivo en milisegundos. El valor por defecto es 10000. |
[providers.<name>] | No | Asigna los campos canónicos del evento a las rutas de salida JSON del webhook. |
Cada evento de queja contiene:
{
"id": "aZ8pQ2xK",
"timestamp": "2026-06-03T12:34:56Z",
"channel": "automation",
"message": "The failing check output was hard to correlate with the changed file.",
"project": "my-repo"
}
El valor de project es solo el nombre del directorio actual. vent-mcp no
registra la ruta completa del espacio de trabajo local.
Canales, sumideros y proveedores
vent-mcp mantiene el enrutamiento deliberadamente simple:
- Un canal es la ruta que el agente puede elegir, u omitir para usar
default_channel. - Un sumidero es un destino concreto, como registro JSONL local o un webhook.
- Un proveedor es una forma de carga útil de webhook.
Los nombres de sumideros y los nombres de canales no tienen que coincidir. Por ejemplo, un canal automation
puede escribir en el registro por defecto y publicar en Discord:
default_channel = "feedback"
[[channels]]
name = "feedback"
description = "General feedback."
sinks = ["log"]
[[channels]]
name = "automation"
description = "Build, test, CI/CD, deployment, scheduler, or pipeline failures that blocked progress."
sinks = ["log", "discord-automation"]
[[sinks]]
type = "jsonl"
name = "log"
[[sinks]]
type = "webhook"
name = "discord-automation"
provider = "discord"
url = "https://discord.com/api/webhooks/..."
timeout_ms = 10000
Con esta configuración, las quejas de channel = "automation" se escriben en vents.jsonl
y se publican en Discord. Otros canales van solo a los sumideros que listan.
Proveedores de webhook
Los sumideros de webhook publican JSON. Sin proveedor, o con provider = "raw", el evento
de queja sin procesar se envía sin cambios.
Los mapas de proveedores integrados incluyen:
| Proveedor | Forma |
|---|---|
zapier, make, n8n, pipedream, workato | Campos canónicos del evento sin procesar. |
ifttt | message, channel y project asignados a value1, value2 y value3. |
slack, mattermost | Texto más campo de proyecto con estilo de adjunto. |
discord | content más un campo embed para el proyecto. |
microsoft_teams, google_chat, webex | Campo de mensaje solo texto. |
Los mapas de proveedores personalizados viven en el mismo archivo de configuración TOML. El lado izquierdo es un
campo canónico del evento y el valor es una ruta JSON de salida con puntos. Los segmentos numéricos
de la ruta crean arreglos. Si field_label_key está establecido, las rutas que terminan en .value
también reciben una etiqueta generada, como Project.
[providers.discord]
field_label_key = "name"
message = "content"
project = "embeds.0.fields.0.value"
[[sinks]]
type = "webhook"
name = "discord-automation"
provider = "discord"
url = "https://discord.com/api/webhooks/..."
timeout_ms = 10000
Los encabezados de webhook leen valores de variables de entorno:
[[sinks]]
type = "webhook"
name = "private-endpoint"
url = "https://example.test/vent"
[[sinks.headers]]
name = "Authorization"
env = "VENT_WEBHOOK_AUTH"
Si un webhook devuelve una respuesta que no es 2xx, la vista previa del error se acorta y los secretos conocidos de URL o encabezados se redactan antes de que el llamador los vea.
Solución de problemas
config file not found
Causa: VENT_MCP_CONFIG apunta a una ruta que no existe.
Solución: Crea el archivo en esa ruta, desestablece VENT_MCP_CONFIG o apúntalo a
una configuración TOML existente.
unknown channel: <name>
Causa: El llamador CLI o MCP solicitó un canal que no está declarado en
[[channels]].
Solución: Ejecuta vent list, elige uno de los nombres configurados o agrega el canal y
su ruta de sumidero a la configuración.
message must not be empty
Causa: El mensaje estaba vacío después de recortar los espacios en blanco.
Solución: Envía un mensaje específico y accionable que diga qué falló y qué desbloquearía el trabajo.
missing environment variable <NAME>
Causa: Un encabezado de webhook referencia una variable de entorno que no está establecida en
el entorno del proceso vent.
Solución: Exporta la variable antes de iniciar el cliente MCP o elimina el encabezado del sumidero.
CLI mode is disabled
Causa: El binario se compiló sin la característica cli y recibió argumentos
de CLI.
Solución: Usa el binario solo como servidor MCP o recompílalo con --features cli.
Desarrollo
Ejecuta la suite de pruebas:
cargo test
Compila un binario de lanzamiento:
cargo build --release
Anclas de código fuente:
- src/main.rs: selección del modo binario, carga de configuración, salida CLI e inicio del servidor MCP.
- src/config.rs: resolución de ruta de configuración, valores por defecto, validación y mapas de proveedores integrados.
- src/server.rs: definiciones de herramientas MCP y modelado dinámico de la superficie de herramientas.
- src/delivery.rs: recorte de mensajes, selección de canal, construcción de eventos y salida de acuse de recibo.
- src/sinks.rs: escritura JSONL, entrega por webhook, encabezados respaldados por entorno, manejo de tiempo de espera y redacción de errores.
- src/provider.rs: validación de rutas de proveedor y renderizado JSON de webhook.
- tests/cli.rs: comportamiento de CLI a nivel de proceso y cobertura de arranque de configuración.