Skip to main content
Glama

MCP SSH Orchestrator

by samerfarida
13-Contributing.md13.8 kB
# 13. Contributing **Purpose:** Guide for contributing to MCP SSH Orchestrator development, including setup, coding standards, and submission process. ## Overview We welcome contributions to MCP SSH Orchestrator! This guide covers how to set up a development environment, understand the codebase, and submit contributions. ## Development Setup ### Prerequisites **Required Software:** - Python 3.11+ - Docker and Docker Compose - Git - SSH client - Code editor (VS Code recommended) **Optional Tools:** - Poetry (for dependency management) - Pre-commit hooks - Docker Desktop ### Local Development Environment **1. Clone the repository:** ```bash git clone https://github.com/samerfarida/mcp-ssh-orchestrator.git cd mcp-ssh-orchestrator ``` **2. Set up Python environment:** ```bash # Create virtual environment python -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate # Install dependencies pip install -e . pip install -r requirements-dev.txt ``` **3. Set up pre-commit hooks:** ```bash pre-commit install ``` **4. Configure development environment:** ```bash # Copy example configurations cp examples/example-servers.yml config/servers.yml cp examples/example-credentials.yml config/credentials.yml cp examples/example-policy.yml config/policy.yml # Generate SSH keys for testing ssh-keygen -t ed25519 -f keys/test_key -N "" chmod 0400 keys/test_key ``` ### Docker Development **Development with Docker Compose:** ```bash # Build development image docker-compose -f compose/docker-compose.dev.yml build # Run development environment docker-compose -f compose/docker-compose.dev.yml up # Run tests docker-compose -f compose/docker-compose.dev.yml run mcp-ssh pytest ``` **Development Container:** ```bash # Run development container docker run -it --rm \ -v $(pwd):/app \ -v $(pwd)/config:/app/config:ro \ -v $(pwd)/keys:/app/keys:ro \ ghcr.io/samerfarida/mcp-ssh-orchestrator:0.1.0 \ bash ``` ## Codebase Structure ### Project Layout ``` src/mcp_ssh/ ├── __init__.py # Package initialization ├── config.py # Configuration management ├── mcp_server.py # MCP server implementation ├── policy.py # Policy engine ├── ssh_client.py # SSH client wrapper └── tools/ ├── __init__.py # Tools package └── utilities.py # Utility functions tests/ ├── test_config.py # Configuration tests ├── test_policy.py # Policy engine tests ├── test_ssh.py # SSH client tests └── test_server_tools.py # MCP server tests ``` ### Key Components **MCP Server (`mcp_server.py`):** - Implements MCP protocol - Handles tool registration - Manages client sessions - Provides audit logging **Policy Engine (`policy.py`):** - Evaluates command policies - Manages security rules - Handles network filtering - Provides compliance reporting **SSH Client (`ssh_client.py`):** - Wraps SSH connections - Manages authentication - Handles command execution - Provides error handling **Configuration (`config.py`):** - Loads YAML configurations - Validates settings - Manages secrets - Provides defaults ## Coding Standards ### Python Style **Code Formatting:** - Use Black for code formatting - Use isort for import sorting - Follow PEP 8 guidelines - Use type hints **Example:** ```python from typing import Dict, List, Optional import logging logger = logging.getLogger(__name__) def evaluate_policy( alias: str, command: str, tags: List[str] ) -> Dict[str, bool]: """Evaluate policy for command execution. Args: alias: Host alias command: Command to execute tags: Host tags Returns: Policy evaluation result """ # Implementation here pass ``` ### Documentation **Docstring Format:** ```python def ssh_run(alias: str, command: str) -> Dict[str, Any]: """Execute SSH command on target host. Args: alias: Host alias from servers.yml command: Command to execute Returns: Command execution result with output and exit code Raises: PolicyViolationError: If command violates policy SSHConnectionError: If SSH connection fails """ pass ``` **Inline Comments:** ```python # Policy evaluation: check if command is allowed if not policy.evaluate(alias, command, tags): raise PolicyViolationError(f"Command '{command}' not allowed for '{alias}'") # SSH connection: establish secure connection with SSHClient(host_config) as client: result = client.execute(command) ``` ### Testing **Test Structure:** ```python import pytest from unittest.mock import Mock, patch from mcp_ssh.policy import Policy class TestPolicy: """Test policy engine functionality.""" def setup_method(self): """Set up test fixtures.""" self.policy = Policy("tests/fixtures/policy.yml") def test_allow_command(self): """Test command allowance.""" result = self.policy.evaluate("web1", "uptime", ["production"]) assert result["allowed"] is True def test_deny_command(self): """Test command denial.""" result = self.policy.evaluate("web1", "rm -rf /", ["production"]) assert result["allowed"] is False @patch('mcp_ssh.policy.logger') def test_policy_violation_logging(self, mock_logger): """Test policy violation logging.""" self.policy.evaluate("web1", "rm -rf /", ["production"]) mock_logger.warning.assert_called_once() ``` **Test Data:** ```python # tests/fixtures/policy.yml known_hosts_path: "/app/keys/known_hosts" limits: max_seconds: 30 max_output_bytes: 131072 rules: - action: "allow" aliases: ["web1"] tags: ["production"] commands: - "uptime*" - "df -h*" - action: "deny" aliases: ["*"] tags: ["*"] commands: - "rm -rf *" - "shutdown*" ``` ## Development Workflow ### Feature Development **1. Create feature branch:** ```bash git checkout -b feature/new-policy-rule ``` **2. Implement feature:** ```python # Add new policy rule type class PolicyRule: def __init__(self, action: str, conditions: Dict[str, Any]): self.action = action self.conditions = conditions def evaluate(self, alias: str, command: str, tags: List[str]) -> bool: # Implementation pass ``` **3. Add tests:** ```python def test_new_policy_rule(): """Test new policy rule functionality.""" rule = PolicyRule("allow", {"aliases": ["web1"]}) result = rule.evaluate("web1", "uptime", ["production"]) assert result is True ``` **4. Update documentation:** ```markdown # Update wiki documentation # Add examples to usage cookbook # Update API reference ``` ### Bug Fixes **1. Create bug fix branch:** ```bash git checkout -b bugfix/ssh-connection-timeout ``` **2. Reproduce issue:** ```python # Create test that reproduces the bug def test_ssh_connection_timeout(): """Test SSH connection timeout handling.""" with pytest.raises(SSHTimeoutError): ssh_client.connect("slow-host", timeout=1) ``` **3. Fix the issue:** ```python # Implement fix def connect(self, host: str, timeout: int = 30): """Connect to SSH host with timeout.""" try: self.client.connect(host, timeout=timeout) except socket.timeout: raise SSHTimeoutError(f"Connection to {host} timed out") ``` **4. Verify fix:** ```python # Test that fix works def test_ssh_connection_timeout_fixed(): """Test SSH connection timeout fix.""" with patch('socket.socket') as mock_socket: mock_socket.return_value.connect.side_effect = socket.timeout() with pytest.raises(SSHTimeoutError): ssh_client.connect("slow-host", timeout=1) ``` ### Code Review Process **1. Submit pull request:** ```bash git push origin feature/new-policy-rule # Create PR on GitHub ``` **2. Address feedback:** ```bash # Make requested changes git add . git commit -m "Address review feedback" git push origin feature/new-policy-rule ``` **3. Merge after approval:** ```bash # Squash commits if needed git rebase -i main git push origin feature/new-policy-rule --force-with-lease ``` ## Testing Guidelines ### Unit Tests **Test Coverage:** - Aim for 90%+ code coverage - Test all public methods - Test error conditions - Test edge cases **Test Examples:** ```python def test_config_validation(): """Test configuration validation.""" config = Config("tests/fixtures/config.yml") assert config.validate() is True # Test invalid config with pytest.raises(ConfigError): Config("tests/fixtures/invalid-config.yml") def test_policy_evaluation(): """Test policy evaluation logic.""" policy = Policy("tests/fixtures/policy.yml") # Test allow case result = policy.evaluate("web1", "uptime", ["production"]) assert result["allowed"] is True # Test deny case result = policy.evaluate("web1", "rm -rf /", ["production"]) assert result["allowed"] is False ``` ### Integration Tests **End-to-end testing:** ```python def test_ssh_command_execution(): """Test complete SSH command execution flow.""" # Set up test environment with DockerCompose("tests/docker-compose.yml") as compose: # Wait for services compose.wait_for_service("test-host", 22) # Execute command result = ssh_run("test-host", "uptime") # Verify result assert result["exit_code"] == 0 assert "load average" in result["output"] ``` ### Performance Tests **Load testing:** ```python def test_concurrent_ssh_connections(): """Test concurrent SSH connections.""" import concurrent.futures def execute_command(host): return ssh_run(host, "uptime") hosts = ["web1", "web2", "web3"] with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor: futures = [executor.submit(execute_command, host) for host in hosts] results = [future.result() for future in futures] # Verify all commands succeeded assert all(result["exit_code"] == 0 for result in results) ``` ## Documentation Contributions ### Wiki Updates **Documentation Standards:** - Use clear, concise language - Include code examples - Provide practical use cases - Update related sections **Example Update:** ```markdown # Add new section to Usage Cookbook ## Advanced Policy Rules **Purpose:** Demonstrate advanced policy rule configurations for complex scenarios. ### Time-based Rules ```yaml rules: - action: "allow" aliases: ["*"] tags: ["production"] commands: ["uptime*"] time_restrictions: start_time: "09:00" end_time: "17:00" timezone: "UTC" ``` ### Resource-based Rules ```yaml rules: - action: "allow" aliases: ["*"] tags: ["production"] commands: ["df -h*"] resource_limits: max_memory: "1GB" max_cpu: "50%" ``` ``` ### API Documentation **Function documentation:** ```python def ssh_run(alias: str, command: str) -> Dict[str, Any]: """Execute SSH command on target host. This function provides secure SSH command execution with policy enforcement, audit logging, and error handling. Args: alias: Host alias from servers.yml configuration command: Command to execute on the target host Returns: Dictionary containing: - output: Command output (str) - error: Error output (str) - exit_code: Command exit code (int) - execution_time: Execution duration in seconds (float) Raises: PolicyViolationError: If command violates policy rules SSHConnectionError: If SSH connection fails SSHTimeoutError: If command execution times out Example: >>> result = ssh_run("web1", "uptime") >>> print(result["output"]) 10:30:45 up 5 days, 2:15, 1 user, load average: 0.00, 0.01, 0.05 """ pass ``` ## Release Process ### Version Management **Semantic Versioning:** - MAJOR: Breaking changes - MINOR: New features - PATCH: Bug fixes **Version Bump:** ```bash # Update version in pyproject.toml version = "0.2.0" # Update CHANGELOG.md ## [0.2.0] - 2024-01-15 ### Added - New policy rule types - Enhanced audit logging - Performance improvements ### Changed - Updated MCP protocol version - Improved error handling ### Fixed - SSH connection timeout issues - Policy evaluation bugs ``` ### Release Checklist **Pre-release:** - [ ] All tests passing - [ ] Documentation updated - [ ] CHANGELOG.md updated - [ ] Version bumped - [ ] Security review completed **Release:** - [ ] Create release tag - [ ] Build Docker image - [ ] Push to registry - [ ] Update GitHub release - [ ] Announce release ## Community Guidelines ### Code of Conduct **Our Pledge:** - Be respectful and inclusive - Welcome newcomers - Focus on constructive feedback - Respect different viewpoints **Reporting Issues:** - Use GitHub issues for bugs - Use discussions for questions - Be specific and provide context - Include reproduction steps ### Getting Help **Resources:** - GitHub Discussions for questions - GitHub Issues for bugs - Wiki documentation - Code examples **Contributing:** - Start with small fixes - Ask questions early - Follow coding standards - Test your changes ## Next Steps - **[FAQ](14-FAQ)** - Common development questions - **[CHANGELOG](../CHANGELOG.md)** - Version history and releases - **[Security Model](05-Security-Model)** - Security considerations for contributors - **[Troubleshooting](12-Troubleshooting)** - Development environment issues

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/samerfarida/mcp-ssh-orchestrator'

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