From a157ec73db0cebf78a4922b1cce50d273b2a73bf Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 2 Nov 2026 06:53:50 +0000 Subject: [PATCH] fix(mcp): pin mcp below 2 and say when the installed mcp is unsupported --- .github/workflows/ci.yml | 2 +- CHANGELOG.md | 8 ++++++++ cli/pyproject.toml | 2 +- cli/src/prescale_cli/commands/mcp.py | 10 +++++++++- cli/tests/test_mcp.py | 18 ++++++++++++++++++ 5 files changed, 37 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 90c5955..93953f1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,7 +23,7 @@ jobs: - name: Install run: | python -m pip install --upgrade pip - pip install -e "cli[dev]" ruff + pip install -e "cli[dev,mcp]" ruff - name: Ruff run: ruff check cli/src diff --git a/CHANGELOG.md b/CHANGELOG.md index 102df7e..0240859 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## Unreleased + +### Fixed +- **`prescale mcp` works on a fresh install again.** `pip install 'prescale[mcp]'` picked up the new + mcp 2.x, which renamed the server class PreScale uses, so the MCP server wouldn't start and told + you to install the extra you already had. The extra now installs mcp 1.x, and if an unsupported + mcp is already installed, `prescale mcp` says so and shows the command that fixes it. + ## 1.1.3 — 2026-10-22 ### Added diff --git a/cli/pyproject.toml b/cli/pyproject.toml index c72a9f8..bf467a3 100644 --- a/cli/pyproject.toml +++ b/cli/pyproject.toml @@ -35,7 +35,7 @@ dependencies = [ [project.optional-dependencies] mcp = [ - "mcp>=1.0", + "mcp>=1.0,<2", # 2.x renamed FastMCP; see mcp_server.py ] dev = [ "pytest>=7.0.0", diff --git a/cli/src/prescale_cli/commands/mcp.py b/cli/src/prescale_cli/commands/mcp.py index 74177e7..80e5904 100644 --- a/cli/src/prescale_cli/commands/mcp.py +++ b/cli/src/prescale_cli/commands/mcp.py @@ -2,6 +2,7 @@ from __future__ import annotations +import importlib.util import os import click @@ -28,7 +29,14 @@ def mcp(allow_hosts: tuple[str, ...]) -> None: """ try: from prescale_cli.mcp_server import serve - except ImportError: + except ImportError as exc: + if importlib.util.find_spec("mcp") is not None: + # Installed, but a version we can't use (mcp 2.x renamed FastMCP). + err.print("[red]Error:[/red] the installed mcp package isn't supported:") + err.print(f" {exc}", markup=False) + err.print("Install a supported version with:") + err.print(" pip install 'mcp>=1.0,<2'", markup=False) + raise SystemExit(1) err.print("[red]Error:[/red] MCP support needs the optional extra. Install it with:") err.print(" pip install 'prescale[mcp]'", markup=False) raise SystemExit(1) diff --git a/cli/tests/test_mcp.py b/cli/tests/test_mcp.py index 751ad70..98e3898 100644 --- a/cli/tests/test_mcp.py +++ b/cli/tests/test_mcp.py @@ -135,7 +135,25 @@ def test_mcp_command_without_extra_gives_correct_install_hint(monkeypatch): # simulate the optional extra not being installed monkeypatch.setitem(sys.modules, "prescale_cli.mcp_server", None) + monkeypatch.setattr("importlib.util.find_spec", lambda name: None) res = CliRunner().invoke(cli, ["mcp"]) assert res.exit_code == 1 # the [mcp] must survive (rich must not eat it as markup) assert "prescale[mcp]" in res.stderr + + +def test_mcp_command_with_unsupported_mcp_says_so(monkeypatch): + import importlib.util + import sys + + from click.testing import CliRunner + + from prescale_cli.main import cli + + # mcp is installed, but importing the server fails (e.g. mcp 2.x renamed FastMCP) + monkeypatch.setitem(sys.modules, "prescale_cli.mcp_server", None) + monkeypatch.setattr(importlib.util, "find_spec", lambda name: object()) + res = CliRunner().invoke(cli, ["mcp"]) + assert res.exit_code == 1 + assert "isn't supported" in res.stderr + assert "mcp>=1.0,<2" in res.stderr