name: Tests # fastmcp-feedback declares fastmcp>=2.12.2,<5, so every version family in # that range gets the full suite. A user on PyPI gets the newest FastMCP the # range allows, not what uv.lock pins, which is how 2026.01.12.1 shipped with # composition broken on 2.14 and 4.x without anyone noticing. on: push: pull_request: workflow_dispatch: schedule: # Weekly, so a new FastMCP release is caught even when nobody pushes - cron: '17 9 * * 1' jobs: test: runs-on: ubuntu-latest timeout-minutes: 15 strategy: fail-fast: false matrix: fastmcp: ['==2.12.2', '==2.14.3', '>=3.3,<4', '>=4,<5'] steps: - uses: actions/checkout@v4 - uses: astral-sh/setup-uv@v6 with: python-version: '3.13' - name: Install against fastmcp${{ matrix.fastmcp }} run: | uv venv uv pip install -e ".[dev]" "fastmcp${{ matrix.fastmcp }}" uv pip show fastmcp | grep -i '^version' - name: Lint run: uv run --no-sync ruff check src/ examples/ tests/_compat.py tests/unit/test_instrumentation.py - name: Test run: uv run --no-sync pytest -q --no-cov # Newest FastMCP with no ceiling. Allowed to fail: it exists to say # "a new major version is out and here is what breaks" before users do. canary: runs-on: ubuntu-latest timeout-minutes: 15 continue-on-error: true steps: - uses: actions/checkout@v4 - uses: astral-sh/setup-uv@v6 with: python-version: '3.13' - name: Install newest FastMCP, ignoring our ceiling run: | uv venv uv pip install fastmcp "sqlalchemy[asyncio]" aiosqlite pydantic \ pytest pytest-asyncio pytest-cov pytest-mock pytest-html uv pip install --no-deps -e . uv pip show fastmcp | grep -i '^version' - name: Test run: uv run --no-sync pytest -q --no-cov