Verifiable audit trails for AI agent actions on GitHub.
When an AI agent leaves a comment or review on a GitHub PR through this MCP server, the comment carries a PrMaat-anchored receipt: a signed JWS that proves which AI agent passport, which device key, which model snapshot, and which room context produced that exact opinion.
GitHub's native audit shows which account wrote a comment. PrMaat closes the gap from account to agent identity — and the verification works offline, without trusting prmaat.com.
$ npx @prmaat/github-anchor --help
GitHub natively proves which account wrote a PR comment. It cannot prove which agent / which runtime / which prompt / which tool-scope produced the decision behind the comment. As AI agents start performing code review at scale, that gap becomes the single biggest audit liability in your stack.
@prmaat/github-anchor closes it. Every anchored comment ends with a
plain-Markdown footer:
---
🛡️ **PrMaat-anchored** · this comment was written by AI agent
[`did:prmaat:e4sKHL…`](https://prmaat.com/passport/e4sKHL…)
in room [`task-rev-2026-05-09`](https://prmaat.com/room/...)
on `2026-05-10T01:23:45Z`.
Receipt: `eyJhbGciOiJFZERTQSI…` ·
[Verify](https://prmaat.com/verify/github?pr=<owner>/<repo>%23<N>&msg=...)(The <owner>/<repo>#<N> placeholder is filled in at post-time by the
package — the Verify link in any real anchored comment points to the
specific PR the comment was written on.)
The footer is plain Markdown — works on github.com without any
extension. The Verify link opens a public PrMaat page that does the
cryptography in your browser. You don't need to trust prmaat.com;
@prmaat/verify (the offline verifier) does the same checks locally.
read_pr({owner, repo, pr_number})
→ { title, body, author, files_changed, head_ref, base_ref, ... }
read_review_thread({owner, repo, pr_number})
→ reviews + comments
list_open_prs({owner, repo, since?})
→ array of PR summaries
post_pr_comment_anchored({owner, repo, pr_number, body, kind?})
→ { commentUrl, receiptJws, verifyUrl }
post_pr_review_anchored({owner, repo, pr_number, body, decision, comments?})
→ { reviewUrl, receiptJws, verifyUrl }
verify_anchored_comment({comment_url})
→ verification result
Reads are unsigned — reads don't need attribution. Writes are all anchored.
npm install -g @prmaat/github-anchorOr zero-install:
npx @prmaat/github-anchor --help{
"mcpServers": {
"prmaat-github-anchor": {
"command": "npx",
"args": ["-y", "@prmaat/github-anchor"],
"env": {
"GITHUB_PAT": "ghp_…",
"PRMAAT_APT": "apt_…",
"PRMAAT_DRY_RUN": "1"
}
}
}
}Restart your MCP host and the AI agent gets the tools above.
This is v0.1.0-pre.1 — a scaffold. Concretely:
- ✅ Read tools functional
- ✅ Write tools accept input + emit a preview receipt
- 🔒 Dry-run by default — every anchored write returns the body it
would have posted, prefixed
[DRY-RUN ANCHOR]. Real GitHub writes ship in v0.2.0 once bridge v0.4 receipt-signing is GA. - 🔒 Real signing requires PrMaat bridge v0.4 (not yet shipped). v0.1 emits unsigned-preview receipts so operators can validate the end-to-end shape.
| Version | Behavior |
|---|---|
| 0.1.0-pre.1 (now) | scaffold + read tools + dry-run preview writes |
| 0.1.0 | MCP SDK wiring, real read tools |
| 0.2.0 | real writes against PRMAAT_GITHUB_ANCHOR_ALLOWED_REPOS allowlist |
| 0.3.0 | workspace-mode, per-repo policy file |
| 1.0.0 | stable + prmaat verify-github CLI |
| Var | Purpose |
|---|---|
GITHUB_PAT |
GitHub personal-access token (scope: pull_requests:write for target repos) |
PRMAAT_APT |
Agent passport bearer (apt_…) — same as any PrMaat bridge |
PRMAAT_HTTP |
API base (default https://prmaat.com) |
PRMAAT_DRY_RUN |
"0" to enable real writes (v0.2.0+); default "1" |
PRMAAT_GITHUB_ANCHOR_ALLOWED_REPOS |
newline-separated owner/repo allowlist |
@prmaat/github-anchor refuses to post on failure — there is no
silent fallback to unsigned comments. If the bridge is offline, the
token is expired, or the receipt sign fails, the GitHub POST does not
happen. The package surfaces the unsigned body to the AI so it can
copy-paste manually if urgent — but never under PrMaat's name.
This is the explicit design: every PrMaat-anchored comment is verifiable, or it is not posted.
A third party verifying a PR comment with the PrMaat anchor footer has two paths:
Hosted (convenience):
- Click the
Verifylink. Browser-local Ed25519 verify against the agent's published DID document.
Offline (zero-trust):
npx @prmaat/verify verify-receipt \
--jws <jws-from-footer> \
--did https://prmaat.com/api/passports/<DID>/did.json \
--content-hash-source <github-comment-url>Both paths run the same cryptography. The hosted page is faster; the offline CLI proves the hosted page isn't lying.
War launch room verdict, 2026-05-09. 4-of-4 advisor convergence:
Maat (spec lens, 9/10): "GitHub proves which account wrote a review, but NOT which agent/runtime/prompt/tool-scope produced the decision; PrMaat adds a receipt bound to passport DID + device-signed."
Blanco (messaging lens, 9/10): "30-second video clear: AI reviews PR, leaves comment/approval, PrMaat proves this opinion came from a specific agent passport via device-signed receipt, not just a bot."
Police (risk lens): smallest blast radius — receipts add proof without expanding the host platform's attack surface.
UX (adoption lens): every codeowner already cares who reviewed what; the audit-curious user base is pre-built.
- PrMaat Spec v0.4 §15 — Connectors / GitHub (promote pending Round 2 closeout)
- Verifiable Execution Receipts (R29 v0.2.1)
- Source: github.com/PrMaat/github-anchor
- Sister packages: @prmaat/verify, @prmaat/cli, @prmaat/mcp
MIT