| 1 |
# oxy mcp: Oxygen for AI agents |
| 2 |
|
| 3 |
`oxy mcp` serves one repository to an AI agent over the |
| 4 |
[Model Context Protocol](https://modelcontextprotocol.io) (MCP), on stdio |
| 5 |
(oxygen#159). The agent calls typed tools (`status`, `log`, `commit`, …) |
| 6 |
and gets JSON back, instead of running `oxy` in a shell and reading its |
| 7 |
output. |
| 8 |
|
| 9 |
## Who changes are signed as |
| 10 |
|
| 11 |
The server signs as whatever identity its environment configures, exactly |
| 12 |
as `oxy` would: it runs each tool as this same `oxy` binary, in the |
| 13 |
repository, with the server's environment. Start it from an agent home and |
| 14 |
every change the agent makes is sealed **via the agent**, with no |
| 15 |
`OXY_HOME` to remember on each command: |
| 16 |
|
| 17 |
```sh |
| 18 |
OXY_HOME=~/.oxy-agents/claude oxy mcp ~/development/myproject |
| 19 |
``` |
| 20 |
|
| 21 |
The server says who it signs as in its `initialize` reply (the first line |
| 22 |
of `oxy identity show`), and the `identity` tool shows the rest. Without an |
| 23 |
identity, reading works and committing is refused with oxy's own message. |
| 24 |
|
| 25 |
## Tools |
| 26 |
|
| 27 |
Each tool returns the command's `--json` output as structured content (an |
| 28 |
array comes wrapped as `{"result": […]}`) and as text. A failed command is a |
| 29 |
tool result with `isError: true` and oxy's error, so the agent sees why. |
| 30 |
|
| 31 |
|
| 32 |
|
| 33 |
| `status` | `oxy status --json` | | |
| 34 |
| `diff` | `oxy diff [CHANGE] --json` | `change` | |
| 35 |
| `log` | `oxy log --json` | `revset`, `path`, `limit` (default 20, at most 1000) | |
| 36 |
| `show` | `oxy show CHANGE --json` | `change` (default `@`), `stat` | |
| 37 |
| `cat` | `oxy cat PATH [-r CHANGE]` | `path`, `change` | |
| 38 |
| `blame` | `oxy blame PATH --json` | `path` | |
| 39 |
| `bookmarks` | `oxy bookmark list --json` | `all` | |
| 40 |
| `tags` | `oxy tag list --json` | | |
| 41 |
| `conflicts` | `oxy resolve --json` (report only) | | |
| 42 |
| `op_log` | `oxy op log --json` | `limit` | |
| 43 |
| `identity` | `oxy identity show` | | |
| 44 |
| `commit` | `oxy commit -m MESSAGE PATHS…` | `message`, and `paths` or `all: true` | |
| 45 |
| `amend` | `oxy amend [-m] PATHS…` | `paths` or `all: true`, `message` | |
| 46 |
| `describe` | `oxy describe [CHANGE] -m MESSAGE` | `message`, `change` | |
| 47 |
| `fetch`, `pull` | `oxy fetch\|pull [REMOTE] --json` | `remote` | |
| 48 |
| `push` | `oxy push [REMOTE] --json` | `remote`, `bookmark`, `force` | |
| 49 |
| `tlog_verify` | `oxy tlog verify --json` | | |
| 50 |
| `undo` | `oxy undo` | only with `--allow-destructive` | |
| 51 |
|
| 52 |
## Safety |
| 53 |
|
| 54 |
- **Commits are deliberate.** `commit` and `amend` take the paths to |
| 55 |
include, or `all: true`; never neither. |
| 56 |
- **Nothing destructive by default.** `undo` is not offered, and `push` |
| 57 |
refuses `force`, unless the server is started with `--allow-destructive`. |
| 58 |
Tag withdrawal, bookmark deletion and history rewriting are not tools at |
| 59 |
all. Each tool carries MCP's `readOnlyHint` and `destructiveHint`. |
| 60 |
- **Values are never flags.** Arguments are passed as `--flag=value` and |
| 61 |
after `--`, so a path or message starting with `-` stays a value. |
| 62 |
- **Your policy still applies.** Pushes go through the remote's checks and |
| 63 |
the repository's trust policy like any other; an agent's delegation |
| 64 |
scope limits what its seals may do. |
| 65 |
- **Output is bounded.** A tool's text stops at 256 KiB, saying to narrow |
| 66 |
the request. |
| 67 |
|
| 68 |
## Adding it to an agent |
| 69 |
|
| 70 |
Claude Code, for one project (run in the project's root): |
| 71 |
|
| 72 |
```sh |
| 73 |
claude mcp add oxy -- env OXY_HOME=$HOME/.oxy-agents/claude oxy mcp |
| 74 |
``` |
| 75 |
|
| 76 |
Any MCP client that starts stdio servers takes the same command: `oxy mcp |
| 77 |
[DIR] [--allow-destructive]`, with `OXY_HOME` set for an agent's identity. |
| 78 |
`DIR` defaults to the current directory and must be a repository's root. |