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
48 changes: 26 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,41 +24,33 @@ This MCP is **not** just documentation or static code analysis. It is a **semant

3. **Minimal MCP Surface** - Exposes only what an LLM needs: Discovery, Description, Instantiation, Execution, and model persistence.

## 🛠️ Prerequisites

- **Python 3.10+**
- **pip** package manager

## 🛠️ Installation

### Virtual Environment Setup
### Zero-install via uvx (recommended)

It is recommended to use a virtual environment:
If you have [uv](https://github.com/astral-sh/uv) installed, no separate installation step is needed. Just update your MCP client config (see [Connecting from an LLM Client](#connecting-from-an-llm-client) below) and `uvx` will handle the rest automatically.

```bash
python3 -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
# Verify uv is available
uvx sktime-mcp --help
```

### Package Installation

Install from PyPI (recommended for users):
### pip

```bash
pip install sktime-mcp

# With all optional dependencies
# With optional extras (SQL, forecasting models, file formats)
pip install "sktime-mcp[all]"
```

For development (editable install from source):
### Development installation

```bash
pip install -e ".[dev]"
git clone https://github.com/sktime/sktime-mcp
cd sktime-mcp
python3 -m pip install -e ".[dev]"
```

For a more detailed first-time setup flow, including MCP server verification and troubleshooting, see [Beginner Setup](#-beginner-setup-firsttime-users).

## 🧭 Beginner Setup (First‑Time Users)

If you are new to sktime‑mcp or to MCP‑based workflows, this section provides a minimal starting point to help you verify that your setup is working correctly.
Expand Down Expand Up @@ -140,24 +132,36 @@ The server uses stdio transport by default, compatible with Claude Desktop, Clau
| Linux | `~/.config/claude/claude_desktop_config.json` |
| Windows | `%APPDATA%\Claude\claude_desktop_config.json` |

**With uvx (recommended — no prior install needed):**
```json
{
"mcpServers": {
"sktime": {
"command": "sktime-mcp"
"command": "uvx",
"args": ["sktime-mcp"]
}
}
}
```

If you are using a virtual environment, or if `sktime-mcp` is not on your `PATH`, point the client directly at the environment's Python executable — this ensures the correct packages are used:
**With optional extras:**
```json
{
"mcpServers": {
"sktime": {
"command": "uvx",
"args": ["sktime-mcp[forecasting,sql]"]
}
}
}
```

**With pip-installed package:**
```json
{
"mcpServers": {
"sktime": {
"command": "<project-root>/.venv/bin/python",
"args": ["-m", "sktime_mcp.server"]
"command": "sktime-mcp"
}
}
}
Expand Down
27 changes: 19 additions & 8 deletions docs/source/intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,14 @@ Get up and running in seconds. Use with **Claude Desktop**, **Cursor**, or any M

### 1. Install

**Zero-install via uvx (recommended):** if you have [uv](https://github.com/astral-sh/uv) installed, skip this step — uvx fetches and runs the package automatically when your MCP client starts.

```bash
# Install directly from PyPI (with all optional dependencies recommended)
pip install "sktime-mcp[all]"
# Or install explicitly with pip
pip install sktime-mcp
```

Alternatively, when contributing, use GitHub to install from source:
When contributing, install from source:

```bash
git clone https://github.com/sktime/sktime-mcp.git
Expand All @@ -61,13 +63,22 @@ source .venv/bin/activate
pip install -e ".[dev]"
```

### 2. Run
```bash
sktime-mcp
### 2. Connect (Claude Desktop / Claude Code Config)
Add this to your `claude_desktop_config.json`:

**With uvx (no prior install needed):**
```json
{
"mcpServers": {
"sktime": {
"command": "uvx",
"args": ["sktime-mcp"]
}
}
}
```

### 3. Connect (Claude Desktop Config)
Add this to your `claude_desktop_config.json`:
**With pip-installed package:**
```json
{
"mcpServers": {
Expand Down
56 changes: 44 additions & 12 deletions docs/source/user-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,31 +11,63 @@ Welcome to the **sktime-mcp** User Guide. This guide walks you through installin
Before you begin, ensure you have:

- **Python 3.10+** installed.
- **pip** package manager.
- A compatible MCP client (like **Claude Desktop**, **Cursor**, or compatible **VS Code extensions** like Cline).
- A compatible MCP client (like **Claude Desktop**, **Cursor**, or **VS Code with Copilot**).

### Installation

Install the package directly from the source. We recommend installing with all dependencies to unlock full functionality.
**Zero-install via uvx (recommended):** if you have [uv](https://github.com/astral-sh/uv) installed, no install step is needed. Just configure your MCP client (see below) and `uvx` handles everything automatically.

```bash
# Standard installation
pip install -e .
# Or install with pip
pip install sktime-mcp

# Recommended: Install with all optional extras (SQL, Forecasting, Files)
pip install -e ".[all]"
# With all optional extras (SQL, forecasting models, file formats)
pip install "sktime-mcp[all]"
```

### Running the Server
### MCP Client Configuration

Start the MCP server to begin listening for connections:
**With uvx (recommended — no prior install needed):**
```json
{
"mcpServers": {
"sktime": {
"command": "uvx",
"args": ["sktime-mcp"]
}
}
}
```

```bash
sktime-mcp
**With optional extras:**
```json
{
"mcpServers": {
"sktime": {
"command": "uvx",
"args": ["sktime-mcp[forecasting,sql]"]
}
}
}
```

*Or manually via Python:*
**With pip-installed package:**
```json
{
"mcpServers": {
"sktime": {
"command": "sktime-mcp"
}
}
}
```

### Running the Server manually

```bash
sktime-mcp

# Or via Python
python -m sktime_mcp.server
```

Expand Down
5 changes: 5 additions & 0 deletions src/sktime_mcp/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"""Allow `python -m sktime_mcp` as an alternative entry point."""

from sktime_mcp.server import main

main()
21 changes: 15 additions & 6 deletions src/sktime_mcp/runtime/executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
logger = logging.getLogger(__name__)


# Dynamically discover all available sktime demo datasets at import time.
# Dynamically discover all available sktime demo datasets on first access.
# This replaces the old hardcoded dictionary and automatically exposes every
# load_* function in sktime.datasets to the MCP server.
def _discover_demo_datasets() -> dict:
Expand All @@ -39,7 +39,15 @@ def _discover_demo_datasets() -> dict:
return {} # fallback: empty dict if sktime not installed


DEMO_DATASETS = _discover_demo_datasets()
_DEMO_DATASETS: dict | None = None


def _get_demo_datasets() -> dict:
"""Lazy singleton — discovers datasets only on first call."""
global _DEMO_DATASETS
if _DEMO_DATASETS is None:
_DEMO_DATASETS = _discover_demo_datasets()
return _DEMO_DATASETS


class Executor:
Expand Down Expand Up @@ -87,15 +95,16 @@ def instantiate(
# L-7: We can also add custom load_dataset functions here
def load_dataset(self, name: str) -> dict[str, Any]:
"""Load a demo dataset."""
if name not in DEMO_DATASETS:
demo_datasets = _get_demo_datasets()
if name not in demo_datasets:
return {
"success": False,
"error": f"Unknown dataset: {name}",
"available": list(DEMO_DATASETS.keys()),
"available": list(demo_datasets.keys()),
}

try:
module_path = DEMO_DATASETS[name]
module_path = demo_datasets[name]
parts = module_path.rsplit(".", 1)
module = __import__(parts[0], fromlist=[parts[1]])
loader = getattr(module, parts[1])
Expand Down Expand Up @@ -529,7 +538,7 @@ def instantiate_pipeline(

def list_datasets(self) -> list[str]:
"""List available demo datasets."""
return list(DEMO_DATASETS.keys())
return list(_get_demo_datasets().keys())

def load_data_source(self, config: dict[str, Any]) -> dict[str, Any]:
"""
Expand Down
9 changes: 5 additions & 4 deletions src/sktime_mcp/tools/codegen.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from typing import Any

from sktime_mcp.registry.interface import get_registry
from sktime_mcp.runtime.executor import DEMO_DATASETS
from sktime_mcp.runtime.executor import _get_demo_datasets
from sktime_mcp.runtime.handles import get_handle_manager


Expand Down Expand Up @@ -253,9 +253,10 @@ def export_code_tool(

# Optionally add fit/predict example
if include_fit_example:
# Resolve the dataset loader from DEMO_DATASETS
if dataset and dataset in DEMO_DATASETS:
module_path = DEMO_DATASETS[dataset]
# Resolve the dataset loader from demo datasets
_demo_datasets = _get_demo_datasets()
if dataset and dataset in _demo_datasets:
module_path = _demo_datasets[dataset]
module_parts = module_path.rsplit(".", 1)
loader_module = module_parts[0]
loader_func = module_parts[1]
Expand Down
Loading