{"id":51429473,"url":"https://github.com/bnomei/vent-mcp","last_synced_at":"2026-07-05T03:02:08.900Z","repository":{"id":362310167,"uuid":"1258295243","full_name":"bnomei/vent-mcp","owner":"bnomei","description":"Allow your agents to file their own issue reports","archived":false,"fork":false,"pushed_at":"2026-06-29T11:08:02.000Z","size":206,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-29T13:08:41.820Z","etag":null,"topics":["agent","ai","channels","cli","discord","feedback","google-chat","issues","logging","make","mcp","microsoft-teams","n8n","slack","stdio","vent","webhook","zapier"],"latest_commit_sha":null,"homepage":"https://crates.io/crates/vent-mcp","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bnomei.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"bnomei","buy_me_a_coffee":"bnomei"}},"created_at":"2026-06-03T12:55:02.000Z","updated_at":"2026-06-29T11:06:40.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/bnomei/vent-mcp","commit_stats":null,"previous_names":["bnomei/vent-mcp"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/bnomei/vent-mcp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bnomei%2Fvent-mcp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bnomei%2Fvent-mcp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bnomei%2Fvent-mcp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bnomei%2Fvent-mcp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bnomei","download_url":"https://codeload.github.com/bnomei/vent-mcp/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bnomei%2Fvent-mcp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35141966,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-05T02:00:06.290Z","response_time":100,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agent","ai","channels","cli","discord","feedback","google-chat","issues","logging","make","mcp","microsoft-teams","n8n","slack","stdio","vent","webhook","zapier"],"created_at":"2026-07-05T03:02:03.550Z","updated_at":"2026-07-05T03:02:08.867Z","avatar_url":"https://github.com/bnomei.png","language":"Rust","funding_links":["https://github.com/sponsors/bnomei","https://buymeacoffee.com/bnomei","https://www.buymeacoffee.com/bnomei"],"categories":[],"sub_categories":[],"readme":"# vent-mcp\n\n[![Crates.io Version](https://img.shields.io/crates/v/vent-mcp)](https://crates.io/crates/vent-mcp)\n[![CI](https://img.shields.io/github/actions/workflow/status/bnomei/vent-mcp/ci.yml?branch=main)](https://github.com/bnomei/vent-mcp/actions/workflows/ci.yml)\n[![Crates.io Downloads](https://img.shields.io/crates/d/vent-mcp)](https://crates.io/crates/vent-mcp)\n[![License](https://img.shields.io/crates/l/vent-mcp)](https://crates.io/crates/vent-mcp)\n[![Discord](https://flat.badgen.net/badge/discord/bnomei?color=7289da\u0026icon=discord\u0026label)](https://discordapp.com/users/bnomei)\n[![Buymecoffee](https://flat.badgen.net/badge/icon/donate?icon=buymeacoffee\u0026color=FF813F\u0026label)](https://www.buymeacoffee.com/bnomei)\n\nAllow your agent to complain before the same paper cut becomes tomorrow's bug.\n\n`vent-mcp` is a small STDIO MCP server that gives agents a non-destructive\nplace to send actionable feedback while they work. Agents can report blocked\nwork, repeated failures, missing capabilities, confusing workflows, or\noperational friction without interrupting the task flow.\n\nThe crate is named `vent-mcp`; the installed binary is named `vent`. The Rust\nlibrary surface supports that binary and is not a stable embedding API.\n\nThe idea pairs well with Benjamin Verbeek's talk,\n[The agent that files its own bug reports](https://www.youtube.com/watch?v=KA5kPbdkK2E)\nand the [official Lovable blog post](https://lovable.dev/blog/we-gave-our-agent-a-vent-tool).\n\n## Quickstart\n\nUse this path when you want `vent` available to a local MCP client and a default\nJSONL feedback log.\n\n### Prerequisites\n\n- Rust 1.88 or newer and Cargo, when installing from crates.io or source.\n- An MCP client that can run a local STDIO server, such as Codex or Claude.\n\n### Install\n\n```bash\ncargo install vent-mcp\n```\n\nThis installs the `vent` binary with the default `cli` and `webhook` features.\n\n### Create the default config\n\nRun:\n\n```bash\nvent list\n```\n\nOn first run, `vent` creates a default config at\n`$XDG_CONFIG_HOME/vent-mcp/config.toml` or\n`~/.config/vent-mcp/config.toml`. The default config contains one `feedback`\nchannel and one local JSONL sink.\n\nExpected output:\n\n```txt\nfeedback (default) - Blocked work, repeated failures, or confusing workflows. Avoid routine progress updates.\n```\n\nJSONL events are written to `vents.jsonl` beside the config file unless you set\n`[logging].jsonl_dir`.\n\n### Register the MCP server\n\nIf `vent` is on your `PATH`, add it as a local STDIO MCP server:\n\n```bash\ncodex mcp add vent -- vent\nclaude mcp add --transport stdio vent -- vent\n```\n\nUse an absolute path to `vent` if your MCP client does not inherit your shell\n`PATH`.\n\n## Installation\n\n### Cargo\n\n```bash\ncargo install vent-mcp\n```\n\n### GitHub Releases\n\nDownload a prebuilt archive from the\n[GitHub Releases](https://github.com/bnomei/vent-mcp/releases) page, extract it,\nand place `vent` on your `PATH`.\n\n### From source\n\n```bash\ngit clone https://github.com/bnomei/vent-mcp.git\ncd vent-mcp\ncargo build --release\n```\n\nThe binary is written to `target/release/vent`.\n\n### Feature builds\n\nBuild without webhook and HTTP dependencies:\n\n```bash\ncargo build --release --no-default-features\n```\n\nBuild JSONL-only delivery while keeping the shell CLI:\n\n```bash\ncargo build --release --no-default-features --features cli\n```\n\nWhen the `cli` feature is disabled, the binary only accepts a bare MCP server\ninvocation. Any CLI arguments exit with an error.\n\n## CLI\n\nWith no arguments, `vent` starts the STDIO MCP server:\n\n```bash\nvent\n```\n\nUse the same binary from a shell when the `cli` feature is enabled:\n\n```bash\nvent list\nvent \"The queue changed mid-run.\"\nvent --channel automation \"The failing check output was hard to correlate.\"\nvent --mcp\n```\n\nSuccessful CLI delivery prints the event id and channel:\n\n```txt\nvented aZ8pQ2xK to feedback\n```\n\nMessage text is trimmed before delivery. Empty messages and unknown channels are\nrejected before any sink receives an event.\n\n## MCP tools\n\n`vent-mcp` exposes a small tool surface:\n\n| Tool | Purpose |\n| --- | --- |\n| `vent` | Send actionable feedback to the configured default channel or to a named channel. |\n| `list_channels` | List configured channel names and descriptions when multiple channels are available. |\n\nWhen the config contains only the default channel, `list_channels` is hidden and\nthe `vent` input schema only contains `message`. When multiple channels exist,\n`list_channels` is exposed and `vent` accepts an optional `channel`.\n\nExample multi-channel `vent` input:\n\n```json\n{\n  \"message\": \"The failing check output was hard to correlate with the changed file.\",\n  \"channel\": \"automation\"\n}\n```\n\nThe `vent` response is an acknowledgement:\n\n```json\n{\n  \"ok\": true,\n  \"eventId\": \"aZ8pQ2xK\",\n  \"channel\": \"automation\"\n}\n```\n\nIf delivery fails, `ok` is `false` and `error` contains the first sink failure.\nThe `eventId` is a short trace id, not a deduplication key. Agents should not\nsend repeated vents for the same issue unless they have new root-cause evidence.\n\n## Configuration\n\n`vent` resolves config in this order:\n\n1. `VENT_MCP_CONFIG`\n2. `$XDG_CONFIG_HOME/vent-mcp/config.toml`\n3. `~/.config/vent-mcp/config.toml`\n\nImplicit XDG or home-directory configs are created when missing. If\n`VENT_MCP_CONFIG` points to a missing file, startup fails instead of creating it.\n\nStart from [configs/config.sample.toml](configs/config.sample.toml) or the\ngenerated default config.\n\n### Minimal config\n\n```toml\ndefault_channel = \"feedback\"\n\n[[channels]]\nname = \"feedback\"\ndescription = \"Blocked work, repeated failures, or confusing workflows. Avoid routine progress updates.\"\nsinks = [\"log\"]\n\n[[sinks]]\ntype = \"jsonl\"\nname = \"log\"\n```\n\n### Config reference\n\n| Setting | Required | Description |\n| --- | --- | --- |\n| `default_channel` | Yes | Channel used when callers omit `channel`. It must match one `[[channels]]` entry. |\n| `[logging].jsonl_dir` | No | Directory for `vents.jsonl`. Empty or omitted values use the config directory. `~` and `~/...` expand from `HOME`. |\n| `[[channels]].name` | Yes | Channel name agents may choose. Names must be lowercase ASCII letters, digits, underscores, or dashes, up to 64 characters. |\n| `[[channels]].description` | Yes | Short description exposed to MCP clients and `vent list`. |\n| `[[channels]].sinks` | Yes | One or more sink names. Every referenced sink must exist. A channel may reference at most one JSONL sink. |\n| `[[sinks]].type` | Yes | `jsonl` or, with the `webhook` feature, `webhook`. |\n| `[[sinks]].name` | Yes | Unique sink name referenced by channels. |\n| `[[sinks]].url` | Webhook only | HTTP or HTTPS endpoint. |\n| `[[sinks]].provider` | No | Built-in or custom provider map. Omit it or use `raw` to send the canonical event JSON. |\n| `[[sinks]].headers` | No | Environment-backed webhook headers. Header values are read when the event is sent. |\n| `[[sinks]].timeout_ms` | Webhook only | Positive timeout in milliseconds. Defaults to `10000`. |\n| `[providers.\u003cname\u003e]` | No | Maps canonical event fields onto webhook JSON output paths. |\n\nEvery vent event contains:\n\n```json\n{\n  \"id\": \"aZ8pQ2xK\",\n  \"timestamp\": \"2026-06-03T12:34:56Z\",\n  \"channel\": \"automation\",\n  \"message\": \"The failing check output was hard to correlate with the changed file.\",\n  \"project\": \"my-repo\"\n}\n```\n\nThe `project` value is only the current directory name. `vent-mcp` does not\nrecord the full local workspace path.\n\n## Channels, sinks, and providers\n\n`vent-mcp` keeps routing deliberately simple:\n\n- A channel is the route the agent can choose, or omit to use `default_channel`.\n- A sink is a concrete destination, such as local JSONL logging or a webhook.\n- A provider is a webhook payload shape.\n\nSink names and channel names do not have to match. For example, an `automation`\nchannel can write to the default log and post to Discord:\n\n```toml\ndefault_channel = \"feedback\"\n\n[[channels]]\nname = \"feedback\"\ndescription = \"General feedback.\"\nsinks = [\"log\"]\n\n[[channels]]\nname = \"automation\"\ndescription = \"Build, test, CI/CD, deployment, scheduler, or pipeline failures that blocked progress.\"\nsinks = [\"log\", \"discord-automation\"]\n\n[[sinks]]\ntype = \"jsonl\"\nname = \"log\"\n\n[[sinks]]\ntype = \"webhook\"\nname = \"discord-automation\"\nprovider = \"discord\"\nurl = \"https://discord.com/api/webhooks/...\"\ntimeout_ms = 10000\n```\n\nWith this config, `channel = \"automation\"` vents are written to `vents.jsonl`\nand posted to Discord. Other channels go only to the sinks they list.\n\n## Webhook providers\n\nWebhook sinks POST JSON. With no provider, or with `provider = \"raw\"`, the raw\nvent event is sent unchanged.\n\nBuilt-in provider maps include:\n\n| Provider | Shape |\n| --- | --- |\n| `zapier`, `make`, `n8n`, `pipedream`, `workato` | Raw canonical event fields. |\n| `ifttt` | `message`, `channel`, and `project` mapped to `value1`, `value2`, and `value3`. |\n| `slack`, `mattermost` | Text plus attachment-style project field. |\n| `discord` | `content` plus an embed field for project. |\n| `microsoft_teams`, `google_chat`, `webex` | Text-only message field. |\n\nCustom provider maps live in the same TOML config file. The left side is a\ncanonical event field and the value is a dotted JSON output path. Numeric path\nsegments create arrays. If `field_label_key` is set, paths ending in `.value`\nalso get a generated label such as `Project`.\n\n```toml\n[providers.discord]\nfield_label_key = \"name\"\nmessage = \"content\"\nproject = \"embeds.0.fields.0.value\"\n\n[[sinks]]\ntype = \"webhook\"\nname = \"discord-automation\"\nprovider = \"discord\"\nurl = \"https://discord.com/api/webhooks/...\"\ntimeout_ms = 10000\n```\n\nWebhook headers read values from environment variables:\n\n```toml\n[[sinks]]\ntype = \"webhook\"\nname = \"private-endpoint\"\nurl = \"https://example.test/vent\"\n\n[[sinks.headers]]\nname = \"Authorization\"\nenv = \"VENT_WEBHOOK_AUTH\"\n```\n\nIf a webhook returns a non-2xx response, the error preview is shortened and\nknown URL or header secrets are redacted before the caller sees it.\n\n## Troubleshooting\n\n### `config file not found`\n\nCause: `VENT_MCP_CONFIG` points to a path that does not exist.\n\nFix: Create the file at that path, unset `VENT_MCP_CONFIG`, or point it at an\nexisting TOML config.\n\n### `unknown channel: \u003cname\u003e`\n\nCause: The CLI or MCP caller requested a channel that is not declared in\n`[[channels]]`.\n\nFix: Run `vent list`, choose one of the configured names, or add the channel and\nits sink route to the config.\n\n### `message must not be empty`\n\nCause: The message was empty after trimming whitespace.\n\nFix: Send a specific, actionable message that says what failed and what would\nunblock the work.\n\n### `missing environment variable \u003cNAME\u003e`\n\nCause: A webhook header references an environment variable that is not set in\nthe `vent` process environment.\n\nFix: Export the variable before starting the MCP client or remove the header from\nthe sink.\n\n### `CLI mode is disabled`\n\nCause: The binary was built without the `cli` feature and received CLI\narguments.\n\nFix: Use the binary only as an MCP server or rebuild with `--features cli`.\n\n## Development\n\nRun the test suite:\n\n```bash\ncargo test\n```\n\nBuild a release binary:\n\n```bash\ncargo build --release\n```\n\nSource anchors:\n\n- [src/main.rs](src/main.rs): binary mode selection, config loading, CLI output,\n  and MCP server startup.\n- [src/config.rs](src/config.rs): config path resolution, defaults,\n  validation, and built-in provider maps.\n- [src/server.rs](src/server.rs): MCP tool definitions and dynamic tool-surface\n  shaping.\n- [src/delivery.rs](src/delivery.rs): message trimming, channel selection,\n  event construction, and acknowledgement output.\n- [src/sinks.rs](src/sinks.rs): JSONL writing, webhook delivery, env-backed\n  headers, timeout handling, and error redaction.\n- [src/provider.rs](src/provider.rs): provider path validation and webhook JSON\n  rendering.\n- [tests/cli.rs](tests/cli.rs): process-level CLI behavior and config\n  bootstrapping coverage.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbnomei%2Fvent-mcp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbnomei%2Fvent-mcp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbnomei%2Fvent-mcp/lists"}