Contributing
Contributing to ROOT-MCP
Thank you for your interest in contributing to ROOT-MCP! This document provides guidelines and instructions for contributing.
Code of Conduct
Be respectful, professional, and inclusive. We welcome contributions from everyone.
How to Contribute
Reporting Bugs
Check if the bug has already been reported in Issues
If not, create a new issue with:
Clear description of the bug
Steps to reproduce
Expected vs actual behavior
Environment details (Python version, OS, etc.)
Minimal example if possible
Suggesting Features
Open an issue with the “enhancement” label
Describe the feature and its use case
Explain why it would be useful
Provide examples if applicable
Pull Requests
Fork the repository
git clone https://github.com/MohamedElashri/root-mcp cd root-mcp
Create a feature branch
git checkout -b feature/feature-name
Set up development environment
pip install -e ".[dev]"
Make your changes
Write clear, readable code
Follow existing code style
Add docstrings to functions/classes
Update documentation if needed
Add tests
Write tests for new functionality
Ensure existing tests pass
pytest tests/Run code quality checks
# Format code black src/ # Lint ruff check src/ # Type check ty check --python venv/bin/python src/
Commit your changes
git add . git commit -m "Add feature: brief description"
Commit message format:
Use present tense (“Add feature” not “Added feature”)
Be concise but descriptive
Reference issue numbers if applicable
Push to your fork
git push origin feature/feature-name
Open a Pull Request
Describe what your PR does
Reference related issues
Include any breaking changes
Add screenshots if relevant
Development Guidelines
Code Style
Python: Follow PEP 8
Line Length: 100 characters (as configured in pyproject.toml)
Type Hints: Use type hints for all functions
Docstrings: Google-style docstrings
Example:
def read_branches(
path: str,
tree_name: str,
branches: list[str],
selection: str | None = None,
) -> dict[str, Any]:
"""
Read branch data from a TTree.
Args:
path: File path or URI
tree_name: Name of the TTree
branches: List of branch names to read
selection: Optional ROOT-style cut expression
Returns:
Dictionary containing data and metadata
Raises:
KeyError: If branch doesn't exist
ValueError: If selection syntax is invalid
"""
# Implementation
Testing
Write tests for all new features
Maintain or improve code coverage
Test edge cases and error conditions
Use pytest fixtures for common setup
Example:
import pytest
from root_mcp.io import FileManager
def test_file_manager_open():
"""Test FileManager can open ROOT files."""
manager = FileManager(config)
file_obj = manager.open("/path/to/test.root")
assert file_obj is not None
def test_file_manager_cache():
"""Test FileManager caching behavior."""
manager = FileManager(config)
file1 = manager.open("/path/to/test.root")
file2 = manager.open("/path/to/test.root")
assert file1 is file2 # Should be cached
Documentation
Update
../README.mdfor user-facing quick start changesUpdate
ARCHITECTURE.mdfor design changesUpdate
api/tools.mdfor tool reference updatesUsage examples should go in
guides/or docstringsAdd docstrings to all public functions/classes
Include examples in docstrings
Commit Guidelines
Good commit messages:
“Add histogram_2d tool for correlation analysis”
“Fix security issue in path validation”
“Improve caching performance by 30%”
Bad commit messages:
“Fix bug”
“Update code”
“WIP”
Project Structure
root-mcp/
├── src/root_mcp/
│ ├── server.py # Main MCP server
│ ├── config.py # Configuration
│ ├── io/ # I/O layer
│ ├── analysis/ # Analysis operations
│ └── tools/ # MCP tool handlers
├── tests/ # Test suite
├── examples/ # Usage examples
├── docs/ # Documentation
└── config.yaml # Default config
Adding New Tools
To add a new MCP tool:
Define the tool in the appropriate module:
Discovery tools →
src/root_mcp/tools/discovery.pyData access →
src/root_mcp/tools/data_access.pyAnalysis →
src/root_mcp/tools/analysis.py
Add tool specification:
def my_new_tool(self, param1: str, param2: int) -> dict[str, Any]: """ Brief description of what the tool does. Args: param1: Description param2: Description Returns: Dictionary with data and metadata """ # Implementation
Register in server.py:
Tool( name="my_new_tool", description="Description for LLMs", inputSchema={ "type": "object", "properties": { "param1": {"type": "string"}, "param2": {"type": "integer"}, }, "required": ["param1", "param2"], }, )
Add handler in call_tool():
elif name == "my_new_tool": result = self.analysis_tools.my_new_tool(**arguments)
Write tests:
def test_my_new_tool(): """Test my_new_tool functionality.""" # Test implementation
Update documentation:
Add to
docs/api/tools.md(tool reference + usage)
Code Review Process
All PRs require review before merging
Address reviewer feedback promptly
Keep PRs focused and reasonably sized
Ensure CI passes before requesting review
Release Process
Update version in
pyproject.tomlUpdate CHANGELOG.md
Tag release:
git tag -a v1.x.x -m "Release 1.x.x"Push tag:
git push origin v1.x.xGitHub Actions will build and publish to PyPI
Getting Help
Questions: Open a Discussion
Bugs: Open an Issue
License
By contributing, you agree that your contributions will be licensed under the MIT License.