Development Guide¶
Guide for contributing to BlenderForge development.
Development Setup¶
Prerequisites¶
- Python 3.10+
- Blender 3.0+ (for testing)
- Git
Clone and Install¶
# Clone the repository
git clone https://github.com/yourusername/blenderforge.git
cd blenderforge
# Create virtual environment
python -m venv .venv
source .venv/bin/activate # macOS/Linux
# or
.venv\Scripts\activate # Windows
# Install in development mode with dev dependencies
pip install -e ".[dev]"
Verify Installation¶
Project Structure¶
blenderforge/
├── src/blenderforge/ # Main package
│ ├── __init__.py # Package init, version
│ ├── server.py # MCP server implementation
│ ├── config.py # Configuration management
│ ├── telemetry.py # Telemetry client
│ └── telemetry_decorator.py # Telemetry decorator
├── addon.py # Blender addon (standalone)
├── tests/ # Test suite
│ ├── conftest.py # Pytest configuration
│ ├── test_config.py # Config tests
│ ├── test_server.py # Server tests
│ ├── test_tools.py # Tool function tests
│ ├── test_ai_features.py # AI-powered features tests
│ ├── test_telemetry.py # Telemetry tests
│ └── test_integration.py # Integration tests
├── docs/ # Documentation
├── .github/workflows/ # CI/CD pipelines
├── pyproject.toml # Project configuration
└── README.md # Main readme
Running Tests¶
All Tests¶
With Coverage¶
Specific Tests¶
# Run specific test file
pytest tests/test_config.py
# Run specific test
pytest tests/test_config.py::test_default_config
# Run tests matching pattern
pytest -k "telemetry"
Test Markers¶
# Skip integration tests (require Blender)
pytest -m "not integration"
# Skip slow tests
pytest -m "not slow"
Code Quality¶
Formatting¶
Linting¶
Type Checking¶
Pre-commit Hooks¶
Adding New Tools¶
1. Define the Tool in server.py¶
@mcp.tool()
async def my_new_tool(
required_param: str,
optional_param: int = 10
) -> dict:
"""
Short description of what the tool does.
Args:
required_param: Description of required parameter
optional_param: Description of optional parameter
Returns:
dict with result data
"""
result = await send_to_blender({
"command": "my_new_command",
"required_param": required_param,
"optional_param": optional_param
})
return result
2. Add Handler in addon.py¶
class BlenderForgeOperator:
def handle_command(self, command):
# ... existing handlers ...
elif command["command"] == "my_new_command":
return self.handle_my_new_command(command)
def handle_my_new_command(self, params):
"""Handle my_new_command."""
required = params["required_param"]
optional = params.get("optional_param", 10)
# Execute Blender operations
# ...
return {
"success": True,
"result": "..."
}
3. Add Tests¶
# tests/test_server.py
def test_my_new_tool():
"""Test my_new_tool function."""
# Test implementation
pass
4. Document the Tool¶
Add to docs/tools-reference.md:
### my_new_tool
Description of what the tool does.
**Parameters**:
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `required_param` | string | Yes | Description |
| `optional_param` | integer | No | Description (default: 10) |
**Returns**:
...
Adding External API Integrations¶
1. Create API Module (if complex)¶
For simple APIs, add directly to server.py. For complex APIs, create a new module:
# src/blenderforge/myapi.py
import httpx
class MyAPIClient:
BASE_URL = "https://api.example.com"
def __init__(self, api_key: str):
self.api_key = api_key
self.client = httpx.AsyncClient()
async def search(self, query: str) -> list:
response = await self.client.get(
f"{self.BASE_URL}/search",
params={"q": query},
headers={"Authorization": f"Bearer {self.api_key}"}
)
return response.json()
2. Add Configuration¶
In addon.py, add to the preferences class:
class BlenderForgePreferences(bpy.types.AddonPreferences):
# ... existing preferences ...
use_myapi: bpy.props.BoolProperty(
name="Use MyAPI",
default=False
)
myapi_key: bpy.props.StringProperty(
name="MyAPI Key",
subtype='PASSWORD'
)
3. Add Tools¶
@mcp.tool()
async def search_myapi(query: str) -> dict:
"""Search MyAPI for resources."""
if not is_myapi_enabled():
return {"error": "MyAPI is not enabled"}
client = MyAPIClient(get_myapi_key())
results = await client.search(query)
return {"results": results}
4. Document¶
Add to docs/asset-integrations.md.
Testing with Blender¶
Integration Tests¶
Integration tests require Blender to be running:
# tests/test_integration.py
import pytest
@pytest.mark.integration
def test_get_scene_info_integration():
"""Test actual connection to Blender."""
# This test requires Blender to be running
# with the addon enabled
pass
Manual Testing¶
- Start Blender with addon
- Connect BlenderForge server
- Run the MCP server manually:
- Test with MCP client or manually send JSON-RPC
Release Process¶
Version Bump¶
- Update version in
pyproject.toml - Update version in
src/blenderforge/__init__.py - Commit:
git commit -m "Bump version to X.Y.Z"
Create Release¶
-
Create and push tag:
-
GitHub Actions will:
- Run full test suite
- Build distribution
- Publish to PyPI
- Create GitHub release
Code Style Guidelines¶
Python Style¶
- Follow PEP 8 (enforced by ruff)
- Use type hints for function parameters and returns
- Write docstrings for public functions
- Keep functions focused and small
Docstrings¶
Use Google-style docstrings:
def my_function(param1: str, param2: int = 10) -> dict:
"""
Short description of function.
Longer description if needed. Can span
multiple lines.
Args:
param1: Description of param1
param2: Description of param2, defaults to 10
Returns:
Dictionary containing result data
Raises:
ValueError: If param1 is empty
"""
Naming Conventions¶
- Functions/variables:
snake_case - Classes:
PascalCase - Constants:
UPPER_SNAKE_CASE - Private:
_leading_underscore
Error Handling¶
# Return errors in consistent format
async def my_tool():
try:
result = await do_something()
return {"success": True, "data": result}
except SomeError as e:
return {"success": False, "error": str(e)}
Pull Request Process¶
- Fork the repository
- Create branch:
git checkout -b feature/my-feature - Make changes following code style guidelines
- Add tests for new functionality
- Run checks:
- Commit with clear message
- Push to your fork
- Create PR with description of changes
PR Requirements¶
- All tests pass
- Code is formatted and linted
- New features have tests
- Documentation is updated
- Commit messages are clear
Getting Help¶
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- MCP Spec: modelcontextprotocol.io
- Blender API: docs.blender.org/api