First off, thank you for considering contributing to NetworkX MCP Server! It's people like you that make this project such a great tool. We welcome contributions from everyone, regardless of their experience level.
- Code of Conduct
- Getting Started
- How Can I Contribute?
- Development Process
- Style Guidelines
- Commit Guidelines
- Pull Request Process
- Testing
- Documentation
- Community
This project and everyone participating in it is governed by our Code of Conduct. By participating, you are expected to uphold this code. Please report unacceptable behavior to brightliu@college.harvard.edu.
- Be respectful and inclusive: Value each other's ideas, styles, and viewpoints
- Be constructive: Provide helpful feedback and accept criticism gracefully
- Be collaborative: Work together towards common goals
- Be patient: Remember that everyone was new once
- Python 3.11 or higher
- Git
- Basic knowledge of graph theory concepts
-
Fork the repository
# Click "Fork" button on GitHub -
Clone your fork
git clone https://github.com/YOUR_USERNAME/networkx-mcp-server.git cd networkx-mcp-server -
Add upstream remote
git remote add upstream https://github.com/Bright-L01/networkx-mcp-server.git
-
Create a virtual environment
python -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate
-
Install development dependencies
pip install -e ".[dev]" -
Install pre-commit hooks
pre-commit install
-
Run tests to verify setup
pytest
Before creating bug reports, please check existing issues to avoid duplicates. When creating a bug report, include:
- Clear title and description
- Steps to reproduce
- Expected behavior
- Actual behavior
- System information (OS, Python version, etc.)
- Relevant logs or error messages
Example:
### Bug: Shortest path fails with weighted edges
**Steps to reproduce:**
1. Create a graph with weighted edges
2. Call shortest_path with weight parameter
3. Observe error
**Expected:** Returns weighted shortest path
**Actual:** KeyError: 'weight'
**System:** macOS 13.5, Python 3.11.5Enhancement suggestions are tracked as GitHub issues. When creating an enhancement suggestion, include:
- Use case: Why is this enhancement needed?
- Proposed solution: How should it work?
- Alternatives considered: What other solutions did you consider?
- Additional context: Mockups, examples, etc.
- Check existing PRs and issues first
- Discuss major changes in an issue before starting
- Keep PRs focused - one feature/fix per PR
- Include tests for new functionality
- Update documentation as needed
- Follow the style guide
Use descriptive branch names:
feature/add-graph-embedding- New featuresfix/memory-leak-in-flow- Bug fixesdocs/update-api-reference- Documentationrefactor/simplify-algorithms- Code refactoringtest/add-clustering-tests- Test additions
# 1. Sync with upstream
git checkout main
git pull upstream main
# 2. Create feature branch
git checkout -b feature/your-feature-name
# 3. Make changes
# ... edit files ...
# 4. Run tests frequently
pytest tests/working/test_relevant_module.py
# 5. Check code quality
black src/ tests/
ruff check src/ tests/
mypy src/
# 6. Commit changes
git add -p # Stage changes interactively
git commit -m "feat: add amazing feature"
# 7. Push to your fork
git push origin feature/your-feature-nameFollow the existing project structure:
src/networkx_mcp/
βββ __init__.py # Package init
βββ __main__.py # CLI entry point (--version, --debug)
βββ __version__.py # Version string
βββ server.py # MCP server (request handling, tool dispatch)
βββ handlers.py # Tool handler functions (args β result dicts)
βββ tool_registry.py # Tool schemas, handler mapping, build_registry()
βββ errors.py # Error codes, validation, MCPError hierarchy
βββ auth.py # API key auth (opt-in)
βββ graph_cache.py # Thread-safe graph storage with LRU/TTL
βββ monitoring_legacy.py # Health monitoring
βββ core/
β βββ basic_operations.py # Compatibility functions for graphs
β βββ algorithms.py # GraphAlgorithms class (advanced)
βββ academic/
β βββ citations.py # DOI resolution, BibTeX, recommendations
β βββ analytics.py # Author impact, trends, collaboration
βββ monitoring/
β βββ dora_metrics.py # DORA CI/CD metrics collection
βββ tools/
βββ cicd_control.py # GitHub Actions workflow control
When adding new features:
- Put algorithms in appropriate category
- Create new subdirectories for major features
- Keep files focused and under 500 lines
- Use clear, descriptive names
We use Black for formatting and Ruff for linting.
# β
Good: Clear, typed, documented
from typing import Dict, List, Optional
import networkx as nx
def calculate_modularity(
graph: nx.Graph,
communities: List[List[str]],
weight: Optional[str] = None
) -> float:
"""Calculate modularity of community partition.
Args:
graph: Input graph
communities: List of node communities
weight: Edge weight attribute name
Returns:
Modularity score between -1 and 1
Raises:
ValueError: If communities overlap
"""
# Implementation here
pass
# β Bad: Unclear, untyped, undocumented
def calc_mod(g, comms, w=None):
# calculate modularity
pass- Type hints: Always use type hints
- Docstrings: Use Google-style docstrings
- Variable names: Be descriptive (
node_countnotn) - Functions: Keep them small and focused
- Error handling: Raise specific exceptions with clear messages
- Constants: Use UPPER_CASE for module-level constants
# β
Good: Descriptive, isolated, comprehensive
import pytest
import networkx as nx
from networkx_mcp.algorithms import find_shortest_path
class TestShortestPath:
"""Test shortest path algorithms."""
def test_simple_path(self):
"""Test shortest path in simple graph."""
# Arrange
graph = nx.Graph()
graph.add_edges_from([("A", "B"), ("B", "C")])
# Act
path = find_shortest_path(graph, "A", "C")
# Assert
assert path == ["A", "B", "C"]
def test_no_path_exists(self):
"""Test when no path exists between nodes."""
graph = nx.Graph()
graph.add_nodes_from(["A", "B"])
with pytest.raises(nx.NetworkXNoPath):
find_shortest_path(graph, "A", "B")
@pytest.mark.parametrize("weight,expected", [
("weight", ["A", "C"]),
(None, ["A", "B", "C"]),
])
def test_weighted_paths(self, weight, expected):
"""Test paths with different weight configurations."""
# Test implementationWe follow Conventional Commits specification.
<type>(<scope>): <subject>
<body>
<footer>
- feat: New feature
- fix: Bug fix
- docs: Documentation only
- style: Code style changes (formatting, missing semicolons, etc)
- refactor: Code change that neither fixes a bug nor adds a feature
- perf: Performance improvement
- test: Adding missing tests
- build: Changes to build system or dependencies
- ci: Changes to CI configuration
- chore: Other changes that don't modify src or test files
# β
Good commits
git commit -m "feat(algorithms): add A* pathfinding algorithm
- Implement A* with customizable heuristic
- Add tests for grid and network graphs
- Update documentation with examples
Closes #123"
git commit -m "fix(storage): handle empty graphs in save operations
Empty NetworkX graphs are falsy, causing save failures.
Changed condition from 'if graph:' to 'if graph is not None:'
Fixes #456"
git commit -m "docs: add examples for community detection
- Add Louvain algorithm example
- Include visualization of results
- Link to theoretical background"
# β Bad commits
git commit -m "fixed stuff"
git commit -m "WIP"
git commit -m "add feature"-
Update from upstream main
git checkout main git pull upstream main git checkout your-branch git rebase main
-
Run all checks
# Format code black src/ tests/ # Lint ruff check src/ tests/ # Type check mypy src/ # Run all tests pytest # Check coverage pytest --cov=src/networkx_mcp --cov-report=term-missing
-
Update documentation
- Add/update docstrings
- Update README if needed
- Add to CHANGELOG.md (unreleased section)
## Description
Brief description of what this PR does.
## Motivation and Context
Why is this change required? What problem does it solve?
If it fixes an open issue, link it here.
## How Has This Been Tested?
Describe the tests you ran. Include OS and Python version.
## Types of changes
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to change)
## Checklist:
- [ ] My code follows the project style guidelines
- [ ] I have performed a self-review of my own code
- [ ] I have added tests that prove my fix is effective or that my feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] I have added necessary documentation (if appropriate)
- [ ] Any dependent changes have been merged and published- Automated checks must pass (CI, tests, linting)
- Code review by at least one maintainer
- Address feedback promptly and politely
- Squash commits if requested
- Celebrate when merged!
# Run all tests
pytest
# Run specific test file
pytest tests/test_algorithms.py
# Run specific test
pytest tests/test_algorithms.py::test_shortest_path
# Run with coverage
pytest --cov=src/networkx_mcp --cov-report=html
# Run only fast tests
pytest -m "not slow"
# Run with verbose output
pytest -v- Test file naming:
test_<module_name>.py - Test class naming:
Test<FeatureName> - Test method naming:
test_<specific_scenario> - Use fixtures for common setup
- Test edge cases and error conditions
- Mock external dependencies when needed
Mark tests appropriately:
@pytest.mark.slow # Tests taking >1 second
@pytest.mark.integration # Tests requiring Redis
@pytest.mark.benchmark # Performance testsUse Google-style docstrings:
def complex_function(
graph: nx.Graph,
source: str,
target: str,
weight: str = "weight",
cutoff: Optional[int] = None
) -> List[str]:
"""Find shortest path between source and target.
This function implements Dijkstra's algorithm with optimizations
for sparse graphs. It handles both weighted and unweighted graphs.
Args:
graph: NetworkX graph instance
source: Starting node for path
target: Ending node for path
weight: Name of edge attribute to use as weight.
If None, all edges have weight 1.
cutoff: Depth to stop the search. Only paths of
length <= cutoff are returned.
Returns:
List of nodes representing the shortest path.
Empty list if no path exists.
Raises:
NodeNotFound: If source or target not in graph
ValueError: If weight attribute doesn't exist
Examples:
>>> G = nx.Graph()
>>> G.add_edges_from([('A', 'B'), ('B', 'C')])
>>> complex_function(G, 'A', 'C')
['A', 'B', 'C']
Note:
For graphs with negative weights, use Bellman-Ford
algorithm instead.
"""- API changes: Update docstrings immediately
- New features: Add to relevant docs/guides
- Examples: Provide working code examples
- Changelog: Add entry to unreleased section
- GitHub Discussions - Ask questions
- Issue Tracker - Report bugs
- Email: brightliu@college.harvard.edu
- Discussions: General questions and ideas
- Issues: Bug reports and feature requests
- Pull Requests: Code contributions
- Security: See SECURITY.md for vulnerability reporting
Contributors are recognized in release notes and project documentation.
Your contributions make this project better for everyone. Whether it's fixing a typo, adding a test, or implementing a new feature, every contribution is valued.