# ExMCP Development Guide
This guide covers everything you need to know for developing, testing, and contributing to ExMCP.
## Table of Contents
1. [Development Setup](#development-setup)
2. [Code Quality Tools](#code-quality-tools)
3. [Testing Strategy](#testing-strategy)
4. [Test Process Cleanup](#test-process-cleanup)
5. [Contributing](#contributing)
6. [Release Process](#release-process)
## Development Setup
### Prerequisites
- Elixir 1.14+ and Erlang/OTP 25+
- Git with hooks support
### Initial Setup
```bash
# Clone the repository
git clone https://github.com/azmaveth/ex_mcp.git
cd ex_mcp
# Install dependencies
mix deps.get
# Install git hooks
mix git_hooks.install
# Verify setup
mix compile --warnings-as-errors && mix credo
```
### Essential Development Commands
```bash
# Dependencies and compilation
mix deps.get # Install dependencies
mix compile # Compile the project
mix compile --warnings-as-errors # Compile with strict warnings
# Code quality
mix format # Format code (required before committing)
mix credo # Static code analysis
mix dialyzer # Type checking (run after significant changes)
mix sobelow --skip # Security analysis
# Testing
mix test # Run all tests
mix test test/ex_mcp/protocol_test.exs # Run specific test file
mix coveralls.html # Generate coverage report
MIX_ENV=test mix compile # Compile for test environment
# Documentation
mix docs # Generate documentation (also verifies rewritten moduledocs + guides render)
iex -S mix # Start interactive shell with project loaded
# After doc or example changes, re-verify key snippets and the getting-started demo:
# mix run -e '...' (see DOCS_EXAMPLES_AUDIT_PLAN.md for example verifiers)
# elixir examples/getting_started/demo_client.exs
# mix examples.getting_started # fast alias (see examples/README.md)
```
## Code Quality Tools
ExMCP uses a comprehensive set of code quality tools to ensure maintainable, reliable code:
### Formatter
- **Tool**: Elixir's built-in code formatter
- **Usage**: `mix format`
- **Purpose**: Consistent code formatting across the project
- **Required**: Yes, before every commit
### Credo
- **Tool**: Static code analysis
- **Usage**: `mix credo` or `mix credo --strict`
- **Purpose**: Code readability, consistency, and best practices
- **Configuration**: See `.credo.exs`
- **Thresholds**:
- Cyclomatic complexity max: 11
- Function length max: reasonable (enforced by review)
### Dialyzer
- **Tool**: Type checking and static analysis
- **Usage**: `mix dialyzer`
- **Purpose**: Find type inconsistencies and potential runtime errors
- **When to run**: After significant changes or before releases
- **PLT location**: `_dialyzer/` (gitignored)
### Sobelow
- **Tool**: Security analysis
- **Usage**: `mix sobelow --skip`
- **Purpose**: Identify security vulnerabilities
- **Focus**: Input validation, SQL injection, XSS prevention
### ExCoveralls
- **Tool**: Test coverage analysis
- **Usage**: `mix coveralls.html`
- **Purpose**: Ensure comprehensive test coverage
- **Target**: Aim for >80% coverage on core modules
### Git Hooks
- **Pre-commit**: Runs formatter, credo, and compile checks
- **Pre-push**: Runs full test suite
- **Setup**: Automatically configured with `make setup`
- **Bypass**: Use `--no-verify` only in emergencies
## Testing Strategy
ExMCP uses a sophisticated test tagging strategy for efficient test execution across different scenarios.
### Test Categories
#### Core Test Suites
```bash
# Fast unit tests (default, ~5s)
mix test.suite unit
# MCP specification compliance tests
mix test.suite compliance
# Integration tests with real components
mix test.suite integration
# CI-appropriate tests (excludes slow tests)
mix test.suite ci
# All tests including slow ones
mix test.suite all
```
#### Transport-Specific Tests
```bash
# BEAM transport tests
mix test --only beam
# HTTP transport tests (Streamable HTTP with SSE)
mix test --only http
# stdio transport tests
mix test --only stdio
```
#### Feature-Specific Tests
```bash
# Security and authentication tests
mix test --only security
# Progress notification tests
mix test --only progress
# Resource management tests
mix test --only resources
# Performance and benchmarking tests
mix test --only performance
```
#### Development Workflows
```bash
# Include normally excluded slow tests
mix test --include slow
# Skip integration tests for faster feedback
mix test --exclude integration
# Skip external dependencies
mix test --exclude external
# List all available tags
mix test.tags
```
### Test Organization
Tests follow a clear structure mirroring the source code:
```
test/
├── ex_mcp/ # Core module tests
│ ├── client/ # Client implementation tests
│ ├── server/ # Server implementation tests
│ ├── transport/ # Transport layer tests
│ └── protocol_test.exs # Protocol tests
├── integration/ # Cross-component integration tests
├── compliance/ # MCP specification compliance tests
└── support/ # Test helpers and utilities
```
### Test Patterns
#### Unit Tests
- Test individual functions and modules in isolation
- Use mocks for external dependencies
- Fast execution (typically <100ms per test)
- Tagged with `:unit` (default)
#### Integration Tests
- Test component interactions
- May use real external services or subprocess
- Slower execution
- Tagged with `:integration`
#### Compliance Tests
- Verify MCP specification adherence
- Test protocol message formats
- Cross-version compatibility
- Tagged with `:compliance`
#### Property-Based Tests
- Used for protocol encoding/decoding
- Input validation testing
- Edge case discovery
- Uses PropCheck library
### Writing Tests
Follow these patterns when writing tests:
```elixir
defmodule ExMCP.SomeModuleTest do
use ExUnit.Case, async: true # Use async: false for shared state
# Add appropriate tags
@moduletag :unit
@moduletag :some_feature
# Use descriptive test names
describe "function_name/2" do
test "handles valid input correctly" do
# Arrange
input = %{valid: "data"}
# Act
result = SomeModule.function_name(input, [])
# Assert
assert {:ok, expected} = result
end
test "returns error for invalid input" do
# Test error conditions
assert {:error, _reason} = SomeModule.function_name(nil, [])
end
end
end
```
## Test Process Cleanup
Tests that start servers can sometimes leave processes running if they crash. ExMCP provides several tools to clean up these stray processes:
### Automatic Cleanup
```bash
# Clean up before running tests (automatic with make test)
mix test.cleanup
# Manual cleanup with verbose output
mix test.cleanup --verbose
# Dry run to see what would be cleaned
mix test.cleanup --dry-run
# Skip automatic cleanup if needed
SKIP_TEST_CLEANUP=true mix test
```
### What Gets Cleaned
The cleanup tools will:
- Stop any Cowboy listeners from tests
- Kill registered test processes
- Free up commonly used test ports (8080-8085, 9000-9002)
- Clean up stray beam.smp processes from test runs
### Manual Process Investigation
If you encounter persistent process issues:
```bash
# Check for running beam processes
ps aux | grep beam
# Check for listening ports
lsof -i :8080-8085
# Kill specific processes if needed
pkill -f "beam.*test"
```
## Contributing
### Contribution Workflow
1. **Fork the repository** on GitHub
2. **Create a feature branch** from `master`:
```bash
git checkout -b feature/your-feature-name
```
3. **Make your changes** following the coding standards
4. **Run quality checks**:
```bash
make quality # Format, credo, compile checks
make test # Full test suite
```
5. **Commit your changes** with conventional commit messages:
```bash
git commit -m "feat: add new transport option"
git commit -m "fix: resolve connection timeout issue"
git commit -m "docs: update configuration examples"
```
6. **Push to your fork** and create a pull request
### Code Standards
#### Formatting and Style
- **Always run `mix format`** before committing
- Follow Elixir community conventions
- Use descriptive variable and function names
- Add appropriate documentation to public functions
#### Documentation
- Add `@doc` to all public functions
- Include examples in documentation when helpful
- Update guides when adding new features
- Ensure examples work with current codebase
#### Testing
- Write tests for all new functionality
- Maintain or improve test coverage
- Add appropriate test tags
- Test both success and error cases
#### Git Commit Messages
Follow [Conventional Commits](https://conventionalcommits.org/):
```
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
```
Types:
- `feat`: New features
- `fix`: Bug fixes
- `docs`: Documentation changes
- `test`: Test additions or modifications
- `refactor`: Code refactoring
- `perf`: Performance improvements
- `chore`: Maintenance tasks
### Pull Request Guidelines
#### Before Submitting
- [ ] All tests pass locally
- [ ] Code is formatted with `mix format`
- [ ] No credo warnings
- [ ] Documentation is updated if needed
- [ ] CHANGELOG.md is updated for user-facing changes
#### PR Description
Include:
- Clear description of the change
- Motivation and context
- Breaking changes (if any)
- Testing approach
- Related issues
### Code Review Process
1. **Automated checks** must pass (CI, formatting, tests)
2. **Manual review** by maintainers
3. **Feedback incorporation** and iteration
4. **Final approval** and merge
## Release Process
### Version Management
ExMCP follows [Semantic Versioning](https://semver.org/):
- **Patch** (`0.6.1`): Bug fixes, documentation updates
- **Minor** (`0.7.0`): New features, non-breaking changes
- **Major** (`1.0.0`): Breaking changes
### Release Checklist
#### Pre-Release
- [ ] All tests pass on CI
- [ ] Documentation is up to date
- [ ] CHANGELOG.md is updated
- [ ] Version is bumped in `mix.exs`
- [ ] Security audit passes
#### Release
- [ ] Tag release: `git tag vX.Y.Z`
- [ ] Push tag: `git push origin vX.Y.Z`
- [ ] GitHub release with changelog
- [ ] Publish to Hex: `mix hex.publish`
#### Post-Release
- [ ] Announce release
- [ ] Update documentation sites
- [ ] Close related issues/milestones
### Hotfix Process
For critical bugs in production releases:
1. Create hotfix branch from release tag
2. Apply minimal fix
3. Update version (patch bump)
4. Release immediately
5. Merge back to master
## Getting Help
### Development Questions
- **GitHub Discussions**: For general development questions
- **GitHub Issues**: For bug reports and feature requests
- **Code Review**: In pull requests
### Documentation
- **This guide**: Development setup and processes
- **[User Guide](guides/USER_GUIDE.md)**: Feature usage and examples
- **[Architecture Guide](ARCHITECTURE.md)**: Internal design decisions
- **[API Docs](https://hexdocs.pm/ex_mcp)**: Complete API reference
### Community
- **Elixir Forum**: For general Elixir questions
- **ExMCP Community**: Growing community of contributors and users
---
Thank you for contributing to ExMCP! Your contributions help make MCP implementation in Elixir more robust and accessible to the community.