Skip to content

Contributing

Thank you for your interest in contributing to FreeCAD Robust MCP Server!


Development Setup

Prerequisites

  • Python 3.11 (must match FreeCAD's bundled version)
  • mise for tool management
  • FreeCAD 0.21+ or 1.0+ installed

Initial Setup

git clone https://github.com/spkane/freecad-robust-mcp-and-more.git
cd freecad-robust-mcp-and-more

# Install mise if not already installed
curl https://mise.run | sh

# Install project tools and dependencies
mise trust
mise install
just setup

Safety CLI Account (Required for Security Scanning)

This project uses Safety CLI for dependency vulnerability scanning. Safety requires a free account for the safety scan command used in pre-commit hooks.

# Register for a free account (interactive)
uv run safety auth

# Or login if you already have an account
uv run safety auth --login

Note: Authentication is stored locally and only needs to be done once per machine. If you skip this step, the safety pre-commit hook will fail with an authentication prompt.

CI/CD: Safety runs in CI using the SAFETY_API_KEY repository secret.

Running Tests

# Run unit tests
just testing::unit

# Run with coverage
just testing::cov

# Run all tests including integration
just testing::all

# Run type checking
uv run mypy src/

Code Quality

# Run all pre-commit checks
just quality::check

# Run linting
just quality::lint

# Format code
just quality::format

# Run security checks
just quality::security

Project Structure

freecad-robust-mcp-and-more/
├── src/freecad_mcp/           # Main package
│   ├── bridge/                # FreeCAD connection bridges
│   ├── tools/                 # MCP tool implementations
│   ├── resources/             # MCP resource implementations
│   ├── prompts/               # MCP prompt templates
│   └── server.py              # Main server entry point
├── freecad/                   # FreeCAD addon namespace package
│   └── RobustMCPBridge/       # Workbench files
├── tests/                     # Test suite
│   ├── unit/                  # Unit tests
│   └── integration/           # Integration tests
├── docs/                      # Documentation
└── just/                      # Justfile modules

Contribution Guidelines

Code Style

  • Follow PEP 8 with 88-character line length (ruff/black)
  • Use type hints for all function signatures
  • Write Google-style docstrings
  • Run just quality::format before committing

Testing

  • Write tests for all new functionality
  • Maintain test coverage
  • Run just all before submitting PRs (runs quality checks + unit tests)
  • Integration tests require FreeCAD (run via CI)

Documentation

  • Update docstrings for API changes
  • Update user docs for feature changes
  • Run just documentation::build to build and verify

Commits

  • Use conventional commit format
  • Keep commits focused and atomic
  • Reference issues when applicable

Adding New MCP Tools

  1. Choose the right module in src/freecad_mcp/tools/
  2. Add the tool function with proper docstring:
@mcp.tool()
async def my_new_tool(
    param1: str,
    param2: int = 10,
    doc_name: str | None = None,
) -> dict[str, Any]:
    """Short description of what the tool does.

    Args:
        param1: Description of param1.
        param2: Description of param2.
        doc_name: Document name. Uses active if None.

    Returns:
        Dictionary with result information.
    """
    bridge = await get_bridge()
    code = f'''
# FreeCAD Python code here
_result_ = {{"success": True}}
'''
    result = await bridge.execute_python(code)
    return result.result or {"success": False}
  1. Add tests in the appropriate test file
  2. Update documentation in docs/guide/tools.md
  3. Update capabilities resource in src/freecad_mcp/resources/freecad.py

Adding New Connection Modes

  1. Create a new bridge class in src/freecad_mcp/bridge/
  2. Inherit from FreecadBridge base class
  3. Implement all abstract methods
  4. Add to bridge factory in src/freecad_mcp/bridge/__init__.py
  5. Add configuration option in src/freecad_mcp/config.py
  6. Update documentation

Release Process

Releases are automated via GitHub Actions:

  1. Update the component's RELEASE_NOTES.md file (see Releasing for details)
  2. Bump versions for workbench/macros (MCP Server auto-bumps from tag)
  3. Commit and push changes
  4. Create release tag with just release::tag-<component> X.Y.Z
  5. CI builds and publishes:
  6. PyPI package and Docker images (MCP Server)
  7. GitHub Release archives (workbench and macros)

Future Work

The following items are on the roadmap and welcome contributions:

Embedded Mode Integration Tests

Currently, embedded mode has only mocked unit tests. Adding live integration tests would require:

  1. CI workflow that runs on Linux (embedded mode is Linux-only)
  2. Uses FreeCAD AppImage's bundled Python interpreter
  3. Sets up PYTHONPATH and LD_LIBRARY_PATH to point to AppImage libs
  4. Runs tests with FREECAD_MODE=embedded

Challenge: The AppImage bundles Python 3.11, so tests must run using that interpreter (not the system Python) to avoid ABI incompatibility.

Reference: See macro-test.yaml for how integration tests currently work with xmlrpc mode.


Getting Help


License

This project is licensed under the MIT License. See LICENSE for details.