Skip to content

Commit 32f8e23

Browse files
committed
rework README prose to read naturally
Em dashes carried most of the sentence structure; they are replaced with plain punctuation or restructured sentences. Bold label leads on list items and paragraphs become plain text, padded participle tails and stacked negations become full clauses. Tables, code blocks, flag names, and content coverage are unchanged.
1 parent ce8f8bd commit 32f8e23

1 file changed

Lines changed: 68 additions & 69 deletions

File tree

README.md

Lines changed: 68 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
# go-gerrit-mcp
22

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.
3+
An MCP (Model Context Protocol) server that exposes Gerrit code review operations as capability-gated tools. An AI
4+
agent can search and read changes, publish review comments, vote, and drive change-state transitions. Every write
5+
capability is an explicit operator opt-in.
66

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))
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))
1010

1111
## Safety posture
1212

1313
Two defaults encode it:
1414

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 seeare refused on changes the authenticated account does
18-
not own, until the operator explicitly passes `--own-changes-only=false`.
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 (comments,
17+
votes, state changes, anything other humans see) are refused on changes the authenticated account does not own,
18+
until the operator explicitly passes `--own-changes-only=false`.
1919

2020
An agent leaving unwanted trail on colleagues' changes is an externally visible failure; a missing capability is a
2121
locally discoverable inconvenience. The defaults are chosen accordingly. Widen deliberately:
@@ -27,7 +27,7 @@ go-gerrit-mcp --groups read,comment,transition --own-changes-only=false --projec
2727

2828
## Install
2929

30-
**Binary release** download the binary for your platform from
30+
Binary release: download the binary for your platform from
3131
[GitHub Releases](https://github.com/GaijinEntertainment/go-gerrit-mcp/releases), make it executable, and put it on
3232
your `PATH`:
3333

@@ -38,21 +38,21 @@ curl -Lo /usr/local/bin/go-gerrit-mcp \
3838
chmod +x /usr/local/bin/go-gerrit-mcp
3939
```
4040

41-
**Docker:**
41+
Docker:
4242

4343
```sh
4444
docker pull ghcr.io/gaijinentertainment/go-gerrit-mcp:latest
4545
```
4646

47-
**go install:**
47+
go install:
4848

4949
```sh
5050
go install dev.gaijin.team/go/go-gerrit-mcp/cmd/go-gerrit-mcp@latest
5151
```
5252

5353
## Quick start
5454

55-
The server reads connection identity from environment variables only credentials never travel through flags:
55+
The server reads connection identity from environment variables only; credentials never travel through flags:
5656

5757
| Variable | Meaning |
5858
| ----------------- | -------------------------------------------------- |
@@ -116,12 +116,12 @@ claude mcp add gerrit \
116116

117117
## Per-project configuration in Claude Code
118118

119-
Everything the server needs is read from the environmentthe identity variables above plus a `GERRIT_MCP_*`
120-
mirror for every flag (see [Configuration reference](#configuration-reference)) — and MCP server processes inherit
121-
the session environment. In Claude Code that turns one user-level registration into per-project configuration,
122-
down to different Gerrit instances with different credentials per repository.
119+
Everything the server needs is read from the environment: the identity variables above plus a `GERRIT_MCP_*` mirror
120+
for every flag (see [Configuration reference](#configuration-reference)). MCP server processes inherit the session
121+
environment, so in Claude Code one user-level registration turns into per-project configuration, down to different
122+
Gerrit instances with different credentials per repository.
123123

124-
**`~/.claude.json`** the registration; no `env` block:
124+
`~/.claude.json` holds the registration, with no `env` block:
125125

126126
```json
127127
{
@@ -133,7 +133,7 @@ down to different Gerrit instances with different credentials per repository.
133133
}
134134
```
135135

136-
**`<project>/.claude/settings.local.json`** the project's environment; every `env` entry reaches the server
136+
`<project>/.claude/settings.local.json` carries the project's environment; every `env` entry reaches the server
137137
process:
138138

139139
```json
@@ -148,22 +148,22 @@ process:
148148
}
149149
```
150150

151-
Values shared by most projects can sit one layer down in `~/.claude/settings.json` — settings files merge with
152-
`.claude/settings.local.json` over `.claude/settings.json` over `~/.claude/settings.json`so a project declares
153-
only its deltas. Anything no layer sets falls back to the server's own defaults: read-only, own changes.
151+
Values shared by most projects can sit one layer down in `~/.claude/settings.json`. Settings files merge, with
152+
`.claude/settings.local.json` over `.claude/settings.json` over `~/.claude/settings.json`, so a project declares only
153+
its deltas. Anything no layer sets falls back to the server's own defaults: read-only, own changes.
154154

155-
The registration's `env` block stays empty for a reason: a variable named there shadows every settings layer, and
156-
references are not a way around that — they never resolve from settings files. `${VAR}` expands only from the
157-
shell environment that launched `claude`, and anything unresolved reaches the server as a literal string.
155+
The registration's `env` block stays empty for a reason. A variable named there shadows every settings layer, and
156+
references are no workaround: `${VAR}` expands only from the shell environment that launched `claude`, never from
157+
settings files, and anything unresolved reaches the server as a literal string.
158158

159159
Other MCP clients inherit their launch environment the same way, so per-directory tooling such as
160160
[direnv](https://direnv.net/) achieves the identical split without client support.
161161

162162
## Capability groups
163163

164-
Capability is selected at startup via `--groups` as a comma-separated list. Groups are independent and combinable
165-
there is no ladder; each write-capable group bundles the minimal change-read subset it needs to function on its own,
166-
and enabled groups union.
164+
Capability is selected at startup via `--groups` as a comma-separated list. Groups are independent and combinable,
165+
with no privilege ladder: each write-capable group bundles the minimal change-read subset it needs to work on its
166+
own, and enabled groups union.
167167

168168
| Group | Tools |
169169
| ------------ | ---------------------------------------------------------------------------------------- |
@@ -173,63 +173,63 @@ and enabled groups union.
173173

174174
### Tools
175175

176-
- `search_changes` query changes with Gerrit's change query syntax, paginated.
177-
- `get_change` one change in review-relevant detail: status, owner, labels with votes, current revision, messages.
178-
- `list_change_files` files touched by a revision, with per-file change stats.
179-
- `get_file_diff` the diff of one file in a revision.
180-
- `get_change_comments` comment threads on a change, with resolution state and comment ids. Returns unresolved
176+
- `search_changes`: query changes with Gerrit's change query syntax, paginated.
177+
- `get_change`: one change in review-relevant detail: status, owner, labels with votes, current revision, messages.
178+
- `list_change_files`: files touched by a revision, with per-file change stats.
179+
- `get_file_diff`: the diff of one file in a revision.
180+
- `get_change_comments`: comment threads on a change, with resolution state and comment ids. Returns unresolved
181181
threads only by default; `status=all` fetches the full history, `status=resolved` the settled threads.
182-
- `post_comments` publish a review in one call: optional top-level message plus inline, range, file-level, and
183-
reply comments; replies anchor to comment ids from `get_change_comments`; `resolved` toggles the thread state.
184-
- `set_vote` set a label vote (e.g. `Code-Review`) with an optional message; value `0` clears an own vote.
185-
- `transition_change` move a change's state: `submit`, `abandon`, `restore`, `wip`, or `ready`, with an optional
186-
message (submit accepts none). Gerrit's refusal a blocked submit, a restore of a merged change is reported
182+
- `post_comments`: publish a review in one call: optional top-level message plus inline, range, file-level, and
183+
reply comments. Replies anchor to comment ids from `get_change_comments`; `resolved` toggles the thread state.
184+
- `set_vote`: set a label vote (e.g. `Code-Review`) with an optional message; value `0` clears an own vote.
185+
- `transition_change`: move a change's state: `submit`, `abandon`, `restore`, `wip`, or `ready`, with an optional
186+
message (submit accepts none). Gerrit's refusal (a blocked submit, a restore of a merged change) is reported
187187
verbatim.
188188

189189
## Review notifications
190190

191-
An opt-in push channel for review activity. The agent subscribes to a change (`subscribe_change`), and from then on
192-
new change messages, votes, inline comment threads, and status transitions arrive in the session by themselves as
193-
`review_activity` blocksthe same llmxml vocabulary the read tools emit, activity carried whole, so nothing needs
194-
fetching afterwards. `unsubscribe_change` ends a subscription early; a merged or abandoned change ends its own with
195-
a final notification saying so, and a change that becomes unreadable (deleted, or no longer visible to the account)
196-
does the same naming the reason.
191+
An opt-in push channel for review activity. The agent subscribes to a change with `subscribe_change`; from then on,
192+
new change messages, votes, inline comment threads, and status transitions arrive in the session on their own as
193+
`review_activity` blocks. The payload uses the same llmxml vocabulary the read tools emit and carries the activity
194+
whole, so nothing needs fetching afterwards. `unsubscribe_change` ends a subscription early. A merged or abandoned
195+
change ends its own subscription with a final notification that says so, and a change that becomes unreadable
196+
(deleted, or no longer visible to the account) does the same, with the reason spelled out.
197197

198198
Subscriptions are per-session and in-memory: they leave no trace on the Gerrit instance, end with the session, and
199-
after a server restart the agent subscribes again. With the feature off the default the server is byte-identical
200-
to its pre-feature self: no extra tools, no extra capability, no background polling.
199+
after a server restart the agent subscribes again. With the feature off (the default) the server is byte-identical
200+
to its pre-feature self, with no extra tools or capabilities and no background polling.
201201

202202
Enabling takes both sides:
203203

204-
1. **Server**`--review-notifications=true` (or its mirror). The server registers both subscription tools and
205-
polls Gerrit every `--review-notifications-poll-interval` (default `60s`): one batched query per tick over all
206-
subscribed changes, detail fetches only for changes that actually moved.
207-
2. **Client** delivery rides the Claude Code **channels** contract (research preview, Claude Code 2.1.80).
204+
1. Server side: pass `--review-notifications=true` (or its mirror). The server registers both subscription tools
205+
and polls Gerrit every `--review-notifications-poll-interval` (default `60s`): one batched query per tick over
206+
all subscribed changes, with detail fetches only for changes that actually moved.
207+
2. Client side: delivery uses the Claude Code channels contract (research preview, Claude Code 2.1.80 or newer).
208208
For a server registered plainly under `mcpServers`, launch with
209-
`claude --dangerously-load-development-channels server:<name>`, where `<name>` is the registration key it
209+
`claude --dangerously-load-development-channels server:<name>`, where `<name>` is the registration key; it
210210
becomes the `source` attribute of the injected `<channel>` blocks. Allowlisted channel plugins load with
211211
`claude --channels` instead.
212212

213213
Research-preview caveats: organization policy can disable channels entirely; the flag syntax may change between
214-
Claude Code releases; and a client without channel support silently drops the events — the server then degrades to
215-
exactly its pre-feature behavior, with no errors on either side.
214+
Claude Code releases; and a client without channel support silently drops the events, in which case the server
215+
behaves exactly as if the feature were off, with no errors on either side.
216216

217-
Noise control is operator configuration, not server heuristics — nothing is filtered by message tag, because a CI
218-
verdict is often exactly the awaited outcome:
217+
Noise control is operator configuration. The server applies no heuristics of its own and filters nothing by message
218+
tag, because a bot's verdict is often exactly the outcome the agent is waiting for:
219219

220220
- the authenticated account's own activity is skipped by default (`--review-notifications-include-own` keeps it);
221221
- `--review-notifications-exclude-accounts` silences accounts by username or numeric ID;
222222
- `--review-notifications-exclude-patterns` drops events whose message or comment text matches a regular
223-
expression; an invalid pattern fails startup naming it.
223+
expression; an invalid pattern fails startup with an error naming it.
224224

225-
Every flag has a `GERRIT_MCP_*` mirror riding the same settings layering as the rest of the configuration (see
226-
[Per-project configuration](#per-project-configuration-in-claude-code)), so a project can enable notifications and
227-
pick its exclusions in its own settings file.
225+
Every flag has a `GERRIT_MCP_*` mirror that follows the same settings layering as the rest of the configuration
226+
(see [Per-project configuration](#per-project-configuration-in-claude-code)), so a project can enable notifications
227+
and pick exclusions in its own settings file.
228228

229229
## Configuration reference
230230

231231
Behavior is configured by CLI flags, each mirrored by an environment variable so one configuration style works for
232-
binary and Docker invocations alike. Precedence: **flag wins over its mirror, the mirror wins over the default.**
232+
binary and Docker invocations alike. Precedence: the flag wins over its mirror, and the mirror wins over the default.
233233

234234
| Flag | Mirror | Default | Meaning |
235235
| -------------------- | ----------------------------- | ------- | -------------------------------------------------------------- |
@@ -248,18 +248,17 @@ Notes:
248248

249249
- `--own-changes-only` takes an explicit boolean value: `--own-changes-only=false`. A bare flag without a value is a
250250
configuration error.
251-
- **Project scoping** (`--projects`) is enforced server-side: a project clause is injected into every change query
251+
- Project scoping (`--projects`) is enforced server-side: a project clause is injected into every change query
252252
regardless of what the agent composed, and direct operations on out-of-scope changes are refused.
253-
- **Tool filters** only narrow. `--exclude-tools` removes tools from what the groups resolved; `--include-tools`
254-
keeps only the listed subset of it. A tool outside the enabled groups can never be activated by a filter, and
255-
exclude wins over include. Filter entries naming no known tool fail startup, so misconfigurations surface
256-
immediately.
253+
- Tool filters only narrow. `--exclude-tools` removes tools from what the groups resolved; `--include-tools` keeps
254+
only the listed subset of it. A tool outside the enabled groups can never be activated by a filter, and exclude
255+
wins over include. Filter entries naming no known tool fail startup, so misconfigurations surface immediately.
257256
- Configuration errors are aggregated: the server reports every problem at once, then exits non-zero.
258257

259258
## Output format
260259

261-
Every tool responds in **llmxml**: an LLM-digestible subset of XMLline-structured, semantically tagged text meant
262-
to be read by a model. Attributes carry metadata, element bodies carry content:
260+
Every tool responds in llmxml, an LLM-digestible subset of XML: line-structured, semantically tagged text meant to
261+
be read by a model. Attributes carry metadata; element bodies carry content:
263262

264263
```
265264
<changes query="status:open owner:self" start="0" count="1" more="false">
@@ -268,7 +267,7 @@ to be read by a model. Attributes carry metadata, element bodies carry content:
268267
```
269268

270269
There is no XML declaration, no namespaces, and no schema; nothing parses it back. If you need machine-readable
271-
Gerrit data, use Gerrit's REST API directly this format is for model consumption.
270+
Gerrit data, use Gerrit's REST API directly; this format is for model consumption.
272271

273272
## License
274273

0 commit comments

Comments
 (0)