Content
# vivado-mcp
[](https://pypi.org/project/vivado-mcp/)
[](https://pypi.org/project/vivado-mcp/)
[](LICENSE)
[](https://github.com/mapleleavessssssss-wq/vivado-mcp/actions/workflows/ci.yml)
A lean MCP server that lets AI agents (Claude Code, Cursor, etc.) drive Xilinx Vivado: synthesis, implementation, XSim simulation & waveforms, timing / CRITICAL WARNING diagnostics — 30 curated tools, everything else via raw `run_tcl`.
> **TL;DR (English)** — A lean MCP server that lets AI agents (Claude Code, Cursor, etc.) drive Xilinx Vivado: synthesis, implementation, XSim simulation & waveforms, timing / CRITICAL WARNING diagnostics — 30 curated tools, everything else via raw `run_tcl`. Docs and diagnostic messages are in English.
**Table of Contents**:[Environment Requirements](#environment-requirements) · [Quick Start](#quick-start) · [Design Philosophy](#design-philosophy-why-30-tools-instead-of-500) · [Features](#features) · [Session Modes](#session-modes) · [Tool List](#tool-list) · [Hook Configuration](#optional-claude-code-hook-configuration-example) · [Usage Examples](#usage-examples---a-complete-debugging-loop) · [Architecture](#architecture) · [CLI Reference](#cli-reference) · [Feedback](#feedback-and-bug-submission)
## Environment Requirements
- **Python ≥ 3.10**, Windows / Linux
- **Xilinx Vivado**: The author has long-term practical experience with **2019.1**; the protocol layer is pure Tcl, and 2018.3 / 2022.2 have been actually used by community users (see issues / PR), and other versions are theoretically compatible
- **Zero additional dependencies** — Only depends on the `mcp` SDK, and testing does not require Vivado
## Quick Start
### 1. Installation
```bash
pip install vivado-mcp
```
### 2. Inject Vivado (one-time)
```bash
vivado-mcp install
```
This will modify your Vivado's `Vivado_init.tcl` to automatically start the TCP server when the GUI is launched (binding to a single port specified by the installation, default 9999; exit if occupied, without sliding to other ports). **The original file will be backed up**, and `vivado-mcp uninstall` can be used to restore.
If Vivado is installed in a protected directory (such as `C:\Program Files\`), run the command with administrator privileges.
### 3. Configure Claude Code
Copy the following content to the `mcpServers` field of `~/.claude.json`:
```json
"vivado": {
"command": "python",
"args": ["-m", "vivado_mcp"],
"env": {
"VIVADO_PATH": "D:/Xilinx/Vivado/2024.1/bin/vivado.bat"
},
"type": "stdio"
}
```
> Replace `VIVADO_PATH` with the actual path to your Vivado:
> - **Windows**: `"D:/Xilinx/Vivado/2019.1/bin/vivado.bat"`
> - **Linux**: `"/opt/Xilinx/Vivado/2024.1/bin/vivado"`
> - You can also set `VIVADO_PATH` by adding the Vivado `bin` directory to the system `PATH`.
### 4. Restart Claude Code
After configuration, restart Claude Code to use the 30 Vivado tools.
<details>
<summary>Install from Source (Development/Contribution)</summary>
```bash
git clone https://github.com/mapleleavessssssss-wq/vivado-mcp.git
cd vivado-mcp
pip install -e ".[dev]"
```
</details>
<details>
<summary><b>What's new in 0.3 series</b> (click to expand)</summary>
> - **list_sessions no longer "creates from nothing" (0.3.21)** ⭐: The "active detection of external Vivado" added in 0.3.19 would occasionally report false positives on machines with VMware / Hyper-V virtual network cards installed - the port 10000 would coincidentally return a JSON-like data that was mistaken for Vivado. This version adds a **random token** to the handshake (`puts VMCP_PROBE_<uuid>`), and the server must return the token as is to be considered a real Vivado - false positives are reduced to zero
> - **Vivado error messages now include a "cleanup guide" (0.3.20)** ⭐: When waveform-related commands (`open_wave_database` / `add_wave` / `log_wave`, etc.) fail, the Vivado GUI will leave behind **orphaned simulation tabs and hundreds of MB of memory waste**. This version automatically appends a copyable `close_sim` / `close_wave_config` cleanup script snippet to the error output, so AI does not have to manually check for quirks; meanwhile, four XSim scripting pitfalls are included in the `run_tcl` tool description (e.g., `set_property RADIX` must be in lowercase `dec`, not uppercase `DEC`). **Contract**: The original Vivado output **is not modified, only appended**
> - **Manually opened Vivado GUI can now be "taken over" (0.3.19)** ⭐: When you run `vivado -mode gui` yourself (`vivado-mcp install` has injected `init.tcl` to automatically start the TCP server), and then AI calls `start_session(mode="gui")`, **a second GUI process will no longer be spawned**, but instead directly attached to yours - the port conflict + 800 MB memory waste issue is resolved. `list_sessions` will also list your manually opened session as `<external@port>`, and note that `stop_session` does not have the permission to close it, please exit manually in the GUI
> - **Chinese Windows stdio mode output alignment (0.3.18)** ⭐: In 0.3.17 and earlier, `run_tcl` on Chinese Windows would return paths containing Chinese characters as `锟斤拷` / `` (Vivado stdout defaults to CP936/GBK, but session.py forces UTF-8 decoding). A new `decode_vivado_output()` function is added - strict UTF-8 decoding + fallback to `mbcs` (system code page) when U+FFFD is encountered, aligning the entire chain. **Only affects tcl/stdio mode**, GUI mode TCP UTF-8 protocol is already OK
> - **XSim simulation pit summary automatically injected into run_tcl docstring (0.3.18)**: 0.3.17 users have encountered nine Tcl writing pitfalls in XSim (`add_wave_group` must be `-into $g` / escaped id must `current_scope` context switching / `remove_wave` only recognizes `[get_waves *]` / `xsim -tclbatch` must explicitly `quit`, etc.). A concise summary of these pitfalls is directly included in the `run_tcl` docstring - AI can see it every time it gets the tool description, without waiting to encounter and then ask
> - **Simulation failure automatically peeled (0.3.16)**: When `launch_simulation` fails and the xsim/*.log file is empty (classic pit with Win 11 24H2 default security policy + Vivado 2019.1 spawn bug), `get_critical_warnings(run_name='sim_1')` automatically triggers `.bat` generation with `-scripts_only`, and then executes it in the Vivado session to catch the real error, directly telling you "whether it's a wrapper failure or RTL failure" + provides a one-line `reg add` command to cure
> - **Environment trap startup self-test (0.3.14 / 0.3.16 / 0.3.18)**: `start_session` detects Chinese paths (2019.x TclStackFree, **0.3.18 expands warning: GUI session cd/open_project Chinese path also triggers**) + Win 11 24H2 `NoDefaultCurrentDirectoryInExePath`=1 + registry policy, and gives a warning before stepping into the pit
> - **Timing violation automatic positioning (0.3.9)**: When `get_timing_report` violates, automatically run `report_timing -max_paths 10`, sniff five modes (CDC / HIGH_FANOUT / LONG_COMBO / IO_UNREGISTERED / UNKNOWN) and provide specific Tcl repair commands, no longer letting you stare at the timing log
> - **CW repair effect visualization (0.3.9)**: `get_critical_warnings(compare_with_last=True)` compares with the last snapshot, reports "N eliminated / N new / N still exist", letting "whether the modification is effective" be directly measurable
> - **Long task visualization**: `get_run_progress` makes 10-30 minute synthesis/implementation no longer a black box
> - **Newbie guide**: `get_next_suggestion` tells you what to do next based on the project status
> - **XDC one-click self-repair**: `xdc_auto_fix` automatically supplements IOSTANDARD and create_clock period
> - **External Verilog pre-check**: `verilog_compile_check` uses iverilog/verilator, 50 times faster than Vivado synthesis
> - **IP obsolescence detection**: `get_ip_status` scans out which IPs in the project need to be upgraded
> - **Commit summary**: `get_pre_commit_summary` generates a markdown project summary to directly paste into the commit body
>
> See [CHANGELOG](CHANGELOG.md) for details.
</details>
## Design Philosophy — Why 30 Tools Instead of 500?
Mainstream Vivado MCPs (such as SynthPilot) have 500+ tools, each essentially a Tcl wrapper. The problem is:
- **Each tool occupies AI context** (tool signature injected into every system prompt) → whether or not to use it, it consumes tokens
- **Large models are better at拼Tcl** (e.g., `create_bd_cell` is just a Tcl line)
- **Most facade tools do what `run_tcl("...")` can do**
This project only retains tools with **local value** - things Tcl can't or can't do well:
1. **Structured parsing**: IO / timing reports → JSON / Chinese summary (more concise than raw tables)
2. **Local knowledge base**: CRITICAL WARNING classified by ID + Chinese repair suggestions (hard to write in Tcl)
3. **Cross-command protocol**: sentinel, session management, timeout, bitstream pre-safety check
4. **Cross-session tools**: `compare_xci` pure Python compares two XCI files, no need for Vivado
Others (BD / simulation / XSCT / hardware debugging / IP configuration, etc.) are all handed over to `run_tcl`, letting large models拼Tcl themselves.
## Features
- **Dual-mode sessions**: default GUI visualization (can see Vivado icon + Tcl Console real-time output), also supports headless CI mode and attach to existing GUI
- **30 curated tools + optional hook configuration examples** — covering complete FPGA development process + intelligent diagnosis + newbie guide + external toolchain linkage
- **Intelligent diagnosis** — automatic extraction of CRITICAL WARNING / ERROR classification + Chinese repair suggestions (including 18+ known IDs) after synthesis/implementation
- **IO verification** — XDC constraints (**supporting both -dict and traditional syntax**) compared with actual pin allocation, GT port mismatch marked as CRITICAL
- **IP debugging** — query IP all CONFIG.* parameters (including GUI hidden parameters), pure Python compares two XCI files
- **Bitstream safety check** — automatically detects CRITICAL WARNING and prevents bitstream generation (can be forced to skip)
- **Structured reporting** — IO and timing reports parsed into JSON, making it easy for AI to accurately extract values (**no more "false PASS" traps**)
- **Safe escaping** — `safe_tcl` automatically escapes paths/identifiers into Tcl lists, and Windows paths with spaces/Chinese characters/$ can be used
- **Multi-session support** — default reuse of a single GUI on port 9999 (different session_id also attaches to the same machine); pass `port=0` to automatically allocate an idle port to start an independent instance; server only binds to a single port, exits if occupied
## Session Modes
The `start_session` tool supports three modes:
| mode | effect | suitable for |
|---|---|---|
| `"gui"` (default) | **probe port (0.3.19+): if there is an existing vmcp server, attach directly; otherwise, spawn a new Vivado** | interactive development, real-time waveform/ schematic observation; **supports reusing your manually opened GUI** (as long as `vivado-mcp install` has been run) |
| `"tcl"` | `vivado -mode tcl` headless subprocess | CI, batch processing, no GUI needed |
| `"attach"` | only attach, no spawn (if port has no server, directly report error) | scenarios where a new GUI process is strictly prohibited |
```
User: Start a GUI session
AI: [call start_session(mode="gui")]
→ port is idle → spawn a new Vivado; port is occupied → attach to existing GUI (0.3.19+)
User: I manually opened a Vivado GUI and want to take over
AI: [call list_sessions] → see <external@9999> (your manually opened session)
[call start_session(mode="gui")] → automatically attach, no second GUI spawned
User: batch process 10 projects
AI: [call start_session(mode="tcl")] → no GUI, runs faster
```
## Tool List
### Session Management
| Tool | Description |
|------|------|
| `start_session` | start a Vivado session (three modes: gui/tcl/attach) |
| `stop_session` | close a specified session (B13 fix: taskkill /T recursive process tree killing + clear vivado_pid*.str) |
| `list_sessions` | list all active sessions |
### Tcl Execution (Core)
| Tool | Description |
|------|------|
| `run_tcl` | execute arbitrary Vivado Tcl commands — **main force for AI to拼commands** |
| `safe_tcl` | with parameter template, automatic Tcl escaping, use when paths contain spaces/Chinese characters/$ |
### Design Flow
| Tool | Description |
|------|------|
| `run_synthesis` | run synthesis, Python polling without blocking, automatically open_run + diagnosis after completion |
| `run_implementation` | run implementation (placement and routing) |
| `get_run_progress` | **0.3.2** check run real-time progress: Phase sequence + log tail + mtime, if log does not update for over 2 minutes, automatically prompt possible stuck |
| `generate_bitstream` | generate bitstream (default pre-CRITICAL WARNING safety check) |
| `program_device` | program FPGA device (package open_hw_manager → connect → program) |
### Newbie Guide & Project Survey
| Tool | Description |
|------|------|
| `get_next_suggestion` | **0.3.2** 11-level decision table: no project → open/create, no top-level → set_property TOP, synthesis completed → run_implementation... each level comes with executable commands |
| `get_project_info` | **0.3.0** get project survey in one go: name/part/top-level/source files/XDC/IP/runs status |
| `get_pre_commit_summary` | **0.3.4** generate markdown project summary to directly paste into commit body: project/timing WNS+WHS/resource/CW/READY-WARN-BLOCK access control |
## ... (rest of the document remains the same)
### Diagnostic (Exclusive Differentiation)
| Tool | Description |
|------|------|
| `get_critical_warnings` | Extract and classify CRITICAL WARNING + ERROR by ID, including 18+ known ID repair suggestions. **0.3.9** added `compare_with_last=True` for differential analysis. **0.3.14** checks for non-standard keywords (TclStackFree/segfault/Chinese path cmd error) when errors=0+cw=0 but STATUS=ERROR. **0.3.15/16** for `run_name='sim_*'`: first glob xsim/*.log; if empty, automatically `launch_simulation -scripts_only` + execute `compile/elaborate.bat` within Vivado session to capture errors. |
| `check_bitstream_readiness` | **0.3.0** One-click READY/WARN/BLOCK comprehensive judgment before burning. |
| `verify_io_placement_tool` | Compare XDC constraints (dict/traditional syntax) with actual IO layout, marking CRITICAL for GT mismatches. |
| `xdc_lint` | **0.3.0** Pure Python static XDC checking (PIN_CONFLICT / missing IOSTANDARD / DUPLICATE_PORT / CLOCK_NO_PERIOD / cross-file conflict), no Vivado required. |
| `xdc_auto_fix` | **0.3.3** Automatically supplement IOSTANDARD + create_clock -period, dry_run preview + board profile (basys3/nexys-a7/arty-a7/zybo/kc705), without touching PIN_CONFLICT. |
| `verilog_compile_check` | **0.3.4** Use iverilog/verilator for syntax + connectivity checking, 50x faster than Vivado synthesis. Returns SKIP if not installed, with installation guidance, supporting Windows + scoop path auto-discovery. |
### IP Debugging
| Tool | Description |
|------|------|
| `inspect_ip_params` | Query all CONFIG.* parameters of IP instances (including GUI hidden items), supporting keyword filtering. |
| `compare_xci` | Pure Python comparison of two XCI files' parameter differences (without Vivado session). |
| `get_ip_status` | **0.3.4** Check which IPs need upgrading / are locked / are up-to-date, with upgrade_ip batch suggestions. |
### Offline Preparation (No Vivado Session, Pure Python)
| Tool | Description |
|------|------|
| `parse_xpr` | **0.3.23** Offline parsing of .xpr project files - no Vivado startup, seconds-level retrieval of part/top-level/source files (grouped by fileset, including .v/.mem/.xci IP)/XDC/runs. Refer to `get_project_info` which requires prior `open_project` (Chinese paths may cause TclStackFree crash). |
| `parse_bit_header` | **0.3.23** Offline parsing of .bit headers - design name/part (original `7k325tffg900` + regularized `xc7k325tffg900`)/build date/time/SHA256. Pre-burning error prevention + delivery verification, Vivado has no Tcl command to read offline .bit. |
| `parse_ltx` | **0.3.23** Offline parsing of .ltx ILA probe lists - probe name/width/net mapping. Before connecting the board and grabbing waveforms, get the list; `get_hw_probes` requires an active hw session. |
### Structured Reports
| Tool | Description |
|------|------|
| `get_io_report` | IO pin report (JSON), automatically determining GT/GPIO types. |
| `get_timing_report` | Timing report, including PASS/FAIL judgment, **data source annotation** (post-synth estimation vs. post-route final), critical path details. **0.3.9** automatically appends top N violation paths + 5 mode classifications (CDC/HIGH_FANOUT/LONG_COMBO/IO_UNREGISTERED/UNKNOWN) + specific Tcl repair commands when violating. |
| `get_utilization_report` | **0.3.0** Structured resource utilization (LUT/FF/BRAM/DSP/IOB), marking CRITICAL for > 90% and WARN for 70-90%. |
> For general reports (power/drc/clock/methodology/cdc, etc.), use `run_tcl("report_power -return_string")` directly.
### Waveform Display (XSim)
| Tool | Description |
|------|------|
| `set_wave_zoom` | **0.3.22** Set waveform time zoom window: modify .wcfg XML → close -force → open reload (Vivado 2019.1 has no Tcl zoom command, cross-command protocol encapsulation). |
| `set_wave_analog` | **0.3.22** Set signal to Analog display: automatically supplement STYLE_ prefix + full path/display name addressing + empty object handling (three silent pitfalls sealed at once). Note that zoom before analog (reloading will overwrite analog settings). |
## Optional: Claude Code Hook Configuration Example
> **Note**: The `.claude/` directory is not distributed with the repository/PyPI package; below is an **optional** hook configuration example. Copy it to your project's `.claude/settings.json` to enable it. The hook-imported `vivado_mcp.analysis` module is installed with `pip install vivado-mcp`, no additional scripts needed. All hook commands are **single-line** `python -c` (semicolon concatenation) - executable in both Windows cmd and bash.
Configured, AI not only responds passively but also **actively guards**:
| Hook | Trigger Event | Effect |
|---|---|---|
| `bitstream-guard` | Before AI calls `generate_bitstream` | Prompt a confirmation dialog (permissionDecision: ask): remind to run `check_bitstream_readiness` first, letting you decide to allow or reject, without hard interruption. |
| `xdc-lint` | After saving any `.xdc` file | Pure Python static checking: PIN_CONFLICT / missing IOSTANDARD / create_clock missing -period, etc., no need to wait for synthesis. |
| `verilog-lint` | After saving any `.v` / `.sv` file | Zero-dependency pre-check: module name matching file name / endmodule existence / bracket pairing. |
| `iverilog-check` | After saving any `.v` / `.sv` file | **0.3.4** iverilog or verilator syntax + connectivity checking; silently skipped if not installed; errors interrupt. |
| `session-guard` | When Claude stops | Scan `vivado_pid*.str` files, reminding to clean up unclosed Vivado sessions. |
<details>
<summary>Copyable settings.json Fragment (click to expand)</summary>
```json
{
"hooks": {
"PreToolUse": [
{
"matcher": "mcp__vivado__generate_bitstream",
"hooks": [
{
"type": "command",
"statusMessage": "bitstream-guard",
"command": "python -c \"import json; print(json.dumps({'hookSpecificOutput': {'hookEventName': 'PreToolUse', 'permissionDecision': 'ask', 'permissionDecisionReason': 'Confirm check_bitstream_readiness is ready and conclusion is READY (invalid bitstream generated in timing violation/unrouted state)'}}))\""
}
]
}
],
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"statusMessage": "xdc-lint",
"command": "python -c \"import json,sys; sys.stderr.reconfigure(encoding='utf-8'); d=json.load(sys.stdin); fp=d.get('tool_input',{}).get('file_path') or d.get('tool_response',{}).get('filePath') or ''; fp.lower().endswith('.xdc') or sys.exit(0); from vivado_mcp.analysis.xdc_linter import lint_xdc_files, format_lint_report; r=lint_xdc_files([fp]); r.issues and (sys.stderr.write('[xdc-lint hook] '+format_lint_report(r)+chr(10)), sys.exit(2))\""
},
{
"type": "command",
"statusMessage": "verilog-lint",
"command": "python -c \"import json,sys; sys.stderr.reconfigure(encoding='utf-8'); d=json.load(sys.stdin); fp=d.get('tool_input',{}).get('file_path') or d.get('tool_response',{}).get('filePath') or ''; fp.lower().endswith(('.v','.sv')) or sys.exit(0); from vivado_mcp.analysis.verilog_quick_check import quick_check_verilog, format_report; t=format_report(quick_check_verilog(fp)); t and (sys.stderr.write('[verilog-lint hook] '+t+chr(10)), sys.exit(2))\""
},
{
"type": "command",
"statusMessage": "iverilog-check",
"command": "python -c \"import json,sys; sys.stderr.reconfigure(encoding='utf-8'); d=json.load(sys.stdin); fp=d.get('tool_input',{}).get('file_path') or d.get('tool_response',{}).get('filePath') or ''; fp.lower().endswith(('.v','.sv')) or sys.exit(0); from vivado_mcp.analysis.verilog_compile_check import compile_check, format_compile_report; r=compile_check([fp], tool='auto', timeout=15.0); r.tool_available or sys.exit(0); r.errors and (sys.stderr.write('[iverilog-check hook] '+format_compile_report(r)+chr(10)), sys.exit(2))\""
}
]
}
],
"Stop": [
{
"hooks": [
{
"type": "command",
"statusMessage": "session-guard",
"command": "python -c \"import sys,glob; sys.stderr.reconfigure(encoding='utf-8'); pids=glob.glob('vivado_pid*.str'); pids and (sys.stderr.write('[session-guard] Found uncleaned Vivado session traces: '+', '.join(pids)+'。建议用 mcp__vivado__stop_session clean or manually delete .str files.'+chr(10)), sys.exit(2))\""
}
]
}
]
}
}
```
</details>
Copy the fragment into your project's `.claude/settings.json`, and Claude Code will pop up: *"Detected project configured with hooks, trust?"* — select **Yes** to enable.
To disable individual or all hooks: write `{"hooks": {}}` in `.claude/settings.local.json` (personal local file, not in git) to override.
## Usage Example — A Complete Debugging Loop
Below is a real example run on a machine (Vivado 2019.1 + basys3 + Kintex-7), demonstrating a complete loop from `get_critical_warnings` → XDC repair → `compare_with_last` verification → timing diagnosis → burning.
### Starting Point: Open Project, Check ERROR/CW Details Immediately
```
User: Open basys3_uart project and see why impl failed
AI: [start_session(mode="gui")]
[run_tcl("open_project .../basys3_uart.xpr")]
[get_critical_warnings(run_name="impl_1")]
!! Found 3 ERRORs !!
Diagnosis Overview: errors=3, critical_warnings=0, warnings=0
--- [ERROR][DRC BIVC-1] IO_STANDARD_MISMATCH (1) ---
First Appearance: Line 165
Sample Message: Bank IO standard Vcc: Conflicting Vcc voltages in bank 14...
Suggestion: Inconsistent IOSTANDARD in Bank (ports use different voltages, e.g., LVCMOS18 and LVCMOS33).
Fix: Explicitly specify IOSTANDARD for all ports in XDC, maintaining voltage consistency within the same Bank.
--- [ERROR][Vivado_Tcl 4-23] DRC_FAILED (1) ---
Suggestion: DRC failure caused Placer not to run.
Fix: Check previous [DRC xxx-N] to locate the root cause, common issues are BIVC-1/NSTD-1/UCIO-1.
--- [ERROR][Common 17-39] STAGE_ABORT (1) ---
Suggestion: Previous stage failure caused the subsequent stage to fail.
```
Diagnosis step 1 locks down the root cause: `BIVC-1` in `Bank 14` has voltage conflicts, and the other two ERRORs are chain reactions.
### Repair XDC + Re-synthesize
```
User: Follow suggestions to supplement IOSTANDARD in XDC and re-synthesize
AI: [xdc_auto_fix(board="basys3", dry_run=false)] # 0.3.3 One-click IOSTANDARD supplement
[run_synthesis]
[run_implementation]
```
### Verify Repair Effectiveness — `compare_with_last` Differential Analysis
```
User: Confirm if fixed
AI: [get_critical_warnings(run_name="impl_1", compare_with_last=True)]
Diagnosis Overview: errors=0, critical_warnings=0, warnings=3
=== CW Differential Report (compared to last snapshot) ===
Repair Effectiveness: 3 eliminated / 0 new / 0 remaining
[-] Eliminated (3):
• [DRC BIVC-1] IO_STANDARD_MISMATCH
• [Vivado_Tcl 4-23] DRC_FAILED
• [Common 17-39] STAGE_ABORT
Conclusion: Repair effective, all previous issues eliminated.
```
No need for manual comparison of two log files — differential analysis directly provides the conclusion: all 3 ERRORs eliminated, **repair effective**.
### Automatic Tcl Fix for Timing Violations (0.3.9 Highlight)
Switch to a large project with WNS violations (PCIe XDMA):
```
User: Timing didn't pass, tell me how to fix it
AI: [get_timing_report]
=== Timing Summary === Status: FAIL (Timing Violation)
Setup WNS = -9.247 ns TNS = -495735.094 ns
Failed Endpoint: 247261 / 247354
Hold WHS = +0.015 ns THS = 0.000 ns
--- Top 10 Violation Paths ---
[1] SETUP slack -9.247 ns [HIGH_FANOUT]
Start: .../xdma_0/.../tready_thrtl_reg/C
End: .../pcie_7x_i/pcie_block_i/CFGPMTURNOFFOKN
Delay Breakdown: logic 0.309 ns route 2.094 ns skew -6.845 ns levels=2
Suggestion: Routing delay (2.094 ns) is much larger than logic delay (0.309 ns), usually due to high fanout or cross-chip routing.
Run `report_high_fanout_nets -fanout_greater_than 1000` to locate,
then add `set_property MAX_FANOUT 50 [get_cells <...>]` to the main register,
or add `-fanout_limit 50` in the synthesis stage to let the tool automatically duplicate registers.
[2] SETUP slack -9.219 ns [HIGH_FANOUT]
...
```
No more "What to do when timing fails" - The tool directly categorizes based on modes (CDC / HIGH_FANOUT / LONG_COMBO / IO_UNREGISTERED / UNKNOWN) and provides specific Tcl commands.
### Pre-Programming Safety Check + Bitstream Generation
```
User: Ready to program the board
AI: [check_bitstream_readiness]
Conclusion: READY — route_design Complete / WNS +0.026 ns / CW=8 (GT_LOC are internal to IPs, ignorable)
[generate_bitstream] # Automatically intercept: if CW exists, block it; use force=True to skip
[program_device(bitstream_path="impl_1/top.bit")]
```
### Common Detour Tools
Other one-time query/comparison use cases:
```
# Compare two XCI files to find configuration drifts
compare_xci(file_a="golden.xci", file_b="suspect.xci")
# → PF0_DEVICE_ID: A=9024 | B=9038
# → LINK_SPEED: A=5.0_GT/s | B=8.0_GT/s
# Verify if GT pin actual placement matches XDC (supports -dict syntax)
verify_io_placement_tool
# → !!! CRITICAL mismatch !!! Port: pcie_7x_mgt_rtl_0_rxp[0]
# XDC: AA4 | Actual: M6
# Arbitrary Tcl — AI command builder
run_tcl("foreach p [get_ports] { puts \"$p: [get_property PACKAGE_PIN $p]\" }")
safe_tcl("set_property PACKAGE_PIN {0} [get_ports {1}]", args=["W5", "clk"])
```
## Architecture
```
AI Tool (Claude/Cursor/Codex) ──(stdio MCP)──▶ vivado-mcp
│
┌─────────────────────┼──────────────────────┐
│ │ │
▼ ▼ ▼
SubprocessSession GuiSession GuiSession
(mode="tcl") (mode="gui") (mode="attach")
│ │ │
vivado -mode tcl Popen + auto-spawn GUI Connect to existing Vivado GUI
(subprocess stdio) TCP:9999 / port=0 TCP:9999 / port=0
auto-alloc auto-alloc
```
**Core Protocol**:
- **Subprocess Mode**: `catch + UUID sentinel` (stdio framing, fixes the line order bug in 0.1.0)
- **GUI/Attach Mode**: TCP length-prefix framing (4-byte BE + UTF-8 payload)
- Commands are transmitted in hexadecimal encoding, preventing Tcl injection and supporting any characters
## CLI Reference
| Command | Description |
|---|---|
| `python -m vivado_mcp` | Launch MCP server (for AI tools) |
| `vivado-mcp serve` | Same as above |
| `vivado-mcp install [path] [--port 9999]` | Inject Vivado_init.tcl |
| `vivado-mcp uninstall [path]` | Remove from Vivado_init.tcl |
| `vivado-mcp version` | Display version |
## Development
```bash
git clone https://github.com/mapleleavessssssss-wq/vivado-mcp.git
cd vivado-mcp
pip install -e ".[dev]"
# Run tests (no Vivado required)
pytest
# Code check
ruff check src/ tests/
```
## Feedback and Bug Submission
### Submit Bug via Code Agent
Encountered an issue? Copy the following prompt into your agent (Claude Code, Cursor, Codex, etc.) to automatically collect environment information and create a standard issue:
<details>
<summary>Click to expand</summary>
````
I'm experiencing issues with vivado-mcp (https://github.com/mapleleavessssssss-wq/vivado-mcp).
Please help me submit a GitHub issue by following these steps:
1. Collect my environment information:
- Operating System: Run `[System.Environment]::OSVersion.VersionString`(PowerShell) or `systeminfo | findstr /B /C:"OS"`(cmd)
- Python Version: Run `python --version`
- vivado-mcp Version: Run `vivado-mcp version`(or `pip show vivado-mcp`)
- Vivado Version: Run `vivado -version`(if vivado is in PATH); otherwise, extract the project tag from my .xpr file
- Current Vivado Process: PowerShell run `Get-Process | Where-Object { $_.ProcessName -like "*vivado*" }`
- MCP Client Type (Claude Code / Cursor / Codex, etc.) and version
- Vivado mode used (`gui` / `tcl` / `attach`)
2. Ask me:
- Expected behavior
- Actual behavior
- Steps to reproduce (complete tool call sequence starting from `start_session`)
- Relevant tool output / error logs (preferably `get_critical_warnings` or `get_run_progress` output)
3. Use `gh issue create` to create an issue on GitHub with the following format:
- Title: Concise problem summary, prefix with `[bug]` / `[feature]` / `[docs]`
- Body includes: **Environment Information**, **Problem Description**, **Steps to Reproduce**, **Expected vs Actual Behavior**, **Relevant Logs**
- If it's a bug, add the `bug` label; if it involves a specific tool (e.g., `get_critical_warnings`), mention it in the title
Repository: mapleleavessssssss-wq/vivado-mcp
````
</details>
### Directly Create an Issue
You can also directly go to [GitHub Issues](https://github.com/mapleleavessssssss-wq/vivado-mcp/issues) to submit one — please include `vivado-mcp version`, Vivado version, and steps to reproduce.
## Documentation
- [CHANGELOG](CHANGELOG.md) — Version change history
- [Migration Guide 0.1 → 0.2](docs/MIGRATION_0.1_to_0.2.md) — Replacement for removed tools with `run_tcl`/`safe_tcl`
- [Audit Report](docs/AUDIT_REPORT.md) — Root cause analysis of 7 bugs in 0.1.0
- [IP Debugging Guide](docs/IP_DEBUG_GUIDE.md) — PCIe GT mapping debugging, XCI configuration comparison, etc.
- [PITFALLS](PITFALLS.md) — What MCP physically cannot do for you (need manual operation)
## License
[Apache License 2.0](LICENSE)
MCP Config
Below is the configuration for this MCP Server. You can copy it directly to Cursor or other MCP clients.
mcp.json
Connection Info
You Might Also Like
everything-claude-code
Complete Claude Code configuration collection - agents, skills, hooks,...
markitdown
MarkItDown-MCP is a lightweight server for converting URIs to Markdown.
cc-switch
All-in-One Assistant for Claude Code, Codex & Gemini CLI across platforms.
servers
Model Context Protocol Servers
servers
Model Context Protocol Servers
Time
A Model Context Protocol server for time and timezone conversions.