Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion cli/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
10 changes: 9 additions & 1 deletion cli/src/prescale_cli/commands/mcp.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from __future__ import annotations

import importlib.util
import os

import click
Expand All @@ -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)
Expand Down
18 changes: 18 additions & 0 deletions cli/tests/test_mcp.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Loading