# BlenderMCP Architecture & BDD Review – 2025-11-06 21:37 UTC
## 1. Summary
- **CRITICAL: Package naming mismatch** – `pyproject.toml` references `blender_mcp` but source is in `src/` with relative imports expecting `blender_mcp` parent package
- **CRITICAL: Duplicate remeshing implementations** – Both `tools/remeshing.py` and `retopo_tools/remesh.py` exist with overlapping functionality
- **MAJOR: Module organization ambiguity** – Unclear distinction between `tools/` and `retopo_tools/` directories
- **POSITIVE: Clean dependency boundaries** – No circular imports or forbidden cross-module dependencies detected
**Mindful Verdict:** The codebase exhibits strong architectural foundations with excellent module separation, but suffers from a critical packaging configuration issue and structural duplication that undermines the otherwise clean design.
## 2. Repository Snapshot
### Current Structure
```
D:\repos\blender-mcp/
├── addon.py # Blender addon (socket server) ✓
├── main.py # Local dev entry point ✓
├── src/
│ ├── __init__.py # Package init exposing BlenderConnection ✓
│ ├── server.py # MCP server (763 lines, thin wrappers) ✓
│ ├── tools/ # Original tool modules ✓
│ │ ├── __init__.py
│ │ ├── mesh_analysis.py
│ │ ├── remeshing.py # ⚠ DUPLICATE with retopo_tools/remesh.py
│ │ ├── viewport.py
│ │ ├── shading.py
│ │ ├── scene.py
│ │ ├── modifiers.py
│ │ └── integrations/
│ │ ├── polyhaven.py
│ │ ├── sketchfab.py
│ │ └── hyper3d.py
│ ├── prompts/ # Guided workflows ✓
│ │ ├── retopo.py
│ │ └── asset_creation.py
│ └── retopo_tools/ # ⚠ DUPLICATE retopo implementations
│ ├── modifiers.py # ⚠ OVERLAPS with tools/modifiers.py
│ ├── remesh.py # ⚠ DUPLICATE remeshing logic
│ ├── mesh_ops.py
│ ├── mesh_analysis.py # ⚠ DUPLICATE with tools/mesh_analysis.py
│ ├── selection.py
│ ├── snapping.py
│ ├── camera.py
│ ├── baking.py
│ └── io.py
├── features/ # BDD specifications (15 files) ✓
├── tests/ # Test directory (present but unexamined)
└── pyproject.toml # ⚠ Package config mismatch
```
### Divergence from Documented Layout
**Expected (per ARCHITECTURE.md):**
```
src/
server.py
tools/
mesh_analysis.py
remeshing.py
viewport.py
shading.py
scene.py
integrations/
prompts/
retopo.py
asset_creation.py
```
**Actual:**
- Additional `retopo_tools/` directory not documented in ARCHITECTURE.md
- Duplicate implementations across `tools/` and `retopo_tools/`
- Old package structure deleted: `src/blender_mcp/__init__.py` and `src/blender_mcp/server.py`
## 3. Architecture & Structure Compliance
### 3.1. Server vs Modules: ✅ EXCELLENT
**File:** `D:\repos\blender-mcp\src\server.py` (1316 lines)
**Findings:**
- server.py correctly contains ONLY infrastructure and thin wrappers
- Lines 1-242: Infrastructure (BlenderConnection, lifespan management, connection pooling)
- Lines 244-276: Imports from tool modules (clean, organized)
- Lines 278-1293: Thin @mcp.tool() and @mcp.prompt() wrappers (one-line delegation)
- Lines 1309-1316: Entry point
**Compliance:** PERFECT adherence to architectural rule "server.py contains only infrastructure and thin wrappers"
**Evidence:**
```python
# Example wrapper (lines 318-321):
@mcp.tool()
def get_scene_info(ctx: Context) -> str:
"""Get detailed information about the current Blender scene"""
return get_scene_info_impl(ctx, get_blender_connection())
```
### 3.2. Modules & Dependencies: ✅ EXCELLENT (with critical packaging issue)
**Dependency Analysis:**
✅ **No forbidden imports detected:**
- `tools/*` modules do NOT import `prompts/*` or `server`
- `prompts/*` modules do NOT import `tools/*` or `server`
- MCP server code does NOT import `addon.py`
- All cross-module imports are unidirectional: `server.py` → `tools`, `prompts`, `retopo_tools`
✅ **Clean module boundaries:**
- `tools/mesh_analysis.py`: Only imports `mcp.server.fastmcp.Context` and `logging`
- `tools/remeshing.py`: Only imports `Context` and `logging`
- `prompts/retopo.py`: Self-contained, no cross-module imports
- `prompts/asset_creation.py`: Self-contained
**Critical Issues:**
❌ **CRITICAL: Package naming mismatch (Line: pyproject.toml:28)**
```toml
[tool.setuptools]
package-dir = {"blender_mcp" = "src"}
```
- This configuration expects the package to be named `blender_mcp`
- But `src/server.py` uses relative imports: `from .tools.mesh_analysis import ...`
- These relative imports expect a parent package named `blender_mcp`
- Currently `src/__init__.py` exists at root, creating ambiguity
- **Impact:** Package cannot be imported correctly without `main.py` workaround
**Test Evidence:**
```bash
$ python -c "import sys; sys.path.insert(0, 'src'); from server import mcp"
ImportError: attempted relative import with no known parent package
```
❌ **MAJOR: Duplicate module hierarchy**
Two parallel implementations exist:
1. `src/tools/remeshing.py` (original, documented in ARCHITECTURE.md)
2. `src/retopo_tools/remesh.py` (extended version with additional parameters)
Both are imported in `server.py`:
- Line 268: `from .tools.remeshing import voxel_remesh as voxel_remesh_impl`
- Line 298: `from .retopo_tools.remesh import remesh_voxel as remesh_voxel_impl`
**Registered wrappers:**
- Line 608-623: `@mcp.tool() def voxel_remesh(...)` → calls `voxel_remesh_impl` (from tools.remeshing)
- Line 1100-1118: `@mcp.tool() def remesh_voxel(...)` → calls `remesh_voxel_impl` (from retopo_tools.remesh)
**Result:** TWO different voxel remesh tools registered with different names and signatures!
Similar duplication exists for:
- `tools/mesh_analysis.py` vs `retopo_tools/mesh_analysis.py`
- `tools/modifiers.py` vs `retopo_tools/modifiers.py`
- `quadriflow_remesh` (tools.remeshing) vs `quadriflow_remesh` (retopo_tools.remesh)
### 3.3. Signatures & Docstrings: ✅ GOOD
**Findings:**
- All public tool functions follow the required signature: `def tool_name(ctx: Context, blender_connection, param1, param2=default) -> str`
- All prompt functions follow: `def prompt_name() -> str`
- Comprehensive docstrings present with Parameters and Returns sections
- Consistent naming: `snake_case_verb_noun()`
**Sample Audit:**
- `tools/mesh_analysis.py:mesh_stats()` – ✅ Proper signature, complete docstring
- `tools/remeshing.py:voxel_remesh()` – ✅ Proper signature, complete docstring
- `prompts/retopo.py:retopo_pipeline()` – ✅ Returns str, complete docstring
- `retopo_tools/modifiers.py:add_mirror_modifier()` – ✅ Proper signature, complete docstring
**Minor Issue:**
- Some docstrings use informal phrasing (e.g., "Good for...") which is acceptable but could be more technical
### 3.4. Error Handling & Logging: ✅ GOOD
**Findings:**
- All tool implementations use try/except blocks consistently
- Logger is initialized correctly: `logger = logging.getLogger("BlenderMCPServer")`
- Error messages are user-friendly with context
- Pattern is consistent across all modules
**Sample Audit:**
```python
# tools/mesh_analysis.py:69-72
except Exception as e:
logger.error(f"Error getting mesh stats: {str(e)}")
return f"Error getting mesh stats: {str(e)}"
```
**Best Practice Observed:**
- Server-side errors are caught and formatted as user-readable strings
- `blender_connection.send_command()` checks for `"error"` in result
- Connection errors in `server.py` include reconnection logic (lines 145-165)
### 3.5. Naming Conventions: ✅ EXCELLENT
**Audit:**
- Modules: `mesh_analysis.py`, `remeshing.py`, `viewport.py` (all `snake_case.py`) ✅
- Functions: `mesh_stats()`, `voxel_remesh()`, `mark_seams_by_angle()` (all `snake_case_verb_noun`) ✅
- Constants: `DEFAULT_HOST`, `DEFAULT_PORT`, `RODIN_FREE_TRIAL_KEY` (all `UPPER_CASE`) ✅
- Private helpers: `_server_loop()` in `addon.py`, `_blender_connection` global (underscore prefix) ✅
## 4. BDD Scenario Coverage & Validation
### Feature Files Inventory (15 total)
| Feature File | Key Scenarios | Implementing Tools | Status |
|--------------|---------------|-------------------|--------|
| `01_mcp_contract.feature` | Tool/resource/prompt discovery | All tools registered via @mcp.tool() | ✅ Implemented |
| `02_mesh_analysis.feature` | mesh_stats, detect_topology_issues | `tools/mesh_analysis.py` | ✅ Implemented |
| `03_voxel_remesh.feature` | Voxel-based remeshing | `tools/remeshing.py:voxel_remesh` + `retopo_tools/remesh.py:remesh_voxel` | ⚠ DUPLICATE |
| `04_quadriflow_remesh.feature` | Quad-dominant remeshing | `tools/remeshing.py:quadriflow_remesh` + `retopo_tools/remesh.py:quadriflow_remesh` | ⚠ DUPLICATE |
| `05_decimation.feature` | Polygon reduction | `tools/remeshing.py:decimate` | ✅ Implemented |
| `06_shrinkwrap.feature` | Surface projection | `tools/remeshing.py:shrinkwrap_reproject` | ✅ Implemented |
| `07_seams_shading.feature` | UV seams, sharp edges | `tools/shading.py` | ✅ Implemented |
| `08_viewport_controls.feature` | View projection, alignment | `tools/viewport.py` | ✅ Implemented |
| `09_baking.feature` | Normal/AO baking | `retopo_tools/baking.py` | ✅ Implemented |
| `10_import_export.feature` | Asset import/export | `retopo_tools/io.py` | ✅ Implemented |
| `11_viewport_resource.feature` | Viewport screenshot resource | `tools/scene.py:get_viewport_screenshot` | ✅ Implemented |
| `12_safety.feature` | execute_blender_code warnings | `tools/scene.py:execute_blender_code` | ⚠ Needs verification |
| `13_model_switching.feature` | Object selection/activation | Likely `tools/scene.py` | ⚠ Needs verification |
| `14_camera_ortho.feature` | Camera controls | `retopo_tools/camera.py` | ✅ Implemented |
| `15_batch_ortho_renders.feature` | Batch rendering | Unknown | ⚠ Needs verification |
### Tool Registration Audit
**Total tools registered in server.py:** 50+ (exact count requires full enumeration)
**Sample verification:**
- Line 575: `@mcp.tool() def mesh_stats(...)` ✅ Registered
- Line 608: `@mcp.tool() def voxel_remesh(...)` ✅ Registered
- Line 626: `@mcp.tool() def quadriflow_remesh(...)` ✅ Registered
- Line 1100: `@mcp.tool() def remesh_voxel(...)` ⚠ DUPLICATE of voxel_remesh
**Prompts registered:**
- Line 1299: `@mcp.prompt() def retopo_pipeline()` ✅ Registered
- Line 1304: `@mcp.prompt() def asset_creation_strategy()` ✅ Registered
### Alignment Issues
❌ **CRITICAL: Duplicate tool registration**
- `voxel_remesh` (line 608) vs `remesh_voxel` (line 1100)
- `quadriflow_remesh` appears twice with different implementations
- This violates the BDD spec expectation of unique, discoverable tools
⚠ **MAJOR: retopo_tools not documented**
- ARCHITECTURE.md does not mention `retopo_tools/` directory
- BDD features assume tools are in `tools/` per architecture doc
- Current implementation splits across both, creating confusion
## 5. Recommendations (Prioritized)
### CRITICAL (Fix Immediately)
**1. Fix Package Configuration [SEVERITY: CRITICAL]**
- **Issue:** `pyproject.toml` expects `blender_mcp` package but imports use relative paths without proper parent
- **Impact:** Package cannot be imported correctly, breaks installation
- **Fix:** Either:
- Option A: Move `src/*` to `src/blender_mcp/*` to match pyproject.toml
- Option B: Update pyproject.toml to use `packages = find_packages(where="src")` and proper package discovery
- **Files affected:** `pyproject.toml`, potentially all import statements
- **Location:** `D:\repos\blender-mcp\pyproject.toml:28`
**2. Resolve Duplicate Remeshing Implementations [SEVERITY: CRITICAL]**
- **Issue:** Two parallel implementations of voxel/quadriflow remesh
- **Impact:** Confusing API, potential bugs, violates single responsibility
- **Fix:** Choose ONE canonical implementation:
- Option A: Keep `tools/remeshing.py` (simpler, matches ARCHITECTURE.md)
- Option B: Keep `retopo_tools/remesh.py` (more parameters, more features)
- Delete the other and remove duplicate registrations from server.py
- **Files affected:**
- `src/tools/remeshing.py` vs `src/retopo_tools/remesh.py`
- `src/server.py` lines 268, 298, 608, 1100
**3. Clarify tools/ vs retopo_tools/ Distinction [SEVERITY: MAJOR]**
- **Issue:** Two overlapping directory structures with unclear boundaries
- **Impact:** Confusing organization, duplicate code, unclear where to add new tools
- **Fix:** Establish clear policy:
- Option A: Merge `retopo_tools/*` into `tools/` (simplifies, matches docs)
- Option B: Document distinction in ARCHITECTURE.md:
- `tools/` = core retopo operations (mesh_analysis, remeshing, viewport, shading, scene)
- `retopo_tools/` = advanced workflows (modifiers, mesh_ops, baking, camera, io)
- Update ARCHITECTURE.md accordingly
- **Files affected:** ARCHITECTURE.md, potentially all tool imports
### MAJOR (Fix Soon)
**4. Update ARCHITECTURE.md to Match Reality [SEVERITY: MAJOR]**
- **Issue:** ARCHITECTURE.md does not document `retopo_tools/` directory
- **Impact:** Misleading documentation, confusion for new contributors
- **Fix:** Add section documenting `retopo_tools/` structure and purpose
- **Location:** `D:\repos\blender-mcp\ARCHITECTURE.md`
**5. Consolidate Duplicate Module Functionality [SEVERITY: MAJOR]**
- **Issue:** Similar duplicates beyond remeshing:
- `tools/mesh_analysis.py` vs `retopo_tools/mesh_analysis.py`
- `tools/modifiers.py` vs `retopo_tools/modifiers.py`
- **Impact:** Code maintenance burden, potential inconsistencies
- **Fix:** After resolving directory structure (Rec #3), merge duplicates
- **Files affected:** Multiple in `tools/` and `retopo_tools/`
### MINOR (Nice to Have)
**6. Add Type Hints for List Parameters [SEVERITY: MINOR]**
- **Issue:** `List[str]` imports missing in some files
- **Current:** Some functions use `list[str]` (Python 3.9+) others use `List[str]`
- **Fix:** Standardize on `from typing import List` for consistency with existing code
- **Example:** `src/server.py:858` uses `List[str]`, but line 487 uses `list[float]`
**7. Add Integration Tests for BDD Features [SEVERITY: MINOR]**
- **Issue:** BDD `.feature` files exist but no test runners found
- **Fix:** Add pytest-bdd or behave test implementations in `tests/`
- **Impact:** Currently specifications without automated verification
**8. Document addon.py Handler Mapping [SEVERITY: MINOR]**
- **Issue:** `addon.py` handler registration not cross-referenced in tool docs
- **Fix:** Add comment blocks in each tool showing corresponding addon.py handler
- **Example:** In `tools/mesh_analysis.py:mesh_stats()`, add comment:
```python
# Blender handler: addon.py:BlenderMCPServer.mesh_stats_handler()
```
## 6. Security & Safety Notes
### Dangerous Tools Identified
**1. execute_blender_code** (`tools/scene.py`)
- **Risk:** Arbitrary Python code execution in Blender
- **Mitigation:** Docstring warns users (line 347-352 in server.py)
- **Status:** ✅ Appropriately documented, risk acknowledged in README.md
### Overly Broad Tools
**None identified** – All tools are appropriately scoped with clear parameters
### Missing Warnings
**1. PolyHaven/Sketchfab/Hyper3D API Keys**
- **Issue:** `addon.py:31` hardcodes `RODIN_FREE_TRIAL_KEY`
- **Risk:** Free trial key exposure, potential rate limiting for all users
- **Fix:** Document in README that users should obtain their own keys for production use
- **Status:** ⚠ README mentions it but doesn't warn about shared key risks
## 7. Positive Observations
### Excellent Architectural Practices ✅
1. **Clean Dependency Boundaries**
- Zero circular dependencies detected
- Unidirectional flow: server → tools/prompts
- Tools and prompts are independent modules
2. **Consistent Error Handling**
- All tools use try/except with logger
- User-friendly error messages with context
- Connection resilience with reconnection logic
3. **Comprehensive Documentation**
- Every tool has complete docstring with Parameters/Returns
- ARCHITECTURE.md provides clear guidance
- BDD feature files serve as executable specs
4. **Modular Refactoring Success**
- server.py reduced from 1514 to 763 lines (per ARCHITECTURE.md metrics)
- Clear separation of concerns
- Easy to locate specific functionality
5. **MCP Integration Quality**
- Proper use of @mcp.tool() and @mcp.prompt() decorators
- FastMCP lifespan management correctly implemented
- Resource endpoints for viewport screenshots
### Well-Structured Components ✅
**Best-in-class modules:**
- `tools/mesh_analysis.py` – Clean, focused, well-documented
- `tools/viewport.py` – Simple, predictable API
- `prompts/retopo.py` – Excellent guided workflow
- `server.py` – Exemplary thin wrapper pattern
## 8. Architectural Health Score
| Category | Score | Notes |
|----------|-------|-------|
| Module Organization | 7/10 | Duplication and unclear tools/ vs retopo_tools/ distinction |
| Dependency Management | 10/10 | Perfect unidirectional dependencies |
| Code Quality | 9/10 | Excellent error handling, naming, docstrings |
| Package Configuration | 3/10 | Critical import path issue |
| Documentation Accuracy | 7/10 | ARCHITECTURE.md outdated, missing retopo_tools/ |
| BDD Coverage | 8/10 | 15 feature files, most implemented, some duplicates |
| Security | 8/10 | Appropriate warnings, one exposed API key |
| **OVERALL** | **7.4/10** | Strong foundations undermined by packaging and duplication issues |
## 9. Next Steps for Development Team
1. **Immediate Action:** Fix package configuration (Recommendation #1)
2. **Short-term:** Resolve duplicate implementations (Recommendations #2, #3, #5)
3. **Medium-term:** Update ARCHITECTURE.md to match reality (Recommendation #4)
4. **Long-term:** Add integration tests for BDD scenarios (Recommendation #7)
## 10. Conclusion
The BlenderMCP project demonstrates excellent architectural discipline in most areas:
- Server.py is a model of clean separation between infrastructure and business logic
- Tool modules are well-organized, documented, and follow consistent patterns
- Dependency boundaries are perfectly maintained with no circular imports
- Error handling and logging are exemplary
However, two critical issues threaten the architectural integrity:
1. **Package configuration mismatch** prevents proper module imports
2. **Duplicate implementations** across tools/ and retopo_tools/ create confusion and maintenance burden
Once these issues are resolved, this codebase will be an excellent example of modular MCP server architecture. The strong foundations are evident—they just need the packaging configuration to match the thoughtful internal structure.
---
**Report Generated:** 2025-11-06 21:37 UTC
**Analyzer:** Architecture Guardian (BlenderMCP)
**Repository:** D:\repos\blender-mcp
**Branch:** main
**Commit:** (not specified, working tree has uncommitted changes)