5.4 KiB
Publishing Guide for unraid-mcp
This guide covers how to publish unraid-mcp to PyPI so it can be installed via uvx or pip from anywhere.
Prerequisites
-
PyPI Account: Create accounts on both:
-
API Tokens: Generate API tokens for automated publishing:
-
Save Tokens Securely:
# Add to ~/.pypirc (never commit this file!) cat > ~/.pypirc << 'EOF' [distutils] index-servers = pypi testpypi [pypi] username = __token__ password = pypi-YOUR-API-TOKEN-HERE [testpypi] username = __token__ password = pypi-YOUR-TEST-API-TOKEN-HERE repository = https://test.pypi.org/legacy/ EOF chmod 600 ~/.pypirc # Secure the file
Version Management
Before publishing, update the version in pyproject.toml:
[project]
version = "0.2.1" # Follow semantic versioning: MAJOR.MINOR.PATCH
Semantic Versioning Guide:
- MAJOR (1.0.0): Breaking changes
- MINOR (0.2.0): New features (backward compatible)
- PATCH (0.2.1): Bug fixes (backward compatible)
Publishing Workflow
1. Clean Previous Builds
# Remove old build artifacts
rm -rf dist/ build/ *.egg-info/
2. Run Quality Checks
# Lint and format code
uv run ruff check unraid_mcp/
uv run ruff format unraid_mcp/
# Type check
uv run ty check unraid_mcp/
# Run tests
uv run pytest
# Check coverage
uv run pytest --cov=unraid_mcp --cov-report=html
3. Build the Package
# Build both wheel and source distribution
uv run python -m build
This creates:
dist/unraid_mcp-VERSION-py3-none-any.whl(wheel)dist/unraid_mcp-VERSION.tar.gz(source distribution)
4. Validate the Package
# Check that the package meets PyPI requirements
uv run twine check dist/*
Expected output: PASSED for both files.
5. Test on Test PyPI (IMPORTANT!)
Always test on Test PyPI first:
# Upload to Test PyPI
uv run twine upload --repository testpypi dist/*
# Test installation from Test PyPI
uvx --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ unraid-mcp-server
# Or with pip in a test environment
pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ unraid-mcp
Note: --extra-index-url https://pypi.org/simple/ is needed because dependencies come from production PyPI.
6. Publish to PyPI (Production)
Once testing passes:
# Upload to production PyPI
uv run twine upload dist/*
7. Verify Installation
# Install and run from PyPI using uvx (no installation required!)
uvx unraid-mcp-server --help
# Or install globally
uv tool install unraid-mcp
# Or install in a project
uv add unraid-mcp
Post-Publishing Checklist
- Create a GitHub Release with the same version tag
- Update CHANGELOG.md with release notes
- Test installation on a fresh machine
- Update documentation if API changed
- Announce release (if applicable)
Running from Any Machine with uvx
Once published to PyPI, users can run the server without installing:
# Run directly with uvx (recommended)
uvx unraid-mcp-server
# Or with custom environment variables
UNRAID_API_URL=https://your-server uvx unraid-mcp-server
Benefits of uvx:
- No installation required
- Automatic virtual environment management
- Always uses the latest version (or specify version:
uvx unraid-mcp-server@0.2.0) - Clean execution environment
Automation with GitHub Actions (Future)
Consider adding .github/workflows/publish.yml:
name: Publish to PyPI
on:
release:
types: [published]
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v4
- name: Build package
run: uv run python -m build
- name: Publish to PyPI
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
run: uv run twine upload dist/*
Tip: Consider using PyPI Trusted Publishing instead of API token secrets. Trusted Publishing uses OpenID Connect (OIDC) to authenticate directly from GitHub Actions without storing long-lived secrets.
Troubleshooting
"File already exists" Error
PyPI doesn't allow re-uploading the same version. Options:
- Increment version number in
pyproject.toml - Delete old dist files and rebuild
Missing Dependencies
If installation fails due to missing dependencies:
- Check that all dependencies are in
pyproject.tomldependenciessection - Ensure dependency version constraints are correct
- Test in a clean virtual environment
Import Errors After Installation
If the package installs but imports fail:
- Verify package structure in wheel:
unzip -l dist/*.whl - Check that
__init__.pyfiles exist in all package directories - Ensure
packages = ["unraid_mcp"]in[tool.hatch.build.targets.wheel]