Skip to content

Commit 2575b2a

Browse files
committed
write README
Covers install paths (release binaries, Docker, go install), copy-pasteable MCP client configuration for Claude Code and generic JSON clients, the full flag/env reference with mirror precedence, capability groups with the safety posture and how to widen it deliberately, the Gerrit 3.13+ target with HTTP credentials, and the llmxml output contract at reader level. Refs: #20
1 parent 0f48f7e commit 2575b2a

1 file changed

Lines changed: 177 additions & 0 deletions

File tree

README.md

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
# go-gerrit-mcp
2+
3+
An MCP (Model Context Protocol) server exposing Gerrit code review operations as capability-gated tools. It lets an
4+
AI agent search and read changes, publish review comments, vote, and drive change-state transitions — with a safety
5+
posture that makes every write capability an explicit operator opt-in.
6+
7+
- **Transport:** stdio
8+
- **Target platform:** Gerrit 3.13+, authenticated via HTTP credentials
9+
- **Output:** llmxml — semantically tagged text meant to be read by a model (see [Output format](#output-format))
10+
11+
## Safety posture
12+
13+
Two defaults encode it:
14+
15+
- **Zero configuration exposes the `read` group only.** Write capability never appears unless enabled via `--groups`.
16+
- **The own-changes restriction is on by default.** Even with write groups enabled, trail-leaving operations —
17+
comments, votes, state changes, anything other humans see — are refused on changes the authenticated account does
18+
not own, until the operator explicitly passes `--own-changes-only=false`.
19+
20+
An agent leaving unwanted trail on colleagues' changes is an externally visible failure; a missing capability is a
21+
locally discoverable inconvenience. The defaults are chosen accordingly. Widen deliberately:
22+
23+
```sh
24+
# agent may comment and vote on anyone's changes, but only within two projects
25+
go-gerrit-mcp --groups read,comment,transition --own-changes-only=false --projects core,infra
26+
```
27+
28+
## Install
29+
30+
**Binary release** — download the archive for your platform from
31+
[GitHub Releases](https://github.com/GaijinEntertainment/go-gerrit-mcp/releases), unpack, and put `go-gerrit-mcp` on
32+
your `PATH`.
33+
34+
**Docker:**
35+
36+
```sh
37+
docker pull ghcr.io/gaijinentertainment/go-gerrit-mcp:latest
38+
```
39+
40+
**go install:**
41+
42+
```sh
43+
go install dev.gaijin.team/go/go-gerrit-mcp/cmd/go-gerrit-mcp@latest
44+
```
45+
46+
## Quick start
47+
48+
The server reads connection identity from environment variables only — credentials never travel through flags:
49+
50+
| Variable | Meaning |
51+
| ----------------- | -------------------------------------------------- |
52+
| `GERRIT_URL` | Base URL of the Gerrit instance |
53+
| `GERRIT_USERNAME` | Account username for HTTP Basic authentication |
54+
| `GERRIT_TOKEN` | HTTP credential paired with the username |
55+
56+
Generate the credential in Gerrit under **Settings → HTTP Credentials** (an HTTP password, or an auth token on
57+
instances that issue them). All three variables are required; the server exits with an error naming the missing ones.
58+
59+
### Claude Code
60+
61+
```sh
62+
claude mcp add gerrit \
63+
--env GERRIT_URL=https://gerrit.example.com \
64+
--env GERRIT_USERNAME=your-username \
65+
--env GERRIT_TOKEN=your-http-credential \
66+
-- go-gerrit-mcp
67+
```
68+
69+
### Any MCP client (JSON configuration)
70+
71+
```json
72+
{
73+
"mcpServers": {
74+
"gerrit": {
75+
"command": "go-gerrit-mcp",
76+
"args": ["--groups", "read"],
77+
"env": {
78+
"GERRIT_URL": "https://gerrit.example.com",
79+
"GERRIT_USERNAME": "your-username",
80+
"GERRIT_TOKEN": "your-http-credential"
81+
}
82+
}
83+
}
84+
}
85+
```
86+
87+
### Docker
88+
89+
```json
90+
{
91+
"mcpServers": {
92+
"gerrit": {
93+
"command": "docker",
94+
"args": [
95+
"run", "-i", "--rm",
96+
"-e", "GERRIT_URL", "-e", "GERRIT_USERNAME", "-e", "GERRIT_TOKEN",
97+
"ghcr.io/gaijinentertainment/go-gerrit-mcp:latest",
98+
"--groups", "read"
99+
],
100+
"env": {
101+
"GERRIT_URL": "https://gerrit.example.com",
102+
"GERRIT_USERNAME": "your-username",
103+
"GERRIT_TOKEN": "your-http-credential"
104+
}
105+
}
106+
}
107+
}
108+
```
109+
110+
## Capability groups
111+
112+
Capability is selected at startup via `--groups` as a comma-separated list. Groups are independent and combinable —
113+
there is no ladder; each write-capable group bundles the minimal change-read subset it needs to function on its own,
114+
and enabled groups union.
115+
116+
| Group | Tools |
117+
| ------------ | ---------------------------------------------------------------------------------------- |
118+
| `read` | `search_changes`, `get_change`, `list_change_files`, `get_file_diff`, `get_change_comments` |
119+
| `comment` | `get_change`, `get_change_comments`, `post_comments` |
120+
| `transition` | `get_change`, `set_vote`, `transition_change` |
121+
122+
### Tools
123+
124+
- `search_changes` — query changes with Gerrit's change query syntax, paginated.
125+
- `get_change` — one change in review-relevant detail: status, owner, labels with votes, current revision, messages.
126+
- `list_change_files` — files touched by a revision, with per-file change stats.
127+
- `get_file_diff` — the diff of one file in a revision.
128+
- `get_change_comments` — comment threads on a change, with resolution state and comment ids.
129+
- `post_comments` — publish a review in one call: optional top-level message plus inline, range, file-level, and
130+
reply comments; replies anchor to comment ids from `get_change_comments`; `resolved` toggles the thread state.
131+
- `set_vote` — set a label vote (e.g. `Code-Review`) with an optional message; value `0` clears an own vote.
132+
- `transition_change` — move a change's state: `submit`, `abandon`, `restore`, `wip`, or `ready`, with an optional
133+
message (submit accepts none). Gerrit's refusal — a blocked submit, a restore of a merged change — is reported
134+
verbatim.
135+
136+
## Configuration reference
137+
138+
Behavior is configured by CLI flags, each mirrored by an environment variable so one configuration style works for
139+
binary and Docker invocations alike. Precedence: **flag wins over its mirror, the mirror wins over the default.**
140+
141+
| Flag | Mirror | Default | Meaning |
142+
| -------------------- | ----------------------------- | ------- | -------------------------------------------------------------- |
143+
| `--groups` | `GERRIT_MCP_GROUPS` | `read` | Comma-separated capability groups: `read`, `comment`, `transition` |
144+
| `--projects` | `GERRIT_MCP_PROJECTS` | (empty) | Project allowlist confining every operation, reads included |
145+
| `--own-changes-only` | `GERRIT_MCP_OWN_CHANGES_ONLY` | `true` | Refuse trail-leaving operations on changes not owned by the authenticated account |
146+
| `--include-tools` | `GERRIT_MCP_INCLUDE_TOOLS` | (empty) | Keep only the listed tools from the group-resolved set |
147+
| `--exclude-tools` | `GERRIT_MCP_EXCLUDE_TOOLS` | (empty) | Remove the listed tools from the group-resolved set |
148+
149+
Notes:
150+
151+
- `--own-changes-only` takes an explicit boolean value: `--own-changes-only=false`. A bare flag without a value is a
152+
configuration error.
153+
- **Project scoping** (`--projects`) is enforced server-side: a project clause is injected into every change query
154+
regardless of what the agent composed, and direct operations on out-of-scope changes are refused.
155+
- **Tool filters** only narrow. `--exclude-tools` removes tools from what the groups resolved; `--include-tools`
156+
keeps only the listed subset of it. A tool outside the enabled groups can never be activated by a filter, and
157+
exclude wins over include. Filter entries naming no known tool fail startup, so misconfigurations surface
158+
immediately.
159+
- Configuration errors are aggregated: the server reports every problem at once, then exits non-zero.
160+
161+
## Output format
162+
163+
Every tool responds in **llmxml**: an LLM-digestible subset of XML — line-structured, semantically tagged text meant
164+
to be read by a model. Attributes carry metadata, element bodies carry content:
165+
166+
```
167+
<changes query="status:open owner:self" start="0" count="1" more="false">
168+
<change number="12345" project="core" branch="main" status="NEW" owner="Jane Doe (jdoe)" updated="2026-07-10T20:48:32Z">fix scanner initialization</change>
169+
</changes>
170+
```
171+
172+
There is no XML declaration, no namespaces, and no schema; nothing parses it back. If you need machine-readable
173+
Gerrit data, use Gerrit's REST API directly — this format is for model consumption.
174+
175+
## License
176+
177+
[MIT](LICENSE)

0 commit comments

Comments
 (0)