jlab-mcp
The jlab-mcp server enables Claude Code to execute Python code with GPU access on SLURM HPC clusters or local machines by orchestrating JupyterLab instances and managing notebook-based sessions.
Session Management
start_new_session: Submit a SLURM job (or local subprocess), start a new IPython kernel, and create a fresh notebookshutdown_session: Stop the kernel and cancel the associated SLURM jobSLURM jobs persist across Claude Code restarts, allowing long-running computations without interruption
Notebook Workflows
start_session_resume_notebook: Re-attach to an existing notebook and re-execute all cells to restore kernel statestart_session_continue_notebook: Fork an existing notebook into a new file with a fresh kernel, without re-executing cells
Code Execution & Editing
execute_code: Run Python code in an active kernel and append it as a new cell, capturing outputsedit_cell: Modify an existing cell's source, re-execute it, and update its outputs (supports negative indexing)add_markdown: Insert markdown documentation cells into the notebook
Other Features
Works in both SLURM cluster mode (auto-detected via
sbatch) and local mode for laptops/workstationsResource monitoring for CPU, memory, and GPU usage on compute nodes
Highly configurable via environment variables (partitions, GPU resources, time limits, modules)
Uses project-specific
.venvdirectories for dependency management
Enables the execution of Python code on GPU compute nodes by managing JupyterLab instances and IPython kernels within a SLURM-managed environment.
Allows for the addition of Markdown cells to notebooks to provide documentation and structure alongside executed code.
Provides tools for executing Python code, managing session kernels, and manipulating notebook cells on high-performance compute clusters.
Supports GPU-accelerated computing workloads by facilitating the use of PyTorch on compute nodes allocated via job schedulers.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@jlab-mcpTrain a PyTorch model on a GPU node and display the training loss"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
jlab-mcp
A Model Context Protocol (MCP) server that enables Claude Code to execute Python code on GPU compute nodes via JupyterLab running on a SLURM cluster.
Inspired by and adapted from goodfire-ai/scribe, which provides notebook-based code execution for Claude. This project adapts that approach for HPC/SLURM environments where GPU resources are allocated via job schedulers.
Architecture
Claude Code
↕ stdio
MCP Server
↕ HTTP/WebSocket
JupyterLab (SLURM compute node or local subprocess) ← one server, many kernels
↕
IPython Kernels (GPU access)JupyterLab runs either on a SLURM compute node (HPC clusters) or as a local subprocess (laptops/workstations). The server process is decoupled from the MCP server and keeps running across Claude Code sessions. It can be started two ways:
From Claude (recommended): the agent calls the
start_serverMCP tool, which asks you once whether to run on SLURM or locally (and, for SLURM, the job walltime and resources), launchesjlab-mcp startin the background (bootstrapping a bare project withuv init/uv addif needed), then monitors startup withwait_for_serverand tells you when it's ready.Manually: run
jlab-mcp startin a separate terminal.
All sessions create separate kernels on this shared server. Each project directory gets its own JupyterLab instance — the status file is scoped by a hash of the working directory where the server was started.
Related MCP server: Jupyter MCP Server
Local Mode
On machines without SLURM (laptops, workstations), jlab-mcp runs JupyterLab as a local subprocess.
How the mode is chosen:
Via the
start_serverMCP tool: on first use in a project it asks you (slurmorlocal) and saves the choice next to the project's status file (~/.jlab-mcp/servers/{name}-{hash}/run-mode). Passmodeexplicitly to change it later.Via the CLI (
jlab-mcp start): auto-detected — ifsbatchis on PATH, SLURM mode; otherwise local mode.The
JLAB_MCP_RUN_MODEenvironment variable overrides both:
export JLAB_MCP_RUN_MODE=local # force local mode
export JLAB_MCP_RUN_MODE=slurm # force SLURM modeIn local mode, jlab-mcp start runs in the foreground — press Ctrl+C to stop. The status file uses the same format as SLURM mode, so the MCP server works identically in both modes.
Setup
Zero-install (recommended)
The only prerequisites are Claude Code and uv. Drop this .mcp.json into any project directory — uvx fetches and runs jlab-mcp on demand (cached after the first run), no separate install step:
{
"mcpServers": {
"jlab-mcp": {
"command": "uvx",
"args": ["--from", "git+https://github.com/kdkyum/jlab-mcp.git", "jlab-mcp"]
}
}
}Start Claude Code in that directory and approve the MCP server when prompted. The first launch clones and builds the package, so it can take a little longer; pin a tag (git+...@v1.0.2) for reproducibility.
Pre-installed alternative
For faster MCP startup (or offline login nodes), install the CLI once and reference it directly:
uv tool install git+https://github.com/kdkyum/jlab-mcp.gitThe SLURM job activates .venv in the current working directory. If the project has no environment yet (e.g. a fresh directory with just .mcp.json), start_server bootstraps it automatically (uv init --bare + uv add jupyterlab ipykernel matplotlib numpy). To set it up manually, or to add GPU-enabled torch:
cd /shared/fs/my-project
uv venv
uv pip install jupyterlab ipykernel matplotlib numpy
uv pip install torch --index-url https://download.pytorch.org/whl/cu126 # NVIDIA GPUs
# AMD GPUs (e.g. MI300A): use the ROCm wheels instead
# uv pip install torch --index-url https://download.pytorch.org/whl/rocm6.3Usage
Option A: Let Claude manage the server
Just start Claude Code in your project directory and ask it to run something in a notebook. When no server is running, the agent calls start_server (asking you SLURM vs local on first use), waits in the background via wait_for_server, and reports when JupyterLab is ready. To stop the server, ask Claude or run jlab-mcp stop.
Option B: Manual CLI
1. Start the compute node
In a separate terminal, start the SLURM job:
jlab-mcp start # uses default time limit (4h)
jlab-mcp start 24:00:00 # 24 hour time limit
jlab-mcp start 1-00:00:00 # 1 dayThis submits the job and waits until JupyterLab is ready:
SLURM job 24215408 submitted, waiting in queue...
Job running on ravg1011, JupyterLab starting...
JupyterLab ready at http://ravg1011:184322. Use Claude Code
In another terminal, start Claude Code. The MCP server connects to the running JupyterLab automatically.
3. Stop when done
jlab-mcp stopCLI Commands
Command | Description |
| Start JupyterLab and wait until ready. In SLURM mode, submits a job and polls until the server responds. In local mode, spawns a subprocess and blocks in the foreground. Optional TIME overrides |
| Stop JupyterLab. In SLURM mode, runs |
| Poll the status file from another terminal until the server is ready (up to 10 min). Prints state transitions ( |
| Print server state, mode, hostname, port, and whether the process/job is alive. Lists active kernels with execution state and last activity time. Queries GPU memory and utilization via |
| Run MCP server (stdio transport, used by Claude Code — not run manually) |
All commands accept --debug to enable verbose logging (status file reads, SLURM parameters, health check attempts, connection file paths) on stderr.
The SLURM job survives Claude Code restarts. You only need to run jlab-mcp start once per work session.
Configuration
All settings are configurable via environment variables. No values are hardcoded for a specific cluster.
Environment Variable | Default | Description |
|
| Base working directory |
|
| Notebook storage (relative to cwd) |
| cwd | JupyterLab root directory (what the file browser sees) |
|
| SLURM job logs |
|
| Per-project status directory (auto-derived from cwd) |
|
| Connection info files |
|
| SLURM partition |
|
| SLURM generic resource |
|
| CPUs per task |
|
| Memory in MB |
|
| Wall clock time limit |
|
| Address JupyterLab binds to on the compute node. Default listens on all interfaces and advertises the node's |
| (empty) | Space-separated modules to load (e.g. |
|
| Seconds |
|
| Seconds to wait for JupyterLab once the job is running. On timeout the job is cancelled |
|
| Port range lower bound |
|
| Port range upper bound |
| (auto) |
|
|
| Address JupyterLab binds to in local mode. Default listens on all interfaces (UI reachable from other hosts / a container host); the same-host MCP server still connects over loopback. Set |
Example: Cluster with A100 GPUs and CUDA module
export JLAB_MCP_SLURM_PARTITION=gpu1
export JLAB_MCP_SLURM_GRES=gpu:a100:1
export JLAB_MCP_SLURM_CPUS=18
export JLAB_MCP_SLURM_MEM=125000
export JLAB_MCP_SLURM_TIME=1-00:00:00
export JLAB_MCP_SLURM_MODULES="cuda/12.6"Claude Code Integration
Use the zero-install .mcp.json from Setup, or — with the CLI pre-installed — reference the binary directly in ~/.claude.json or a project .mcp.json:
{
"mcpServers": {
"jlab-mcp": {
"command": "jlab-mcp"
}
}
}No env block is needed: on first use the agent surveys the cluster (sinfo) and asks you for walltime and resources, saving the choices per project. An env block with JLAB_MCP_* variables still works to pin cluster-specific defaults (e.g. JLAB_MCP_SLURM_MODULES for a CUDA module).
The MCP server uses the working directory to find .venv for the compute node. Claude Code launches from your project directory, so it picks up the right venv automatically.
MCP Tools
Tool | Description |
| Launch the JupyterLab server in the background (spawns |
| Monitor server startup (bootstrap, queue wait, health check) with MCP progress keepalives; returns when the server is ready, errored, or timed out. Auto-resumes a lapsed SLURM queue wait |
| Start kernel on shared server, create empty notebook (never overwrites — duplicate names get |
| Open an existing notebook, reusing its live kernel if one exists (state preserved); otherwise starts a fresh kernel. Returns cell contents |
| Insert new code cell and execute it (supports positional insertion) |
| Edit code cell source only, no execution (clears stale outputs) |
| Run existing cell without modifying its source |
| Add markdown cell to notebook (supports positional insertion) |
| Edit an existing markdown cell's content |
| Delete a cell (code or markdown) by index |
| Run code on a utility kernel (no notebook save, no session state) |
| Interrupt running execution without shutting down the session |
| Stop kernel (SLURM job stays alive) |
| Lightweight health check — verify JupyterLab is reachable (no kernel needed) |
| Check CPU, memory, and GPU usage on the compute node (no session needed) |
Resource: jlab-mcp://server/status — returns shared server info and active sessions.
Session Lifecycle
start_new_notebook: Creates a new kernel and a new notebook. Any previously running kernels/sessions are shut down (one active session at a time)start_notebook: Opens an existing notebook. If a session with a live kernel already exists for it, that session is returned with all state preserved; otherwise a fresh kernel is startedRestart kernel:
shutdown_session+start_notebook(same_path)= fresh kernel on same notebookshutdown_session: Kills the kernel only. The SLURM job keeps running.SLURM job dies: Next tool call returns an error pointing the agent at
start_server(or runjlab-mcp startmanually).
Testing
# Unit tests (no SLURM needed)
uv run python -m pytest tests/ --ignore=tests/test_tools.py -v
# Integration tests (requires running `jlab-mcp start` first)
uv run python -m pytest tests/test_tools.py -v -s --timeout=600Acknowledgments
This project is inspired by goodfire-ai/scribe, which provides MCP-based notebook code execution for Claude. The tool interface design, image resizing approach, and notebook management patterns are adapted from scribe for use on HPC/SLURM clusters.
License
MIT
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseBqualityDmaintenanceA server that provides Model Control Protocol (MCP) tools for High Performance Computing, designed to integrate with Large Language Models in IDEs like Cursor and VSCode for debugging and other HPC tasks.13MIT
- AlicenseAqualityDmaintenanceAI-powered MCP server for connecting and managing Jupyter Notebooks. Enables interactive code execution, multi-notebook management, and multimodal output for data analysis, visualization, and machine learning.129MIT

globus-mcpofficial
AlicenseAqualityCmaintenanceMCP server enabling LLMs to manage Globus data transfers and compute tasks.1011Apache 2.0- Flicense-qualityAmaintenanceAn MCP server for monitoring and managing multi-cluster Slurm GPU jobs, enabling AI agents to execute commands, check allocations, and explore logs across HPC clusters.1
Related MCP Connectors
MCP server for AI dialogue using various LLM models via AceDataCloud
MCP server providing access to the Scorecard API to evaluate and optimize LLM systems.
MCP server for MiniMax H3 multimodal video generation
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/kdkyum/jlab-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server