Metadata-Version: 2.4
Name: renderdoc-mcp
Version: 0.2.1
Summary: MCP server for RenderDoc graphics debugger - enables AI-assisted frame capture analysis
Requires-Python: ==3.13.*
Requires-Dist: mcp[cli]>=1.0.0
Description-Content-Type: text/markdown

# renderdoc-mcp

<div align="center">

<h2>⚠️ Disclaimer</h2>

$\Large\color{#ff69b4}{\textsf{This is a personal }}$ $\Large\color{#ff69b4}{\mathtt{✨ vibe\text{-}coding ✨}}$ $\Large\color{#ff69b4}{\textsf{project —}}$
$\Large\color{#ff69b4}{\textsf{built for fun, not for production use.}}$

$\small\color{gray}{\textsf{I have no idea why this repo has so many stars...}}$

<img src="assets/crying.gif" width="64" />

</div>

MCP server for [RenderDoc](https://renderdoc.org/) — let AI assistants analyze GPU frame captures (`.rdc` files) for graphics debugging and performance analysis.

Built on the [Model Context Protocol](https://modelcontextprotocol.io/), works with Claude Desktop, Kiro, and any MCP-compatible client.

## Features

- **42 tools** covering the full RenderDoc analysis workflow
- **10 high-level tools** for one-call analysis (draw call state, frame overview, diff, batch export, pixel region sampling, etc.)
- **3 built-in prompts** for guided debugging
- **Human-readable output** — blend modes, depth functions, topology shown as names not numbers
- **GPU quirk detection** — auto-identifies Adreno/Mali/PowerVR/Apple-specific pitfalls from driver name
- **Headless** — no GUI needed, runs entirely via RenderDoc's Python replay API
- **Bundled dependencies** — includes all required RenderDoc DLLs and Python bindings
- Supports D3D11, D3D12, OpenGL, Vulkan, OpenGL ES captures

> **Note**: Currently Windows-only. The bundled `renderdoc.pyd` and DLLs are Windows x64 binaries. Linux/macOS support requires building from source with platform-specific bindings.

## Quick Start

### Installation

```bash
# Navigate to project directory
cd E:\MCP\renderdoc-mcp-master

# Install using uv
uv pip install --python python313\python.exe -e .

# Verify installation
python313\python.exe -c "import renderdoc_mcp; print('Installation successful!')"
```

### Configuration

Add to your MCP client configuration:

**Kiro** (`~/.kiro/settings/mcp.json`):
```json
{
  "mcpServers": {
    "renderdoc": {
      "command": "E:\\MCP\\renderdoc-mcp-master\\python313\\python.exe",
      "args": ["-m", "renderdoc_mcp"]
    }
  }
}
```

**Claude Desktop** (`claude_desktop_config.json`):
```json
{
  "mcpServers": {
    "renderdoc": {
      "command": "E:\\MCP\\renderdoc-mcp-master\\python313\\python.exe",
      "args": ["-m", "renderdoc_mcp"]
    }
  }
}
```

> **Note**: Replace `E:\\MCP\\renderdoc-mcp-master` with your actual project path.

Restart your MCP client and you're ready to analyze `.rdc` files!

### How It Works

- **Bundled Python 3.13**: The project includes a complete Python 3.13 environment in `python313/`
- **No system Python needed**: Everything runs in the bundled environment
- **All dependencies included**: RenderDoc DLLs are in `lib/`, Python packages in `python313/Lib/site-packages/`
- **Simple installation**: One `uv pip install` command installs all dependencies

## Usage Examples

Once configured, just talk to your AI assistant:

> "Open `frame.rdc` and show me what's happening in the frame"

> "Find the draw call that renders the character model and check its pipeline state"

> "Why is my shadow map rendering black? Check the depth pass"

> "Analyze performance — are there any redundant draw calls?"

### Typical Tool Flow

```
open_capture("frame.rdc")                     # Load the capture
├── get_capture_info()                         # API, GPU, known_gpu_quirks
├── get_frame_overview()                       # Frame-level stats and render passes
├── get_draw_call_state(142)                   # Complete draw call state in one call
├── diff_draw_calls(140, 142)                  # Compare two draw calls (with implications)
├── export_draw_textures(142, "./tex/")        # Batch export all bound textures
├── save_render_target(142, "./rt.png")        # Save render target snapshot
├── analyze_render_passes()                    # Auto-detect render pass boundaries
├── find_draws(blend=True, min_vertices=1000)  # Search by rendering state
├── sample_pixel_region(rt_id, 0,0,512,512)   # Scan RT region for NaN/Inf/negatives
├── pixel_history(id, 512, 384)               # Debug a specific pixel
├── export_mesh(142, "./mesh.obj")             # Export mesh as OBJ
└── close_capture()                            # Clean up
```

For performance and diagnostic analysis:

```
get_pass_timing(granularity="pass")      # Find most expensive render passes
analyze_overdraw()                        # Fill-rate pressure estimate
analyze_bandwidth()                       # Memory bandwidth estimate
analyze_state_changes()                   # Batching opportunities
diagnose_negative_values()               # Find NaN/Inf/negative color values (爆闪)
diagnose_precision_issues()              # R11G11B10, D16, SRGB mismatches
diagnose_reflection_mismatch()           # Reflection artifact diagnosis
diagnose_mobile_risks()                  # Comprehensive mobile GPU risk check
```

For lower-level inspection, all granular tools remain available:

```
set_event(142)                                    # Navigate to a draw call
├── get_pipeline_state()                          # Inspect rasterizer/blend/depth
├── get_shader_bindings("pixel")                  # Check what textures/buffers are bound
├── get_cbuffer_contents("pixel", 0, filter="ibl") # Read shader constants (filterable)
├── disassemble_shader("pixel", search="SampleSH") # Shader code with context search
└── save_texture(id, "rt.png")                    # Export a specific texture
```

## Tools

### Session Management (4)

| Tool | Description |
|------|-------------|
| `open_capture` | Open a `.rdc` file (auto-closes previous) |
| `close_capture` | Close current capture and free resources |
| `get_capture_info` | Capture metadata: API, action count, resolution, **known_gpu_quirks** (Adreno/Mali/PowerVR/Apple) |
| `get_frame_overview` | **Frame-level statistics**: action counts by type, texture/buffer memory, render targets, resolution |

### Event Navigation (5)

| Tool | Description |
|------|-------------|
| `list_actions` | List the draw call / action tree — supports `filter` (name substring) and `event_type` (draw/clear/copy…) |
| `get_action` | Full detail for a single action |
| `set_event` | Navigate to an event (**required** before pipeline queries) |
| `search_actions` | Search by name pattern and/or action flags |
| `find_draws` | **Search draw calls by rendering state**: blend, min vertices, texture/shader/RT binding |

### Pipeline Inspection (4)

| Tool | Description |
|------|-------------|
| `get_pipeline_state` | Full state: topology, viewports, rasterizer, blend, depth, stencil (human-readable enums) |
| `get_shader_bindings` | Constant buffers, SRVs, UAVs, samplers for a shader stage |
| `get_vertex_inputs` | Vertex attributes, vertex/index buffer bindings |
| `get_draw_call_state` | **One-call draw analysis**: action info, blend formula, depth, stencil, rasterizer, textures with sizes, RTs, shaders |

### Resource Analysis (4)

| Tool | Description |
|------|-------------|
| `list_textures` | All textures (filterable by format, min width) |
| `list_buffers` | All buffers (filterable by min size) |
| `list_resources` | All named resources (filterable by type, name pattern) |
| `get_resource_usage` | Which events read/write a resource |

### Data Extraction (8)

| Tool | Description |
|------|-------------|
| `save_texture` | Export to PNG, JPG, BMP, TGA, HDR, EXR, or DDS |
| `get_buffer_data` | Read buffer bytes (hex dump or float32 array) |
| `pick_pixel` | RGBA value at a coordinate |
| `get_texture_stats` | Per-channel min/max/avg with **anomaly detection** (NaN/Inf/negative); supports `all_slices` for cubemaps |
| `read_texture_pixels` | Read a rectangular region of pixels (up to 64×64) with per-pixel anomaly flags |
| `export_draw_textures` | **Batch export** all textures bound to a draw call (auto-names, skips placeholders) |
| `save_render_target` | **Save RT snapshot** at an event (color + optional depth) |
| `export_mesh` | **Export mesh as OBJ** with positions, normals, UVs from post-VS data |

### Shader Analysis (3)

| Tool | Description |
|------|-------------|
| `disassemble_shader` | Shader disassembly with **auto fallback chain**; supports `search` (keyword + context) and `line_range` |
| `get_shader_reflection` | Input/output signatures, resource binding layout |
| `get_cbuffer_contents` | Actual constant buffer variable values; supports `filter` for variable name substring |

### Advanced (6)

| Tool | Description |
|------|-------------|
| `pixel_history` | Full per-pixel modification history across all events |
| `get_post_vs_data` | Post-transform vertex data (VS out / GS out) |
| `diff_draw_calls` | **Compare two draw calls** — shows state differences with human-readable implications |
| `analyze_render_passes` | **Auto-detect render pass boundaries** by Clear/RT switches, summarize each pass |
| `sample_pixel_region` | **Uniform-grid scan** of an RT region — detects NaN/Inf/negative/overexposed hotspots |
| `debug_shader_at_pixel` | **Per-pixel shader debug** — returns variable trace or pixel value + shader info as fallback |

### Performance Analysis (4)

| Tool | Description |
|------|-------------|
| `get_pass_timing` | Most expensive render passes — uses GPU counters if available, falls back to triangle-count heuristic |
| `analyze_overdraw` | Overdraw estimate per render target group |
| `analyze_bandwidth` | Write/read bandwidth estimate per render target |
| `analyze_state_changes` | Finds redundant state-change patterns and batching opportunities |

### Diagnostics (4)

| Tool | Description |
|------|-------------|
| `diagnose_negative_values` | Scans all float RTs for negative/NaN/Inf — finds first event introducing them, detects TAA accumulation |
| `diagnose_precision_issues` | Checks R11G11B10 sign-bit loss, shallow depth buffers, SRGB/linear mismatches |
| `diagnose_reflection_mismatch` | Compares reflection passes against main scene draws — finds shader/blend/format causes |
| `diagnose_mobile_risks` | Comprehensive check across precision / performance / compatibility / GPU-specific risk categories |

## Prompts

Built-in prompt templates to guide AI through common workflows:

| Prompt | Description |
|--------|-------------|
| `debug_draw_call` | Deep-dive a single draw call: pipeline → shaders → cbuffers → outputs |
| `find_rendering_issue` | Systematic diagnosis from a problem description |
| `analyze_performance` | Frame-wide perf analysis: pass timing, overdraw, bandwidth, state changes |

## How It Works

```
AI Assistant ←—MCP—→ renderdoc-mcp server ←—Python API—→ renderdoc.pyd ←→ GPU replay
```

The server uses RenderDoc's headless replay API (`renderdoc.pyd`) to:
1. Open `.rdc` capture files without the GUI
2. Replay frames and query pipeline state at any event
3. Extract textures, buffers, shader data, and pixel history
4. Return structured JSON for the AI to reason about

All required RenderDoc DLLs and the Python binding (`renderdoc.pyd`) are bundled with the package, so no separate RenderDoc installation is needed.

## Troubleshooting

### Python Version Issues

The bundled `renderdoc.pyd` requires Python 3.13. Check your version:

```bash
python --version
```

If not 3.13, install Python 3.13 or create a virtual environment with it.

### Module Import Errors

If you see `ImportError: DLL load failed`:

1. Ensure the `lib/` directory exists in the project
2. Verify you're running from the correct directory (use `cwd` in config)
3. Check that your antivirus isn't blocking the DLLs

### Server Won't Start

Check the MCP client logs. Common issues:
- Wrong `cwd` path in configuration
- Package not installed (`pip install -e .`)
- Python version not 3.13

## Development

### Local Development Setup

```bash
# Clone the repository
git clone https://github.com/Linkingooo/renderdoc-mcp.git
cd renderdoc-mcp

# Install in editable mode with Python 3.13
uv pip install --python 3.13 -e .

# Or use regular pip with Python 3.13
pip install -e .
```

### Testing

```bash
# Run tests (no RenderDoc needed — uses mocks)
python -m pytest tests/ -v
```

### Project Structure

```
src/renderdoc_mcp/
├── server.py                 # FastMCP server, 3 prompt definitions
├── session.py                # Capture lifecycle, resource/texture caches (singleton)
├── util.py                   # Serialization, enum maps, blend formula, module loader
└── tools/
    ├── session_tools.py      # open/close/info (GPU quirks) + get_frame_overview
    ├── event_tools.py        # list/get/set/search actions + find_draws
    ├── pipeline_tools.py     # pipeline state, shader bindings, vertex inputs + get_draw_call_state
    ├── resource_tools.py     # texture/buffer/resource enumeration
    ├── data_tools.py         # save/read/pick/stats + read_texture_pixels + export_draw_textures, save_render_target, export_mesh
    ├── shader_tools.py       # disassembly (fallback chain, search), reflection, cbuffer contents (filter)
    ├── advanced_tools.py     # pixel history, post-VS data + diff_draw_calls (implications), analyze_render_passes, sample_pixel_region, debug_shader_at_pixel
    ├── performance_tools.py  # get_pass_timing, analyze_overdraw, analyze_bandwidth, analyze_state_changes
    └── diagnostic_tools.py  # diagnose_negative_values, diagnose_precision_issues, diagnose_reflection_mismatch, diagnose_mobile_risks

lib/                          # Bundled RenderDoc dependencies (Windows)
├── renderdoc.dll             # Core RenderDoc library
├── renderdoc.pyd             # Python 3.13 binding
└── *.dll                     # Qt5 and other dependencies
```

### Building for Distribution

The package includes all necessary RenderDoc DLLs in the `lib/` directory. When building:

```bash
# Build wheel
python -m build

# The wheel will include lib/ directory with all DLLs
```

## License

MIT
