- Add detailed docstrings and inline comments to all source files - Create README with installation, usage, and Claude recreation guide - Add pyproject.toml for pip installation - Add MIT LICENSE file - Document architecture, design patterns, and MCP server structure Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
265 lines
8.6 KiB
Markdown
265 lines
8.6 KiB
Markdown
# Vivado MCP Server
|
|
|
|
A Model Context Protocol (MCP) server that enables AI assistants like Claude to directly interact with AMD/Xilinx Vivado FPGA development tools.
|
|
|
|
## Features
|
|
|
|
- **Session Management**: Start/stop persistent Vivado TCL sessions (avoids 30s startup per command)
|
|
- **Project Management**: Open/close Vivado projects (.xpr files)
|
|
- **Design Flow**: Run synthesis, implementation, and bitstream generation
|
|
- **Reports & Analysis**: Get timing summaries, utilization reports, and design analysis
|
|
- **Design Queries**: Explore hierarchy, ports, nets, and cells
|
|
- **Simulation**: Control Vivado's integrated simulator (xsim)
|
|
- **Raw TCL**: Execute arbitrary Vivado TCL commands for advanced operations
|
|
|
|
## Requirements
|
|
|
|
- Python 3.10+
|
|
- AMD/Xilinx Vivado installed (tested with 2023.2+)
|
|
- Vivado must be in your PATH, or specify the full path when starting a session
|
|
|
|
## Installation
|
|
|
|
### From GitHub
|
|
|
|
```bash
|
|
git clone https://github.com/coreyhahn/vivado_mcp.git
|
|
cd vivado_mcp
|
|
pip install -e .
|
|
```
|
|
|
|
### Configure Claude Code
|
|
|
|
Add to your Claude Code MCP configuration (`~/.claude/claude_desktop_config.json` or project-level `.mcp.json`):
|
|
|
|
```json
|
|
{
|
|
"mcpServers": {
|
|
"vivado": {
|
|
"command": "vivado-mcp"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
Or if you want to specify the Python interpreter:
|
|
|
|
```json
|
|
{
|
|
"mcpServers": {
|
|
"vivado": {
|
|
"command": "python",
|
|
"args": ["-m", "vivado_mcp"]
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## Usage
|
|
|
|
Once configured, Claude can interact with Vivado through natural language. Example workflow:
|
|
|
|
1. **Start Vivado session**: "Start a Vivado session"
|
|
2. **Open project**: "Open my project at /path/to/project.xpr"
|
|
3. **Run synthesis**: "Synthesize the design"
|
|
4. **Check timing**: "What's the timing summary? Is timing met?"
|
|
5. **Check utilization**: "Show me the resource utilization"
|
|
6. **Close session**: "Stop the Vivado session"
|
|
|
|
## Available Tools
|
|
|
|
### Session Management
|
|
- `start_session` - Start a persistent Vivado TCL session
|
|
- `stop_session` - Stop the Vivado session
|
|
- `session_status` - Get session statistics
|
|
|
|
### Project Management
|
|
- `open_project` - Open a Vivado project (.xpr)
|
|
- `close_project` - Close the current project
|
|
- `get_project_info` - Get project information (part, directory, etc.)
|
|
|
|
### Design Flow
|
|
- `run_synthesis` - Run synthesis
|
|
- `run_implementation` - Run place and route
|
|
- `generate_bitstream` - Generate bitstream
|
|
|
|
### Reports & Analysis
|
|
- `get_timing_summary` - Get timing summary (WNS, TNS, WHS, THS)
|
|
- `get_timing_paths` - Get detailed timing paths for failing/critical paths
|
|
- `get_utilization` - Get resource utilization (LUTs, FFs, BRAMs, DSPs)
|
|
- `get_clocks` - Get clock information
|
|
- `get_messages` - Get synthesis/implementation messages
|
|
|
|
### Design Queries
|
|
- `get_design_hierarchy` - Get module/instance hierarchy
|
|
- `get_ports` - Get top-level ports
|
|
- `get_nets` - Search for nets
|
|
- `get_cells` - Search for cells/instances
|
|
|
|
### Simulation
|
|
- `launch_simulation` - Launch behavioral/post-synth/post-impl simulation
|
|
- `run_simulation` - Run simulation for specified time
|
|
- `restart_simulation` - Restart from time 0
|
|
- `close_simulation` - Close the simulator
|
|
- `get_simulation_time` - Get current simulation time
|
|
- `get_signal_value` - Get a signal's current value
|
|
- `get_signal_values` - Get multiple signal values by pattern
|
|
- `add_signals_to_wave` - Add signals to waveform viewer
|
|
- `set_simulation_top` - Set the testbench module
|
|
- `get_simulation_objects` - List signals in a scope
|
|
- `get_scopes` - List hierarchy scopes
|
|
- `step_simulation` - Step simulation
|
|
- `add_breakpoint` - Add signal breakpoint
|
|
- `remove_breakpoints` - Remove all breakpoints
|
|
|
|
### Advanced
|
|
- `run_tcl` - Execute raw TCL commands
|
|
- `generate_full_report` - Generate full reports to file
|
|
- `read_report_section` - Read portions of large reports
|
|
- `request_feature` - Request new features
|
|
- `list_feature_requests` - List submitted requests
|
|
|
|
## Architecture
|
|
|
|
```
|
|
┌─────────────────┐ MCP Protocol ┌─────────────────┐
|
|
│ Claude Code │◄────(JSON-RPC)────────►│ Vivado MCP │
|
|
│ (AI Client) │ over stdio │ Server │
|
|
└─────────────────┘ └────────┬────────┘
|
|
│
|
|
│ pexpect
|
|
│ (TCL commands)
|
|
▼
|
|
┌─────────────────┐
|
|
│ Vivado Process │
|
|
│ (TCL mode) │
|
|
└─────────────────┘
|
|
```
|
|
|
|
The server maintains a persistent Vivado process in TCL mode. Commands are sent via pexpect and output is captured by waiting for the Vivado prompt. This avoids the ~30 second startup overhead that would occur if Vivado were launched for each command.
|
|
|
|
## Recreating This MCP Server with Claude
|
|
|
|
This MCP server was created entirely through conversation with Claude. Here's how you can create similar MCP servers:
|
|
|
|
### 1. Start with a Clear Goal
|
|
|
|
Tell Claude what you want to build:
|
|
> "I want to create an MCP server that lets you control Vivado FPGA tools. You should be able to start Vivado, open projects, run synthesis, check timing, etc."
|
|
|
|
### 2. Describe the Architecture
|
|
|
|
Explain the key technical challenges:
|
|
> "Vivado takes 30 seconds to start, so we need a persistent session. Vivado has a TCL interface we can use. We need to parse Vivado's text output into structured data."
|
|
|
|
### 3. Iterate on Tools
|
|
|
|
Start with basic tools and add more:
|
|
1. Session management (start/stop)
|
|
2. Project management
|
|
3. Design flow commands
|
|
4. Reports and queries
|
|
5. Simulation control
|
|
|
|
### 4. Key Design Patterns Used
|
|
|
|
**Singleton Session**: Only one Vivado process runs at a time
|
|
```python
|
|
_session: Optional[VivadoSession] = None
|
|
|
|
def get_session() -> VivadoSession:
|
|
global _session
|
|
if _session is None:
|
|
_session = VivadoSession()
|
|
return _session
|
|
```
|
|
|
|
**pexpect for Process Management**: Keeps Vivado alive between commands
|
|
```python
|
|
self.child = pexpect.spawn(
|
|
f'{self.vivado_path} -mode tcl -nojournal -nolog',
|
|
encoding='utf-8',
|
|
timeout=self.timeout
|
|
)
|
|
self.child.expect('Vivado%', timeout=10) # Wait for prompt
|
|
```
|
|
|
|
**Output Parsing**: Convert text reports to structured JSON
|
|
```python
|
|
def parse_timing_summary(output: str) -> dict:
|
|
wns_match = re.search(r"WNS\(ns\)\s*:\s*([-\d.]+)", output)
|
|
if wns_match:
|
|
result["wns"] = float(wns_match.group(1))
|
|
```
|
|
|
|
**Response Truncation**: Handle large outputs gracefully
|
|
```python
|
|
def truncate_response(content: str, max_chars: int) -> dict:
|
|
if len(content) > max_chars:
|
|
return {"content": content[:max_chars], "truncated": True}
|
|
```
|
|
|
|
### 5. MCP Server Structure
|
|
|
|
Every MCP server needs:
|
|
|
|
```python
|
|
from mcp.server import Server
|
|
from mcp.server.stdio import stdio_server
|
|
from mcp.types import Tool, TextContent
|
|
|
|
server = Server("your-server-name")
|
|
|
|
@server.list_tools()
|
|
async def list_tools() -> list[Tool]:
|
|
return [Tool(name="...", description="...", inputSchema={...})]
|
|
|
|
@server.call_tool()
|
|
async def call_tool(name: str, arguments: dict) -> list[TextContent]:
|
|
# Handle tool calls
|
|
return [TextContent(type="text", text=json.dumps(result))]
|
|
|
|
async def main():
|
|
async with stdio_server() as (read_stream, write_stream):
|
|
await server.run(read_stream, write_stream,
|
|
server.create_initialization_options())
|
|
```
|
|
|
|
### 6. Prompt for Creating Your Own MCP Server
|
|
|
|
Use this prompt template with Claude:
|
|
|
|
```
|
|
I want to create an MCP server for [YOUR TOOL].
|
|
|
|
Background:
|
|
- [Tool] is a [description] that [what it does]
|
|
- It has a [CLI/API/etc] interface that accepts [commands/requests]
|
|
- Key operations I want to support: [list operations]
|
|
|
|
Technical considerations:
|
|
- [Startup time, persistent state, output formats, etc.]
|
|
|
|
Please help me create an MCP server with:
|
|
1. Session/connection management
|
|
2. Core operations as tools
|
|
3. Proper error handling
|
|
4. Structured JSON responses
|
|
5. Comprehensive code comments
|
|
|
|
Start with the basic structure and we'll iterate from there.
|
|
```
|
|
|
|
## Contributing
|
|
|
|
Contributions welcome! Please feel free to submit issues and pull requests.
|
|
|
|
## License
|
|
|
|
MIT License - see LICENSE file for details.
|
|
|
|
## Acknowledgments
|
|
|
|
- Created with [Claude](https://claude.ai) (Anthropic)
|
|
- Uses the [Model Context Protocol](https://modelcontextprotocol.io) specification
|
|
- Integrates with [AMD/Xilinx Vivado](https://www.xilinx.com/products/design-tools/vivado.html)
|