Skip to main content
Glama
contributing.md13.7 kB
# Contributing Guide Thank you for your interest in contributing to the Ignition MCP Server! This guide will help you get started with development and contributing to the project. ## Table of Contents - [Getting Started](#getting-started) - [Development Setup](#development-setup) - [Code Style Guidelines](#code-style-guidelines) - [Testing](#testing) - [Pull Request Process](#pull-request-process) - [Issue Guidelines](#issue-guidelines) - [Development Workflow](#development-workflow) - [Release Process](#release-process) ## Getting Started ### Prerequisites Before contributing, ensure you have: - **Python 3.10+** installed - **Git** for version control - **uv** or **pip** for package management - Access to an **Ignition Gateway 8.3+** for testing - Familiarity with **asyncio** and **MCP protocol** ### Fork and Clone 1. **Fork the repository** on GitHub 2. **Clone your fork** locally: ```bash git clone https://github.com/yourusername/ignition-mcp.git cd ignition-mcp ``` 3. **Add upstream remote**: ```bash git remote add upstream https://github.com/originalowner/ignition-mcp.git ``` ## Development Setup ### 1. Create Development Environment ```bash # Using uv (recommended) uv venv source .venv/bin/activate # Windows: .venv\Scripts\activate uv pip install -e ".[dev]" # Using pip python -m venv .venv source .venv/bin/activate # Windows: .venv\Scripts\activate pip install -e ".[dev]" ``` ### 2. Install Pre-commit Hooks ```bash pre-commit install ``` This ensures code formatting and linting on every commit. ### 3. Configure Environment ```bash cp .env.example .env # Edit .env with your test gateway details ``` ### 4. Verify Setup ```bash # Run tests pytest # Test code formatting black --check . isort --check-only . ruff check . # Test server python test_server.py ``` ## Code Style Guidelines We follow Python best practices and use automated tooling to maintain consistent code style. ### Formatting Tools - **Black**: Code formatting (100 character line length) - **isort**: Import sorting - **Ruff**: Fast linting and code quality checks - **mypy**: Static type checking ### Style Rules #### 1. Code Formatting ```python # Good: Black-formatted code async def get_gateway_status(self) -> Dict[str, Any]: """Get gateway status information.""" return await self._request("GET", "/system/gateway-network/remote-servers/status") # Bad: Inconsistent formatting async def get_gateway_status(self)->Dict[str,Any]: return await self._request( "GET","/system/gateway-network/remote-servers/status" ) ``` #### 2. Type Hints Always use type hints for function signatures: ```python # Good: Complete type hints async def call_tool(self, name: str, arguments: Dict[str, Any]) -> CallToolResult: """Execute an Ignition Gateway API call.""" ... # Bad: Missing type hints async def call_tool(self, name, arguments): """Execute an Ignition Gateway API call.""" ... ``` #### 3. Docstrings Use Google-style docstrings: ```python async def execute_api_call( self, client: IgnitionClient, tool_def: Dict[str, Any], arguments: Dict[str, Any] ) -> Dict[str, Any]: """Execute the actual API call. Args: client: Ignition client instance tool_def: Tool definition dictionary arguments: Call arguments Returns: API response data Raises: httpx.HTTPStatusError: On API errors """ ``` #### 4. Import Organization Follow isort configuration: ```python # Standard library imports import asyncio import json from typing import Dict, Any, List # Third-party imports import httpx from mcp.types import Tool, CallToolResult # Local imports from .config import settings from .ignition_client import IgnitionClient ``` #### 5. Error Handling Use specific exceptions and proper error messages: ```python # Good: Specific error handling try: result = await client._request(method, final_path, **kwargs) except httpx.HTTPStatusError as e: return CallToolResult( content=[TextContent(type="text", text=f"HTTP {e.response.status_code}: {e.response.text}")], isError=True ) except httpx.ConnectError: return CallToolResult( content=[TextContent(type="text", text="Failed to connect to gateway")], isError=True ) # Bad: Generic error handling try: result = await client._request(method, final_path, **kwargs) except Exception as e: return CallToolResult( content=[TextContent(type="text", text=str(e))], isError=True ) ``` ### Running Style Checks ```bash # Format code black . isort . # Check style ruff check . mypy src/ # Run all checks pre-commit run --all-files ``` ## Testing ### Test Structure ``` tests/ ├── unit/ │ ├── test_config.py │ ├── test_api_generator.py │ └── test_ignition_tools.py ├── integration/ │ ├── test_ignition_client.py │ └── test_server.py └── fixtures/ ├── sample_openapi.json └── mock_responses.py ``` ### Writing Tests #### 1. Unit Tests ```python # tests/unit/test_config.py import pytest from ignition_mcp.config import Settings def test_default_settings(): """Test default configuration values.""" settings = Settings() assert settings.ignition_gateway_url == "http://localhost:8088" assert settings.server_port == 8000 def test_environment_override(): """Test environment variable override.""" import os os.environ["IGNITION_MCP_SERVER_PORT"] = "9000" settings = Settings() assert settings.server_port == 9000 # Cleanup del os.environ["IGNITION_MCP_SERVER_PORT"] ``` #### 2. Integration Tests ```python # tests/integration/test_ignition_client.py import pytest from ignition_mcp.ignition_client import IgnitionClient @pytest.mark.asyncio async def test_get_openapi_spec(): """Test OpenAPI spec retrieval.""" async with IgnitionClient() as client: spec = await client.get_openapi_spec() assert "openapi" in spec assert "paths" in spec @pytest.mark.asyncio async def test_connection_error(): """Test connection error handling.""" client = IgnitionClient(gateway_url="http://invalid-gateway:8088") with pytest.raises(Exception): async with client: await client.get_openapi_spec() ``` #### 3. Mock Testing ```python # tests/unit/test_ignition_tools.py import pytest from unittest.mock import AsyncMock, patch from ignition_mcp.ignition_tools import IgnitionTools @pytest.fixture def mock_api_generator(): """Mock API generator with sample tools.""" with patch('ignition_mcp.ignition_tools.IgnitionAPIGenerator') as mock: mock.return_value.generate_tools.return_value = [ { 'name': 'test_tool', 'description': 'Test tool', 'inputSchema': {'type': 'object', 'properties': {}}, '_ignition_path': '/test', '_ignition_method': 'GET' } ] yield mock def test_get_tools(mock_api_generator): """Test tool generation.""" tools_manager = IgnitionTools() tools = tools_manager.get_tools() assert len(tools) == 1 assert tools[0].name == 'test_tool' ``` ### Running Tests ```bash # Run all tests pytest # Run with coverage pytest --cov=src/ignition_mcp --cov-report=html # Run specific test categories pytest tests/unit/ pytest tests/integration/ # Run specific test file pytest tests/unit/test_config.py # Run with verbose output pytest -v # Run tests matching pattern pytest -k "test_config" ``` ### Test Configuration Create `pytest.ini` for consistent test configuration: ```ini [tool:pytest] testpaths = tests python_files = test_*.py python_classes = Test* python_functions = test_* addopts = --strict-markers --disable-warnings --tb=short markers = unit: Unit tests integration: Integration tests slow: Slow running tests ``` ## Pull Request Process ### 1. Create Feature Branch ```bash # Update main branch git checkout main git pull upstream main # Create feature branch git checkout -b feature/your-feature-name # or git checkout -b fix/issue-description ``` ### 2. Make Changes - Write code following the style guidelines - Add tests for new functionality - Update documentation if needed - Ensure all tests pass ### 3. Commit Changes ```bash # Stage changes git add . # Commit with descriptive message git commit -m "feat: add support for custom timeout configuration - Add timeout parameter to IgnitionClient - Update configuration with timeout setting - Add tests for timeout functionality - Update documentation" ``` #### Commit Message Format Follow [Conventional Commits](https://www.conventionalcommits.org/): ``` <type>[optional scope]: <description> [optional body] [optional footer(s)] ``` **Types**: - `feat`: New feature - `fix`: Bug fix - `docs`: Documentation changes - `style`: Code style changes (formatting) - `refactor`: Code refactoring - `test`: Adding or updating tests - `chore`: Maintenance tasks **Examples**: ``` feat(tools): add project import validation fix(client): handle connection timeout errors docs: update installation guide for Windows test: add integration tests for backup tools ``` ### 4. Push and Create PR ```bash # Push feature branch git push origin feature/your-feature-name # Create pull request on GitHub ``` ### 5. PR Requirements Your pull request must: - [ ] Include clear description of changes - [ ] Have passing tests (`pytest`) - [ ] Pass code quality checks (`ruff`, `black`, `isort`, `mypy`) - [ ] Include documentation updates if needed - [ ] Follow semantic versioning for breaking changes - [ ] Have appropriate commit messages ### 6. Review Process - Maintainers will review your PR - Address any feedback or requested changes - Once approved, your PR will be merged ## Issue Guidelines ### Reporting Bugs Use the bug report template: ```markdown **Bug Description** A clear description of what the bug is. **Steps to Reproduce** 1. Go to '...' 2. Click on '....' 3. See error **Expected Behavior** What you expected to happen. **Actual Behavior** What actually happened. **Environment** - OS: [e.g. macOS 14.0] - Python: [e.g. 3.11.0] - Ignition Version: [e.g. 8.1.25] - MCP Server Version: [e.g. 0.1.0] **Additional Context** Any other context about the problem. ``` ### Feature Requests Use the feature request template: ```markdown **Feature Description** A clear description of what you want to happen. **Use Case** Describe the use case that would benefit from this feature. **Proposed Solution** If you have ideas on how to implement this, describe them here. **Alternatives Considered** Describe any alternative solutions you've considered. **Additional Context** Any other context or screenshots about the feature request. ``` ### Issue Labels - `bug`: Something isn't working - `enhancement`: New feature or request - `documentation`: Improvements or additions to documentation - `good first issue`: Good for newcomers - `help wanted`: Extra attention is needed - `priority:high`: High priority issue - `priority:low`: Low priority issue ## Development Workflow ### 1. Daily Development ```bash # Start development session git checkout main git pull upstream main git checkout -b feature/new-feature # Make changes, test frequently pytest tests/unit/ python test_server.py # Commit often with good messages git add . git commit -m "feat: implement basic functionality" # Continue development... ``` ### 2. Before Submitting ```bash # Run full test suite pytest # Check code quality pre-commit run --all-files # Update documentation if needed # Update CHANGELOG.md if significant changes # Rebase on latest main git fetch upstream git rebase upstream/main # Push and create PR git push origin feature/new-feature ``` ### 3. Keeping Fork Updated ```bash # Regularly sync with upstream git checkout main git fetch upstream git merge upstream/main git push origin main ``` ## Release Process ### Versioning We use [Semantic Versioning](https://semver.org/): - `MAJOR.MINOR.PATCH` (e.g., 1.2.3) - `MAJOR`: Breaking changes - `MINOR`: New features (backward compatible) - `PATCH`: Bug fixes (backward compatible) ### Release Steps 1. **Update Version**: - Update `pyproject.toml` - Update `CHANGELOG.md` 2. **Create Release PR**: ```bash git checkout -b release/v1.2.3 # Make version updates git commit -m "chore: bump version to 1.2.3" ``` 3. **Tag Release**: ```bash git tag v1.2.3 git push upstream v1.2.3 ``` 4. **GitHub Release**: - Create release on GitHub - Include changelog - Attach built packages ## Getting Help ### Development Questions - **GitHub Discussions**: For general questions - **Discord/Slack**: Real-time chat (if available) - **Issues**: For specific bugs or features ### Resources - [MCP Protocol Documentation](https://github.com/modelcontextprotocol) - [Ignition API Documentation](https://docs.inductiveautomation.com/) - [Python AsyncIO Guide](https://docs.python.org/3/library/asyncio.html) - [Pydantic Documentation](https://docs.pydantic.dev/) ## Code of Conduct Please note that this project is released with a [Code of Conduct](CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms. ## License By contributing to this project, you agree that your contributions will be licensed under the MIT License. --- Thank you for contributing to the Ignition MCP Server! Your contributions help make this project better for everyone.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/WhiskeyHouse/ignition-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server