Files
unraid-mcp/docs/PUBLISHING.md

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

  1. PyPI Account: Create accounts on both:

  2. API Tokens: Generate API tokens for automated publishing:

  3. 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:

  1. Increment version number in pyproject.toml
  2. Delete old dist files and rebuild

Missing Dependencies

If installation fails due to missing dependencies:

  1. Check that all dependencies are in pyproject.toml dependencies section
  2. Ensure dependency version constraints are correct
  3. Test in a clean virtual environment

Import Errors After Installation

If the package installs but imports fail:

  1. Verify package structure in wheel: unzip -l dist/*.whl
  2. Check that __init__.py files exist in all package directories
  3. Ensure packages = ["unraid_mcp"] in [tool.hatch.build.targets.wheel]

Resources