# Contributing to Clockify MCP Server
Thank you for your interest in contributing! This document provides guidelines and instructions for contributing to the project.
## Getting Started
### Prerequisites
- Python 3.10 or higher
- Git
- Clockify account with API access
### Development Setup
1. **Fork and clone the repository**
```bash
git clone https://github.com/yourusername/clockify-mcp-server.git
cd clockify-mcp-server
```
2. **Set up development environment**
```bash
# Run the setup script
./setup.sh
# Or manually:
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
```
3. **Set your API key**
```bash
export CLOCKIFY_API_KEY="your_key_here"
```
4. **Test the installation**
```bash
python example_usage.py
```
## Project Structure
```
clockify-mcp-server/
├── src/clockify_mcp/
│ ├── __init__.py # Package initialization
│ ├── client.py # Clockify API client
│ └── server.py # MCP server implementation
├── docs/ # API documentation
├── tests/ # Test suite (TODO)
├── pyproject.toml # Project metadata and dependencies
└── README.md # Main documentation
```
## Development Workflow
### Making Changes
1. **Create a feature branch**
```bash
git checkout -b feature/your-feature-name
```
2. **Make your changes**
- Follow the existing code style
- Add docstrings to new functions
- Update documentation as needed
3. **Test your changes**
```bash
# Run tests (when implemented)
pytest tests/
# Test the example script
python example_usage.py
# Test the MCP server manually
clockify-mcp-server
```
4. **Format and lint**
```bash
# Format code
black src/
# Check linting
ruff check src/
```
5. **Commit your changes**
```bash
git add .
git commit -m "feat: add your feature description"
```
### Commit Message Convention
We follow [Conventional Commits](https://www.conventionalcommits.org/):
- `feat:` New feature
- `fix:` Bug fix
- `docs:` Documentation changes
- `style:` Code style changes (formatting, etc.)
- `refactor:` Code refactoring
- `test:` Adding or updating tests
- `chore:` Maintenance tasks
### Submitting Changes
1. **Push to your fork**
```bash
git push origin feature/your-feature-name
```
2. **Create a Pull Request**
- Use a clear title and description
- Reference any related issues
- Include examples of usage if applicable
## Code Style
### Python Style Guide
We follow [PEP 8](https://pep8.org/) with these specifics:
- **Line length**: 100 characters max
- **Indentation**: 4 spaces
- **Quotes**: Double quotes for strings
- **Imports**: Grouped and sorted (stdlib, third-party, local)
### Documentation
- **Docstrings**: Use Google style docstrings
- **Type hints**: Add type hints to all function signatures
- **Comments**: Explain "why", not "what"
Example:
```python
async def find_user_by_name(
self,
workspace_id: str,
name: str
) -> Optional[Dict[str, Any]]:
"""
Find a user by name with case-insensitive partial matching.
Args:
workspace_id: The workspace to search in
name: User name or partial name to search for
Returns:
User dictionary if found, None otherwise
Example:
user = await client.find_user_by_name(ws_id, "John")
"""
# Implementation
```
## Adding New Tools
To add a new MCP tool:
1. **Add the tool definition** in `server.py` `list_tools()`:
```python
Tool(
name="your_tool_name",
description="Clear description of what the tool does",
inputSchema={
"type": "object",
"properties": {
"param_name": {
"type": "string",
"description": "Parameter description"
}
},
"required": ["param_name"]
}
)
```
2. **Implement the tool handler** in `server.py` `call_tool()`:
```python
elif name == "your_tool_name":
param = arguments["param_name"]
# Implementation
result = await client.some_method(param)
return [TextContent(
type="text",
text=f"Result: {result}"
)]
```
3. **Add client methods** if needed in `client.py`:
```python
async def some_method(self, param: str) -> Dict[str, Any]:
"""Method documentation"""
url = f"{self.base_url}/endpoint"
response = await self.client.get(url, headers=self.headers)
response.raise_for_status()
return response.json()
```
4. **Update documentation** in `README.md`
5. **Test thoroughly** with real Clockify data
## Testing Guidelines
### Manual Testing
Always test with real Clockify data:
1. Test with your own account
2. Test edge cases (empty results, missing data)
3. Test error handling (invalid IDs, network errors)
4. Test with different workspaces if available
### Automated Testing (TODO)
We're working on adding automated tests. When implemented:
```bash
# Run all tests
pytest
# Run specific test file
pytest tests/test_client.py
# Run with coverage
pytest --cov=clockify_mcp
```
## Documentation
### Updating Documentation
- **README.md**: User-facing documentation
- **API docs** (docs/): Reference documentation
- **MCP_CONFIG_EXAMPLE.md**: Configuration examples
- **CONTRIBUTING.md**: This file
### Writing Good Documentation
- Use clear, concise language
- Include examples
- Explain prerequisites
- Document edge cases and limitations
- Keep it up-to-date with code changes
## API Design Principles
When working with the Clockify API:
1. **Use async/await**: All API calls should be async
2. **Handle errors gracefully**: Catch exceptions and provide helpful messages
3. **Validate inputs**: Check parameters before making API calls
4. **Respect rate limits**: Don't make unnecessary API calls
5. **Default to user's workspace**: Use default workspace when not specified
6. **Parse durations consistently**: Use helper methods for PT format
7. **Return user-friendly data**: Format responses for human readability
## Common Issues
### "No workspaces found"
- Check API key is valid
- Ensure user has workspace access
### "User not found"
- User search is partial and case-insensitive
- Try different variations of the name
### Rate Limiting
- Clockify allows 50 requests/second
- Batch operations when possible
- Cache reference data (users, projects)
## Getting Help
- **Questions**: Open a GitHub Discussion
- **Bugs**: Open a GitHub Issue
- **Clockify API**: Check [docs.clockify.me](https://docs.clockify.me/)
## Code of Conduct
- Be respectful and inclusive
- Welcome newcomers
- Focus on constructive feedback
- Assume good intentions
## License
By contributing, you agree that your contributions will be licensed under the MIT License.
## Recognition
Contributors will be recognized in:
- GitHub contributors list
- Release notes (for significant contributions)
- README.md (for major features)
Thank you for contributing! 🎉