Skip to main content
Glama
qtalen

jupyter-kernel-mcp

by qtalen
README.md
> **I share an in-depth data science and AI project practice every month. Visit and subscribe to https://www.dataleadsfuture.com**
>

# jupyter-mcp-kernel

An MCP (Model Context Protocol) server that connects **directly** to a Jupyter kernel via ZMQ — no JupyterLab or Notebook server required.

Enable your AI assistant to read, create, edit, execute, and manage Jupyter Notebooks as MCP tools.

---

## Architecture

```
┌──────────────┐     stdio      ┌──────────────────┐      ZMQ      ┌────────────────┐
│  AI Agent    │ ◄────────────► │ jupyter-mcp-     │ ◄──────────► │  Jupyter IPykernel  │
│  (OpenCode)  │   MCP tools    │ kernel server    │              │  (python3)     │
└──────────────┘                └──────────────────┘              └────────────────┘
                                      │
                                ┌─────┴──────┐
                                │  .ipynb     │
                                │  (on disk)  │
                                └────────────┘
```

The server communicates with the kernel over ZMQ channels (iopub, shell, stdin, control) and persists notebook files to disk after every modification.

---

## Prerequisites

- Python ≥ 3.10
- `ipykernel` installed (so the kernel can start). If not sure:
  ```bash
  python -m ipykernel install --user
  ```
- `uv` (recommended) or `pip`

---

## Installation

### Option A: Install from GitHub (recommended for end users)

```bash
uv tool install git+https://github.com/qtalen/jupyter-mcp-kernel.git
```

This makes the `jupyter-mcp-kernel` command available globally (managed by `uv`).

### Option B: Install from local source (for development)

```bash
git clone https://github.com/qtalen/jupyter-mcp-kernel.git
cd jupyter-mcp-kernel
uv tool install --path . jupyter-mcp-kernel
```

### Option C: Install via pip

```bash
pip install git+https://github.com/qtalen/jupyter-mcp-kernel.git
```

---

## Register with OpenCode

Add the following `mcp` entry to your project's `opencode.json`:

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "jupyter": {
      "type": "local",
      "command": ["jupyter-mcp-kernel", "--cell-timeout", "7200"],
      "enabled": true,
      "timeout": 7200000
    }
  }
}
```

Then restart OpenCode. The 8 MCP tools will appear automatically.

---

## Available Tools

All tools are registered as `@mcp.tool()` and are callable by your AI agent once the MCP server is connected.

### 1. `connect_to_jupyter`

| Item | Value |
|------|-------|
| **Description** | Start (or reuse) a Jupyter kernel. Must be called before any other operation. |
| **Parameters** | `kernel_name` (str, default `"python3"`) — the kernel spec name |
| **Returns** | `str` — confirmation message |

### 2. `use_notebook`

| Item | Value |
|------|-------|
| **Description** | Open an existing `.ipynb` file, or create a new one if it doesn't exist. Attaches the notebook to the current session. |
| **Parameters** | `path` (str) — file path; `kernel_name` (str, default `"python3"`) |
| **Returns** | `str` — path and cell count |

### 3. `read_notebook`

| Item | Value |
|------|-------|
| **Description** | List all cells. In simple mode, returns a TSV summary (index, type, preview, output count). In detailed mode, returns full source + outputs for every cell. |
| **Parameters** | `detailed` (bool, default `False`) |
| **Returns** | `list[TextContent | ImageContent]` — per-cell content, including embedded PNG images |

### 4. `read_cell`

| Item | Value |
|------|-------|
| **Description** | Read a single cell's source code and its outputs. |
| **Parameters** | `cell_index` (int, default `0`) |
| **Returns** | `list[TextContent | ImageContent]` — source + outputs (images are returned as inline base64 PNG) |

### 5. `insert_cell`

| Item | Value |
|------|-------|
| **Description** | Insert a new code or markdown cell at a specified index. |
| **Parameters** | `source` (str) — cell content; `index` (int, default `-1` = append); `cell_type` (str, `"code"` or `"markdown"`) |
| **Returns** | `str` — confirmation message |

### 6. `edit_cell_source`

| Item | Value |
|------|-------|
| **Description** | Find and replace text in an existing cell's source. Clears outputs. |
| **Parameters** | `cell_index` (int); `old_string` (str); `new_string` (str) |
| **Returns** | `str` — confirmation or error |

### 7. `delete_cell`

| Item | Value |
|------|-------|
| **Description** | Remove a cell by index. |
| **Parameters** | `cell_index` (int) |
| **Returns** | `str` — confirmation |

### 8. `execute_cell`

| Item | Value |
|------|-------|
| **Description** | Execute a code cell in the open notebook. Supports long execution with timeout and progress reporting. Results are saved back to the `.ipynb` file. |
| **Parameters** | `cell_index` (int); `timeout_seconds` (int or None, default: `--cell-timeout` CLI value); `progress_interval` (int, default `5`, set to `0` to disable progress) |
| **Returns** | `list[TextContent | ImageContent]` — stdout/stderr text, error tracebacks, images, and a final status message (`[COMPLETED in Xs]` / `[TIMEOUT after Xs]` / `[CANCELLED]`) |

### 9. `execute_code`

| Item | Value |
|------|-------|
| **Description** | Execute arbitrary Python code directly on the kernel (outside the notebook context). Useful for quick experiments or inspection. |
| **Parameters** | `code` (str); `timeout` (int, default `60`) |
| **Returns** | `list[TextContent | ImageContent]` — same output types as `execute_cell` |

---

## Typical Workflow

A typical AI-driven notebook session follows these steps:

```
connect_to_jupyter(kernel_name="python3")
  → "Kernel ready — python3"

use_notebook(path="notebooks/my_analysis.ipynb")
  → "Using notebook: C:/.../my_analysis.ipynb (0 cells)"

insert_cell(source="# My Analysis\n\n## Objective\n...", index=0, cell_type="markdown")
  → "Inserted markdown cell at index 0"

insert_cell(source="import pandas as pd\ndf = pd.read_csv('data.csv')", index=1)
  → "Inserted code cell at index 1"

execute_cell(cell_index=1)
  → [...] + "[COMPLETED in 2s]"

read_cell(cell_index=1)
  → Shows source + any output

edit_cell_source(cell_index=1, old_string="data.csv", new_string="data_v2.csv")
  → "Cell 1 updated: replaced 1 occurrence of 8 → 11 chars"

execute_cell(cell_index=1)
  → [...] + "[COMPLETED in 3s]"

delete_cell(cell_index=2)
  → "Deleted cell 2 (code)"
```

---

## CLI Options

```
jupyter-mcp-kernel [--cell-timeout SECONDS]
```

| Option | Default | Description |
|--------|---------|-------------|
| `--cell-timeout` | `7200` | Default execution timeout per cell (seconds). Can be overridden per-call via `execute_cell(timeout_seconds=...)`. |

---

## Troubleshooting

### Kernel fails to start

- Ensure `ipykernel` is installed: `python -m ipykernel install --user`
- Verify the kernel name. Run `jupyter kernelspec list` to see available kernels.
- Check for proxy issues. The server automatically adds `localhost,127.0.0.1` to `NO_PROXY`.

### No tools appear in OpenCode

- Confirm `jupyter-mcp-kernel` is on your PATH: `jupyter-mcp-kernel --help`
- Check `opencode.json` syntax and path.
- Restart OpenCode entirely after configuration changes.

### Cell execution hangs indefinitely

- The default timeout is 7200s (2h). Use `execute_cell(timeout_seconds=120)` for shorter tasks.
- The kernel may be stuck. Use `execute_cell(progress_interval=5)` to see progress updates.
- OpenCode can cancel execution via SIGINT → the server will interrupt the kernel.

### Windows-specific

- The server registers `SIGBREAK` (Ctrl+Break) for graceful shutdown on Windows.
- Paths with spaces are supported if quoted correctly in `opencode.json`.

---

## License

MIT

TDQS

B3.2/5.0

Scored across 9 tools

Disambiguation4/5

Tools have mostly distinct purposes, but 'execute_cell' and 'execute_code' could confuse agents due to similar names despite different contexts. Other tools are clearly separated.

Naming Consistency4/5

Most tools follow a verb_noun pattern (e.g., delete_cell, insert_cell), but 'connect_to_jupyter' and 'edit_cell_source' deviate slightly. Overall consistent.

Tool Count5/5

9 tools is well-scoped for a Jupyter kernel server, covering connection, notebook management, cell operations, and code execution without excess.

Completeness3/5

Covers core CRUD for cells and execution, but missing kernel management tools like restart or interrupt, and no explicit save/close functionality.

Maintenance

ActivityInactive
ResponsivenessNo issues