universal-notebook-mcp
Provides tools for reading, editing, and executing Jupyter notebook cells, managing kernels, and running pipelines, enabling AI assistants to interact with Jupyter notebooks live.
Click on "Deploy 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., "@universal-notebook-mcp list the cells in my analysis notebook"
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.
universal-notebook-mcp
Run Jupyter notebooks from any AI editor. Gives your AI assistant full access to read, edit, and execute .ipynb files with live kernel output — without needing to open JupyterLab.
Works in Antigravity, Cursor, Windsurf, Claude Desktop, Claude Code, and any MCP-compatible tool. Works on Windows, macOS, and Linux.
Quick start
1. Install Python 3.10+
Skip this step if you already have Python 3.10 or later (python --version to check).
Download from python.org and run the installer. Make sure to check "Add Python to PATH" during setup.
Or with winget:
winget install Python.Python.3.11brew install python@3.11Or download from python.org.
# Debian / Ubuntu
sudo apt install python3.11 python3.11-pip
# Fedora / RHEL
sudo dnf install python3.11
# Arch
sudo pacman -S python2. Install the package
pip install universal-notebook-mcpOn macOS/Linux, if
pipmaps to Python 3.9, usepip3.11instead. On Windows,pipfrom the Python 3.11 installer works directly.
Verify it installed:
nb-mcp --help3. Add to your editor
Pick your editor below and paste the config. Replace the path with the folder that contains your notebooks.
⚠️ Use the real absolute path — MCP clients pass arguments as literal strings and do not expand editor variables like
${workspaceFolder}.Windows paths: use forward slashes or escape backslashes:
C:/Users/you/notebooksorC:\\Users\\you\\notebooks
Create .antigravity/mcp.json in your project folder:
{
"mcpServers": {
"notebook": {
"command": "nb-mcp",
"args": ["--workspace-root", "/absolute/path/to/notebooks"]
}
}
}Or go to Settings → MCP Servers and add the same block.
~/.cursor/mcp.json (global) or .cursor/mcp.json (per-project):
{
"mcpServers": {
"notebook": {
"command": "nb-mcp",
"args": ["--workspace-root", "/absolute/path/to/notebooks"]
}
}
}~/.codeium/windsurf/mcp_config.json:
{
"mcpServers": {
"notebook": {
"command": "nb-mcp",
"args": ["--workspace-root", "/absolute/path/to/notebooks"]
}
}
}Config file location:
Windows:
%APPDATA%\Claude\claude_desktop_config.jsonmacOS:
~/Library/Application Support/Claude/claude_desktop_config.jsonLinux:
~/.config/Claude/claude_desktop_config.json
{
"mcpServers": {
"notebook": {
"command": "nb-mcp",
"args": ["--workspace-root", "/absolute/path/to/notebooks"]
}
}
}claude mcp add notebook -- nb-mcp --workspace-root /absolute/path/to/notebooks4. Reload your editor and go
Your AI can now work with notebooks. Try:
"List the cells in my notebook" "Run cell 3 and show me the output" "Fix the error in cell 5 and re-run it"
Related MCP server: JupyterMCP
What it can do
Tool | What it does | |
📖 |
| See all cells (type, tags, first line) |
📖 |
| Read full source + saved outputs of a cell |
📖 |
| Read just the outputs (stream, result, error) |
📖 |
| Read notebook metadata (kernel, language, etc.) |
📖 |
| List all pipeline stage tags in the notebook |
✏️ |
| Edit a cell's source |
✏️ |
| Insert a new cell at any position |
✏️ |
| Delete a cell |
✏️ |
| Add or update cell tags and metadata |
✏️ |
| Update notebook-level metadata |
▶️ |
| Execute one cell and get its output |
▶️ |
| Execute a range of cells |
▶️ |
| Execute all cells |
▶️ |
| Execute all cells tagged with a stage name |
🔧 |
| Clear kernel state (variables, imports) |
🔧 |
| List all installed kernel environments |
🔧 |
| See which notebooks have a live kernel |
Kernel state persists across calls — variables and imports from one cell are available in the next, just like a normal Jupyter session.
Edits are checkpointed — every edit creates a timestamped backup (.checkpoint_<timestamp>.ipynb) before writing, so you can always roll back.
Troubleshooting
nb-mcp: command not found (or 'nb-mcp' is not recognized on Windows)
The install directory isn't on your PATH. Find where pip installed it:
# macOS / Linux
python3 -m site --user-scripts # or: which nb-mcp after activating your venv
# Windows (PowerShell)
python -c "import sys; print(sys.prefix + r'\Scripts')"Then either use the full path in your MCP config:
"command": "C:\\Users\\you\\AppData\\Local\\Programs\\Python\\Python311\\Scripts\\nb-mcp.exe"Or add the Scripts/bin directory to your PATH permanently.
ModuleNotFoundError when running a cell
The kernel doesn't have your packages installed. Register your environment:
pip install ipykernel
python -m ipykernel install --user --name myenv --display-name "My Env"Then restart the kernel via notebook_restart_kernel or ask your AI to switch kernels.
List available kernels:
jupyter kernelspec listWindows: path format in MCP config
Both of these work:
"C:/Users/you/notebooks" ✓ forward slashes
"C:\\Users\\you\\notebooks" ✓ escaped backslashesAvoid raw backslashes — they break JSON:
"C:\Users\you\notebooks" ✗ invalid JSONgit clone https://github.com/your-org/universal-notebook-mcp.git
cd universal-notebook-mcp
# macOS / Linux
pip3.11 install -e ".[dev]"
# Windows (PowerShell)
python -m pip install -e ".[dev]"Run the tests:
python -m pytest # all tests
python -m pytest -m "not integration" # unit tests only (no kernel needed)
python -m pytest -m integration -v # integration tests (needs ipykernel)Or use make targets on macOS/Linux:
make test # unit only
make test-all # unit + integration
make coverage # coverage report
make lint # ruff linterProject layout:
src/universal_notebook_mcp/
server.py ← MCP tool surface (17 tools, FastMCP, stdio)
notebook_adapter.py ← nbformat cell CRUD + checkpoint backups
kernel_session.py ← jupyter_client async kernel lifecycle
notebook_runner.py ← cell execution + output capture
tests/
conftest.py ← shared fixtures (mocked kernel, workspace)
fixtures/ ← simple.ipynb, pipeline.ipynb, error.ipynb
test_*.py ← 125 tests (116 unit + 9 integration)Security
All notebook paths are sandboxed to --workspace-root. Paths that escape it (e.g. ../secret.ipynb) or that aren't .ipynb files are rejected with an error.
License
MIT
Available Tools
17 toolsnotebook_delete_cellA
Delete the cell at the given index.
A timestamped backup is written first unless checkpoint=false.
Args: notebook_path: Path to the .ipynb file, relative to the workspace root. cell_index: Zero-based index of the cell to delete. checkpoint: Write a backup before deleting (default: true).
Inputs: cell_index (required), notebook_path (required), checkpoint. Returns: result
notebook_edit_cellA
Replace the source of a cell.
A timestamped .checkpoint_*.ipynb backup is written before the change unless checkpoint=false.
Args: notebook_path: Path to the .ipynb file, relative to the workspace root. cell_index: Zero-based index of the cell to edit. source: New source code or markdown text. checkpoint: Write a backup before editing (default: true).
Inputs: source (required), cell_index (required), notebook_path (required), checkpoint. Returns: result
notebook_edit_cell_metadataA
Merge a JSON object into a cell's metadata.
Useful for adding or removing pipeline stage tags: updates = '{"tags": ["preprocess"]}'
Args: notebook_path: Path to the .ipynb file, relative to the workspace root. cell_index: Zero-based index of the target cell. updates: JSON string with metadata keys to merge in. checkpoint: Write a backup before editing (default: true).
Inputs: updates (required), cell_index (required), notebook_path (required), checkpoint. Returns: result
notebook_edit_metadataA
Merge a JSON object into the top-level notebook metadata.
Args: notebook_path: Path to the .ipynb file, relative to the workspace root. updates: JSON string with top-level metadata keys to merge in. checkpoint: Write a backup before editing (default: true).
Inputs: updates (required), notebook_path (required), checkpoint. Returns: result
notebook_insert_cellA
Insert a new cell at the given position.
Cells at index and above are shifted down. To append after the last cell, pass index equal to the total number of cells.
Args: notebook_path: Path to the .ipynb file, relative to the workspace root. index: Position to insert at (0 = before first cell). source: Source code or text for the new cell. cell_type: 'code', 'markdown', or 'raw' (default: 'code'). checkpoint: Write a backup before editing (default: true).
Inputs: index (required), source (required), notebook_path (required), cell_type, +1 more. Returns: result
notebook_list_active_kernelsA
List notebooks that currently have a running kernel in this session.
Returns the absolute resolved paths of notebooks with live kernels.
Inputs: no named parameters. Returns: result
notebook_list_cellsA
List every cell in a notebook with its index, type, tags, and first line.
Call this first to understand the structure before reading or editing specific cells.
Args: notebook_path: Path to the .ipynb file, relative to the workspace root.
Inputs: notebook_path (required). Returns: result
notebook_list_kernelsA
List every Jupyter kernel spec installed on this machine.
Returns a dict of {kernel_name: display_name}. Use the kernel_name value as the kernel_name argument to execution tools.
If you get ModuleNotFoundError when running a cell, the kernel may not have your packages installed. Install the current virtualenv as a kernel: python -m ipykernel install --user --name myenv
Inputs: no named parameters. Returns: result
notebook_list_stagesA
List every pipeline stage tag present across the notebook's cells.
Pipeline stages are cell tags set in JupyterLab via View → Cell Toolbar → Tags (e.g. 'preprocess', 'train', 'evaluate'). Use notebook_run_pipeline to execute all cells in a named stage.
Args: notebook_path: Path to the .ipynb file, relative to the workspace root.
Inputs: notebook_path (required). Returns: result
notebook_read_cellA
Read the full source, type, tags, and saved outputs of a single cell.
Args: notebook_path: Path to the .ipynb file, relative to the workspace root. cell_index: Zero-based index of the cell (use notebook_list_cells to find it).
Inputs: cell_index (required), notebook_path (required). Returns: result
notebook_read_cell_outputA
Read the saved outputs of a code cell from the last time it was run.
Returns stream text, execute_result data, display_data, or error tracebacks. Note: outputs are empty until the cell has been executed at least once.
Args: notebook_path: Path to the .ipynb file, relative to the workspace root. cell_index: Zero-based index of a code cell.
Inputs: cell_index (required), notebook_path (required). Returns: result
notebook_read_metadataA
Read the top-level notebook metadata (kernelspec, language_info, etc.).
Args: notebook_path: Path to the .ipynb file, relative to the workspace root.
Inputs: notebook_path (required). Returns: result
notebook_restart_kernelA
Restart the kernel for a notebook, clearing all variables and imports.
The kernel process stays alive — only its state is reset, so subsequent run_cell calls start from a clean slate without the startup overhead of a fresh kernel.
Args: notebook_path: Path to the .ipynb file whose kernel should be restarted.
Inputs: notebook_path (required). Returns: result
notebook_run_allA
Execute every cell in the notebook in order and return all outputs.
Args: notebook_path: Path to the .ipynb file, relative to the workspace root. kernel_name: Kernel to use (default: 'python3'). timeout: Per-cell timeout in seconds (default: 60). stop_on_error: Stop at first failing cell (default: true). save_outputs: Write outputs back to the .ipynb file (default: true).
Inputs: notebook_path (required), timeout, kernel_name, save_outputs, +1 more. Returns: result
notebook_run_cellA
Execute a single code cell and return its outputs.
Kernel state (variables, imports) is preserved between calls on the same notebook, so cells can depend on earlier ones.
Args: notebook_path: Path to the .ipynb file, relative to the workspace root. cell_index: Zero-based index of the cell to run. kernel_name: Kernel to use (e.g. 'python3', 'myenv'). Defaults to 'python3'. Run notebook_list_kernels to see options. timeout: Seconds to wait for the cell to finish (default: 60). save_outputs: Write outputs back to the .ipynb file (default: true).
Inputs: cell_index (required), notebook_path (required), timeout, kernel_name, +1 more. Returns: result
notebook_run_pipelineA
Run all cells tagged with a pipeline stage, in notebook order.
Pipeline stage tags are set per-cell in JupyterLab: View → Cell Toolbar → Tags (add e.g. 'preprocess', 'train', 'evaluate')
Use notebook_list_stages to see what stages exist in a notebook.
Args: notebook_path: Path to the .ipynb file, relative to the workspace root. stage: Tag name of the stage to run (e.g. 'preprocess'). kernel_name: Kernel to use (default: 'python3'). timeout: Per-cell timeout in seconds (default: 60). stop_on_error: Stop at first failing cell (default: true). save_outputs: Write outputs back to the .ipynb file (default: true).
Inputs: stage (required), notebook_path (required), timeout, kernel_name, +2 more. Returns: result
notebook_run_rangeA
Execute cells from start to end (inclusive) and return all outputs.
Execution stops at the first error by default (stop_on_error=true).
Args: notebook_path: Path to the .ipynb file, relative to the workspace root. start: First cell index to run (inclusive). end: Last cell index to run (inclusive). kernel_name: Kernel to use (default: 'python3'). timeout: Per-cell timeout in seconds (default: 60). stop_on_error: Stop at first failing cell (default: true). save_outputs: Write outputs back to the .ipynb file (default: true).
Inputs: end (required), start (required), notebook_path (required), timeout, +3 more. Returns: result
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 17 tools
Each tool targets a distinct operation on notebooks, cells, metadata, or kernels. There is no overlap, and descriptions clearly differentiate purposes (e.g., list_cells vs read_cell, run_all vs run_pipeline).
All tools follow the `notebook_verb_noun` pattern consistently. Verbs like delete, edit, insert, list, read, restart, run are used uniformly, making it easy to predict tool behavior from its name.
With 17 tools, the set covers cell manipulation, metadata editing, execution modes, and kernel management without being excessive. Each tool serves a clear purpose, and the count is well-suited to the domain.
Core workflows like CRUD for cells, multiple execution modes, and kernel management are covered. However, missing notebook creation (e.g., `notebook_create`) and explicit save/export operations are minor gaps that agents may need to work around.
Maintenance
Related MCP Connectors
Read and write KukGit repositories, files, issues and pull requests from an AI assistant.
Connect AI assistants to GitHub - manage repos, issues, PRs, and workflows through natural language.
Persistent cloud workspaces for AI agents: run commands, edit files, use git and a browser.
Files and tables your AI reads and writes from any chat, with version history and sharing.
Related MCP Servers
- AlicenseAqualityDmaintenanceEnables programmatic interaction with Jupyter notebooks, allowing reading, editing, and executing cells via Claude.640 PyPI34MIT
- AlicenseAqualityDmaintenanceEnables AI agents to create, read, edit, and execute Jupyter notebook cells, manage kernels, and connect to remote Jupyter servers.2124 PyPIMIT
- FlicenseNot gradedqualityDmaintenanceEnables AI agents to execute Jupyter notebook cells with persistent kernel state, output persistence, and structured JSON control surface.2-
- AlicenseNot gradedqualityDmaintenanceEnables AI agents to read, edit, execute cells, and capture outputs from Jupyter notebooks directly within VS Code or Cursor via the Model Context Protocol.8 npm18MIT