An MCP server for managing Architectural Decision Records (ADRs). Provides tools to create, read, update, validate, and analyze ADRs with support for multiple templates (MADR, Nygard), linking, supersession, and intelligent analysis.
AdrMcp demonstrates solid tool design with 18 well-named, verb-prefixed tools organized into logical groups (Authoring, Navigation, Intelligence, Utility). All tools have descriptions (avg ~120 chars) and input schemas with typed parameters. Strengths: clear naming (create_adr, update_adr, search_adrs), consistent preview-by-default pattern for mutations, good parameter descriptions. Weaknesses: output schemas are not documented in the source code provided; error handling guidance is minimal; some parameters lack enum constraints (e.g., 'status' and 'template' accept free-form strings despite having known valid values); no tool annotations (readOnlyHint/destructiveHint) visible in the MCP registration.
Report ADR coverage per architectural area (mapped to tags). Areas with zero ADRs are decision gaps. Provide 'areas' to check a specific set, otherwise all tags are reported.
Create a new ADR from a template (madr or nygard). Previews the file by default; set preview_only=false to write it.
Find ADR pairs that conflict: explicit conflicts-with links plus highly similar accepted decisions.
Diff two ADRs' bodies, or (when 'other' is omitted) diff an ADR's on-disk file against its canonical rendering to reveal formatting drift.
Find ADRs related to a given ADR: incoming/outgoing links plus its supersession chain.
Find non-rejected ADRs whose code_refs no longer resolve against the repository (stale decisions).
Output schemas not documented. Tools return MutationResult, AdrDetail, ConflictReport, etc., but the response structure is not visible in tool definitions. LLMs cannot plan downstream calls or extract required fields without documented return types.
Missing enum constraints on known-value parameters. 'template' accepts 'madr' or 'nygard'; 'status' accepts 'proposed', 'accepted', 'rejected', 'deprecated', 'superseded'; 'type' (link_adrs) accepts 'relates-to', 'supersedes', 'superseded-by', 'conflicts-with'. Free-form strings invite hallucinated values. Declare these as enums in the schema.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 62 | 2026-07-28+ | v2 |
Get a single ADR by id or slug. Pass 'sections' to return only specific ## sections (token-efficient).
Return the full ADR relationship graph (nodes + typed edges).
Return the decision log: every ADR as a chronological/id-ordered timeline entry.
Create a typed link between two ADRs (supersedes, superseded-by, relates-to, conflicts-with). Adds the inverse on the target unless bidirectional=false. Preview-by-default.
List ADRs, optionally filtered by status, tag, or date range. Returns compact summaries.
Regenerate the browsable decision index (README.md in the ADR folder). Preview-by-default.
Search ADRs. Lexical by default; set semantic=true for term-vector similarity ranking.
Transition an ADR's status. Enforces the lifecycle (e.g. proposed->accepted). Preview-by-default.
Given a unified diff, draft an ADR proposal: a suggested title, code_refs for the changed files, and a ready-to-edit MADR body. Does not write anything.
Create a new ADR that supersedes an existing one: writes the new ADR (accepted), marks the old superseded, and links both — in one call. Preview-by-default.
Replace (or append) the content of a single ## section of an ADR. Preview-by-default.
Validate one ADR (by id/slug) or the whole corpus: required sections, valid status, dangling links, duplicate ids.
No tool annotations visible. Mutation tools (create_adr, update_adr, set_status, supersede_adr, link_adrs, render_index) should declare destructiveHint=true or idempotentHint=true. Read-only tools should declare readOnlyHint=true. This metadata guides agent planning and safety checks.
Error handling lacks recovery guidance. Tests show validation errors (e.g., 'ADR not found', 'invalid status transition') but tool descriptions do not explain what the LLM should do next. Add guidance like 'If ADR not found, call list_adrs() to find the correct id or slug.'
Pagination not visible for list_adrs and search_adrs. These tools accept 'topK' (search_adrs) but no offset/limit or cursor. If a corpus has 100+ ADRs, results may be truncated without the LLM knowing. Add explicit pagination parameters and document the limit in the description.