Contributing#

Thank you for your interest in contributing to the OpenSWMM MCP Server. This guide covers development setup, coding standards, and the pull request process.

Development Setup#

  1. Clone the repository:

    git clone https://github.com/HydroCouple/openswmm.mcp.git
    cd openswmm.mcp
    
  2. Create a virtual environment:

    python -m venv .venv
    source .venv/bin/activate  # Linux/macOS
    .venv\Scripts\activate     # Windows
    
  3. Install in editable mode with dev extras:

    pip install -e ".[dev,docs]"
    
  4. Verify the installation:

    pytest tests/unit/ -v
    ruff check src/ tests/
    ruff format --check src/ tests/
    

Project Layout#

src/openswmm_mcp/    # Main package (src layout)
tests/
  unit/              # Unit tests (mock engine, no C extensions needed)
  integration/       # Integration tests (require compiled openswmm engine)
  mocks/             # Mock engine classes
docs/                # Sphinx documentation

Coding Standards#

Style#

  • Formatter: Ruff (ruff format).

  • Linter: Ruff (ruff check) with rules: E, F, I, W, UP.

  • Line length: 100 characters.

  • Target Python: 3.10+.

Type Annotations#

  • All public functions and methods should have type annotations.

  • Use from __future__ import annotations for PEP 604 union syntax (X | Y).

  • Pydantic models define the schema for all tool responses.

Docstrings#

  • Use NumPy-style docstrings for tool functions (these are rendered by Napoleon in Sphinx and surfaced to MCP clients as tool descriptions).

  • Module-level docstrings describe the purpose of each file.

Async Conventions#

  • All tool functions are async.

  • Engine calls (synchronous Cython bindings) are wrapped in asyncio.to_thread().

  • Use asyncio.Lock for shared state protection in SessionManager.

Adding a New Tool#

  1. Identify the appropriate sub-server module in src/openswmm_mcp/tools/.

  2. Define the tool function with @sub_mcp.tool() decorator.

  3. Add parameter type annotations – FastMCP generates the JSON schema from these.

  4. Use get_session_manager(ctx) and require_state() for session access.

  5. Wrap engine calls in asyncio.to_thread().

  6. Return a Pydantic model or dict.

  7. Add a corresponding unit test in tests/unit/.

  8. Update the documentation in docs/user-guide/tools.md.

Running Tests#

Unit Tests#

Unit tests use mock engine classes and the in-memory MCP client. They do not require the compiled openswmm engine.

pytest tests/unit/ -v

With Coverage#

pytest tests/unit/ -v --cov=openswmm_mcp --cov-report=term-missing

Integration Tests#

Integration tests require a compiled openswmm engine installation. They are marked with @pytest.mark.integration and skipped by default.

OPENSWMM_RUN_INTEGRATION=1 pytest tests/integration/ -v

Linting#

ruff check src/ tests/
ruff format --check src/ tests/

To auto-fix:

ruff check --fix src/ tests/
ruff format src/ tests/

Building Documentation#

sphinx-build -W -b html docs docs/_build/html

Open docs/_build/html/index.html in a browser to preview.

Pull Request Process#

  1. Branch from main: Create a feature branch with a descriptive name (e.g. feature/add-pump-tools, fix/session-cleanup).

  2. Write tests first: Ensure new functionality has corresponding unit tests. Aim for 80 %+ coverage on new code.

  3. Run CI checks locally:

    ruff check src/ tests/
    ruff format --check src/ tests/
    pytest tests/unit/ -v --cov=openswmm_mcp
    sphinx-build -W -b html docs docs/_build/html
    
  4. Commit with clear messages: Use imperative mood (e.g. “Add pump speed forcing tool”).

  5. Open a pull request: Target main. Include a summary of changes and a test plan.

  6. CI must pass: The GitHub Actions CI workflow runs linting, tests across Python 3.10–3.13 on Ubuntu/macOS/Windows, and the documentation build.

  7. Review: At least one maintainer approval is required before merging.

Reporting Issues#

Open an issue on GitHub with:

  • A clear description of the problem or feature request.

  • Steps to reproduce (for bugs).

  • Python version and operating system.

  • Relevant logs or error messages.