MCP server: One MCP server.

veto

@aivetoMCP server · External

Turn OpenAPI services into tools an agent can call under your rules.

AI agent governancev0.1.12Apache-2.0Go
Freeno charge per call

Runs on your machine from its package; the steps are below.

veto makes it possible for an AI agent to call your API with context and semantics. A hundred endpoints stay 3 tools.
From the README · 1 of 2

What it does

  1. Reads
  2. Writes
  3. High impact

At most: moves money, runs code or commands, deletes data, or sends messages for you.

What it costs

Free

Odel charges nothing per call. The publisher may charge for its own service.

Runs locally over stdio

This server isn't hosted — your MCP client launches it from a package registry. Use one of the commands below, or drop the config into your client (e.g. Claude Desktop).

Dockerghcr.io/aiveto/veto:0.1.12

Run

docker run -i --rm ghcr.io/aiveto/veto:0.1.12

MCP client config

{
  "mcpServers": {
    "veto": {
      "command": "docker",
      "args": [
        "run",
        "-i",
        "--rm",
        "ghcr.io/aiveto/veto:0.1.12"
      ]
    }
  }
}
README4 min read
veto makes it possible for an AI agent to call your API with context and semantics. A hundred endpoints stay 3 tools.

Turn existing OpenAPI services into tools AI agents can discover and call under your rules.

The model may request a call. Veto checks policy, requires approval for a destructive call, and resolves credentials before your API runs. Declared relations name a linked operation. A trace records the decision.

The model proposes. Veto decides. Your API executes.

MCP, JSON lines on veto serve --json, and veto search, describe, and invoke are the same three capabilities. They share one runtime. Your services stay where they already run.

Claude, Cursor, or ChatGPT talks to veto over MCP. A CLI or script uses search, describe, and invoke. Search and describe read the catalog. Invoke goes to policy and confirmation, then HTTP.
bash
brew install aiveto/veto/veto
bash
go install github.com/aiveto/veto/cmd/veto@latest

brew does not need Go. go install needs Go 1.27.1. Binaries are on GitHub Releases. A release also pushes ghcr.io/aiveto/veto.

See veto in action

veto-demo is the full walk. Harbor sells home goods. Orders, customers, and billing are the APIs. The walk follows a customer from an order, holds a delete until a person approves it, and keeps the secret out of the trace. make demo runs that story over the CLI, then over MCP. make mcp leaves Harbor listening and prints the config for Claude, Cursor, or ChatGPT. make cli is the same story through search, describe, and invoke.

This repo runs the relation, the held delete, and the redacted trace, then exits. No model key.

bash
git clone https://github.com/aiveto/veto.git
cd veto
go run ./examples/two-apis
text
Someone asked who placed order 123.
orders.get returned customerId 7.
customers.get was called for 7 because the note said Order.customerId identifies customers.get.
orders.delete did not call HTTP until approved.
The trace left the secret out.

A delete waits

text
Agent requests the call                          -> pending ID; no upstream HTTP
Person accepts the form in the chat              -> one matching invocation
TTY stdin and stdout: same sentence, y           -> one matching invocation
Host without that form: veto approve <id>        -> approved ID, then the agent submits it once

The approval is bound to the caller, the operation, and the parameters. Permission and confirmation run before credentials are fetched and before HTTP. An OPA allow does not skip those checks. A webhook or a command can notify your approval system. The server and veto approve share approval storage and signing configuration. confirmation: false in veto.yaml turns that gate off for the deployment. Unset leaves it on.

A per-caller limit stops a call before policy. Timeouts and retries apply to the call that is sent.

The next call is declared

yaml
relations:
  - schema: Order
    field: customerId
    to: customers.get

Search returns the related ids and related_calls. Describe returns the note, such as Order.customerId identifies customers.get. A successful invoke includes next_calls when the response has that field. Invoke still runs one operation. Relations.

What the agent receives

The agent gets search, describe, and invoke. Over MCP the names are capabilities_search, capabilities_describe, and capabilities_invoke. veto --help-json is the contract. veto serve --json serves JSON lines for skills and scripts. Each line is one of those three. veto search, describe, and invoke are a shorthand for a human. Direct pins add a few operations beside those three. Grouped mode adds one tool per resource. Search matches the summary, tags, the path noun, and synonyms such as retire for delete. An overlay can add a word of your own.

Response shaping returns named fields and a bounded list, and marks pagination and truncation. A Go context pack holds rules, operation summaries, the conversation, relations, and a pending confirmation, inside a byte budget. The raw OpenAPI document stays out of the pack.

Connect your services

veto init writes veto.yaml for the OpenAPI files or URLs you name, and a relations.yaml stub if you do not have one. If veto.yaml is already there, init stops.

bash
veto init orders.yaml customers.yaml

veto serve --stdio speaks MCP on stdin. veto serve --json serves JSON lines for skills and scripts. Authenticated Streamable HTTP serves the same runtime to a remote client.

Credentials come from the environment, OAuth, a caller-supplied token, token exchange, a command that returns headers, or a Go provider that signs the request. The agent does not perform that login. Authentication.

Commands for validate, doctor, preview, eval, check, and replay are in the setup guide.

bash
veto validate --config testdata/veto.yaml
veto eval --config testdata/veto.yaml --case testdata/delete.yaml
veto serve --config testdata/veto.yaml --stdio
veto serve --config testdata/veto.yaml --json

testdata/veto.yaml is already written. eval runs the delete case in this repo. A call needs an API that is still listening, which is what veto-demo keeps up.

Scope

Pre-1.0. Public APIs may change.

Setup guide | Current limits

Similar modules

Browse AI agent governance