mcp-rtl-review
# @zesun33/mcp-rtl-review
<!-- BEGIN GENERATED PROJECT GUIDE -->
## Purpose and first steps
Review RTL assignment, width, and reset rules before simulation through an MCP server.
**Who it is for:** Hardware engineers using an MCP-capable client or coding agent.
**First task:** Configure the server in your MCP client, then call `rtl_toolchain_info` before running a design.
**What to expect:** AST-backend availability, then rule findings with source locations and a review score.
**Current scope:** Published static-analysis server using a Verilator AST backend. A review score covers the implemented rules and does not replace simulation or formal properties. The npx command waits for an MCP client.
**Start here:** [Runtime requirements and configuration](README.md#execution-runtime).
**Related projects:** [hw-agent-skills](https://github.com/zesun33/hw-agent-skills), [mcp-verilog](https://github.com/zesun33/mcp-verilog), [mcp-formal](https://github.com/zesun33/mcp-formal).
[Choose another project](https://github.com/zesun33/personal-projects/blob/main/GETTING_STARTED.md).
<!-- END GENERATED PROJECT GUIDE -->
> Model Context Protocol (MCP) server for AST-backed static RTL code review, semantic bug detection, and code review scoring.
[](./LICENSE)
[](https://github.com/zesun33/mcp-rtl-review/actions/workflows/ci.yml)
[](https://modelcontextprotocol.io)
[](#execution-runtime)
`mcp-rtl-review` equips AI coding agents and IDEs (**Cursor**, **Windsurf**, **GitHub Copilot / OpenAI Codex**, **Claude Code**, **Google Antigravity**, **OpenCode**, **Cline**) with structured tools to perform semantic Verilog/SystemVerilog code reviews. It programmatically enforces the cognitive rubrics established in [`hw-agent-skills/skills/rtl-reviewer`](https://github.com/zesun33/hw-agent-skills/blob/main/skills/rtl-reviewer/SKILL.md), parsing full typed ASTs to catch race conditions, improper assignment styles, inverted reset polarities, and bitwidth truncations.
## Install and run
Run this MCP server directly from npm:
```bash
npx -y @zesun33/mcp-rtl-review
```
For the complete hardware-agent setup, use `npx -y @zesun33/create-hw-agent my-asic`.
---
## ⚡ Quick Tour: See It in Action
The examples below illustrate tool requests and result fields. Timings, counts, and scores depend on the input and runtime; they are not guaranteed outcomes or fresh verification results.
### Why AI Agents Need `mcp-rtl-review`
| Without `mcp-rtl-review` (Syntax Linters) | With `mcp-rtl-review` (AST-Backed Semantic Audit) |
| :--- | :--- |
| `verible-lint` only catches surface formatting and whitespace | Analyzes **full typed AST** for deep semantic hardware bugs |
| Misses blocking assignments (`=`) inside clocked sequential blocks | Flags **`SEQ_BLOCKING_ASSIGN`** with exact line and non-blocking `<=` fix |
| Silent active-low reset polarity bugs survive to simulation | Detects **`RESET_POLARITY_MISMATCH`** between sensitivity and `if` branch |
| Implicit bitwidth truncation requires reading manual compiler logs | Immediate **`WIDTH_MISMATCH`** alerts with expected vs actual bitwidths |
| Agent has no feedback on overall design quality | Computes a deterministic **0–100 RTL Quality Score** |
| Requires local installation of Verilator, Python, and C++ compilers | **Zero host configuration** (runs via isolated rootless Podman) |
### Example tool requests and results
#### 1. Probing the Environment (Zero-Config Verification)
```json
// Tool Call: rtl_toolchain_info
{
"runtime": "podman",
"image": "ghcr.io/zesun33/verilog",
"verilatorVersion": "Verilator 5.050 2026-07-01 rev vUNKNOWN-built20260907",
"rulesSupported": [
"SEQ_BLOCKING_ASSIGN",
"COMB_NONBLOCKING_ASSIGN",
"RESET_POLARITY_MISMATCH",
"WIDTH_MISMATCH",
"UNDRIVEN_NET",
"COMBINATIONAL_LOOP",
"UNUSED_SIGNAL",
"MISSING_RESET",
"LATCH_RISK",
"MULTIPLE_DRIVERS",
"CASE_DEFAULT_MISSING",
"INITIAL_BLOCK_SYNTH"
]
}
```
#### 2. Clean Golden Module Audit (Score 100/100)
```json
// Tool Call: rtl_review {"verilog_sources": ["clean_counter.v"], "top_module": "clean_counter"}
{
"passed": true,
"score": 100,
"totalViolations": 0,
"errors": 0,
"warnings": 0,
"info": 0,
"violations": [],
"metrics": {
"modulesAnalyzed": 1,
"alwaysBlocksAnalyzed": 1,
"sequentialBlocks": 1,
"combinationalBlocks": 0,
"linesAnalyzed": 16
},
"rulesChecked": ["SEQ_BLOCKING_ASSIGN", "COMB_NONBLOCKING_ASSIGN", "RESET_POLARITY_MISMATCH", "WIDTH_MISMATCH", "UNDRIVEN_NET", "COMBINATIONAL_LOOP", "UNUSED_SIGNAL", "MISSING_RESET", "LATCH_RISK", "MULTIPLE_DRIVERS", "CASE_DEFAULT_MISSING", "INITIAL_BLOCK_SYNTH"]
}
```
#### 3. Catching Simulation Race Conditions (Blocking Assignment in Sequential Block)
```json
// Tool Call: rtl_check_assignments {"verilog_sources": ["blocking_in_seq.v"], "top_module": "blocking_in_seq"}
{
"passed": false,
"totalViolations": 2,
"blockingInSeq": [
{
"file": "fixtures/blocking_in_seq.v",
"line": 11,
"variable": "count",
"message": "Blocking assignment '=' to 'count' inside sequential (clocked) block. This causes simulation race conditions.",
"fixSuggestion": "Replace '=' with non-blocking assignment '<=' to 'count'."
},
{
"file": "fixtures/blocking_in_seq.v",
"line": 13,
"variable": "count",
"message": "Blocking assignment '=' to 'count' inside sequential (clocked) block. This causes simulation race conditions.",
"fixSuggestion": "Replace '=' with non-blocking assignment '<=' to 'count'."
}
],
"nonBlockingInComb": []
}
```
#### 4. Flagging Inverted Reset Polarity
```json
// Tool Call: rtl_review {"verilog_sources": ["reset_mismatch.v"], "top_module": "reset_mismatch"}
{
"passed": false,
"score": 85,
"errors": 1,
"warnings": 0,
"violations": [
{
"ruleId": "RESET_POLARITY_MISMATCH",
"severity": "error",
"file": "fixtures/reset_mismatch.v",
"line": 10,
"message": "Reset polarity inversion: sensitivity list declares active-low reset 'rst_n', but if condition checks active-high 'rst_n'.",
"fixSuggestion": "Change condition to 'if (!rst_n)' to match sensitivity list polarity."
}
]
}
```
#### 5. Detecting Bitwidth Truncation & Expansion
```json
// Tool Call: rtl_check_widths {"verilog_sources": ["width_mismatch.v"], "top_module": "width_mismatch"}
{
"passed": false,
"totalMismatches": 1,
"widthMismatches": [
{
"file": "fixtures/width_mismatch.v",
"line": 9,
"expectedWidth": 4,
"actualWidth": 8,
"message": "Operator ASSIGN expects 4 bits on the Assign RHS, but Assign RHS's VARREF 'in_b' generates 8 bits.",
"fixSuggestion": "Verify signal widths and explicitly slice or sign-extend operands to avoid unintended truncation."
}
]
}
```
---
## Tools Exposed
| Tool | Parameters | Engine | Description |
| :--- | :--- | :--- | :--- |
| `rtl_review` | `verilog_sources: string[]`<br>`top_module?: string`<br>`ruleset?: "strict" \| "standard" \| "relaxed"`<br>`include_info?: boolean`<br>`cwd?: string` | Verilator JSON/XML AST + Diagnostics | Full AST-backed static RTL review evaluating assignment discipline, reset polarity, bitwidths, and undriven nets, returning a 0–100 Quality Score. |
| `rtl_check_assignments` | `verilog_sources: string[]`<br>`top_module?: string`<br>`cwd?: string` | AST Assignment Visitor | Audits source files specifically for assignment discipline violations (`=` in sequential or `<=` in combinational). |
| `rtl_check_widths` | `verilog_sources: string[]`<br>`top_module?: string`<br>`cwd?: string` | Verilator Semantic Lint | Performs bitwidth analysis to identify implicit truncation and unintended extension bugs. |
| `rtl_check_resets` | `verilog_sources: string[]`<br>`top_module?: string`<br>`cwd?: string` | AST Reset Visitor | Audits reset usage per sequential block: presence, identity, edge, and polarity agreement. |
| `rtl_generate_assertion` | `signal: string`<br>`property_type: no_x_after_reset \| reset_value \| req_ack_handshake \| onehot`<br>`clock?`<br>`reset?` | SVA Templates | Generates a SystemVerilog Assertion scaffold with a TODO to bind and prove it (scaffolding only). |
| `rtl_toolchain_info` | `cwd?: string` | Probe | Returns container/host runtime and version information for the Verilator AST parser and supported rule catalog. |
---
## AST backend compatibility
The server selects `--json-only` when the installed Verilator advertises it and reads the JSON tree with its separate file metadata. Older toolchains without that option use `--xml-only`. Both feed the same assignment/reset rule engine. Verilator removed XML output in 5.046; see the [official option reference](https://verilator.org/guide/latest/exe_verilator.html#cmdoption-xml-only).
Verified against the available container toolchains: all 12 integration tests pass on both Verilator 5.050 (JSON) and 5.020 (legacy XML). The JSON parser fixture was captured from 5.050's `clean_counter` output; pointer metadata is excluded because review uses file IDs and source locations.
Compiler diagnostics and nonzero exits are preserved through temporary-file cleanup. Missing, malformed, or module-free AST output produces a failed review/assignment/reset audit, even if the compiler exits zero. Source paths and top-module arguments are passed as literal arguments rather than interpolated shell text.
Version `0.2.2` includes the JSON AST backend and legacy XML fallback. Use `npx -y @zesun33/mcp-rtl-review@0.2.2` to select the fixed release explicitly. Version `0.2.1` contains the earlier XML-only backend. To run a source checkout, use `npm ci`, `npm run build`, and a client command pointing to `node /path/to/mcp-rtl-review/dist/index.js`.
## Execution Runtime
For tested tarball releases and GitHub Actions trusted publishing, see [RELEASING.md](https://github.com/zesun33/mcp-rtl-review/blob/main/RELEASING.md).
`mcp-rtl-review` runs inside the [`zesun33/verilog`](https://github.com/zesun33/eda-docker-images) rootless Podman image so tools are identical on any Linux host.
**Public install (recommended — anyone can pull):**
```bash
podman pull ghcr.io/zesun33/verilog:latest
export MCP_RTL_REVIEW_IMAGE=ghcr.io/zesun33/verilog
```
`ghcr.io/zesun33/verilog` is the default (anyone can pull). Local builds still work as `localhost/zesun33/verilog` via `MCP_RTL_REVIEW_IMAGE`.
- Container mount: `-v <workspace>:/workspace:Z -w /workspace`
- Podman storage option: `--storage-opt overlay.ignore_chown_errors=true`
To force host binaries instead of container execution:
```bash
export MCP_RTL_REVIEW_RUNTIME=host
```
---
## Client Configuration
To register `mcp-rtl-review` with your AI IDE or agent, add it to your configuration file (e.g., `.cursor/mcp.json`, `claude_desktop_config.json`, or Windsurf settings):
```json
{
"mcpServers": {
"rtl-review": {
"command": "node",
"args": ["/path/to/mcp-rtl-review/dist/index.js"],
"env": {
"MCP_RTL_REVIEW_RUNTIME": "podman",
"MCP_RTL_REVIEW_IMAGE": "ghcr.io/zesun33/verilog"
}
}
}
}
```
### Universal Compatibility
Works seamlessly across all modern AI coding environments:
- **Cursor**: Configure in `.cursor/mcp.json`.
- **Windsurf**: Configure in `~/.codeium/windsurf/mcp_config.json`.
- **GitHub Copilot / OpenAI Codex**: Configure via Copilot MCP settings or Codex tool proxy.
- **Claude Code**: Configure via `claude mcp add rtl-review node /path/to/dist/index.js`.
- **Google Antigravity**: Load as workspace MCP server in `antigravity.json`.
- **OpenCode & Cline**: Direct stdio JSON-RPC connection.
---
## Verification & Testing
Strict 6-gate verification suite matching the portfolio engineering standard:
```bash
# Full verification (all 6 gates with Podman integration)
./scripts/verify.sh
# Fast / CI verification (headless environments)
./scripts/verify.sh --quick
# Target specific gates
./scripts/verify.sh --gate 1 # Spec lock & package integrity
./scripts/verify.sh --gate 2 # Static build (TypeScript)
./scripts/verify.sh --gate 3 # Unit tests (AST parser & rule engine)
./scripts/verify.sh --gate 4 # Live Podman container integration tests
./scripts/verify.sh --gate 5 # Stdio JSON-RPC contract check
./scripts/verify.sh --gate 6 # Documentation validation
```
---
## License
Apache-2.0 © 2026 Md Zesun Ahmed Mia
TDQS
Scored across 4 tools
The full review tool overlaps with the two targeted check tools, but each has a clearly scoped purpose: comprehensive audit versus specific assignment or width checks. The toolchain info tool is entirely distinct. Some ambiguity exists about when to run the full review versus individual checks, but descriptions mitigate it well.
All tools share the rtl_ prefix, but the naming pattern is mixed: two use verb_noun (rtl_check_assignments, rtl_check_widths), while rtl_review is verb-only and rtl_toolchain_info is noun_noun. The inconsistency is noticeable but still readable and predictable given the shared prefix.
Four tools is well-scoped for a focused RTL review server: one comprehensive review, two targeted checks, and one metadata query. Each tool has a clear purpose and the count feels neither thin nor bloated.
The full review tool provides broad static-analysis coverage including assignments, reset polarity, widths, and undriven nets, while the targeted check tools allow narrower queries. The toolchain info tool supplies environment and rule-compatibility context. No obvious missing operations are apparent for the stated purpose.