MCP Jupyter Notebook Server
A Model Context Protocol (MCP) server that gives AI agents full control over a live Jupyter notebook session — run code, add markdown, manage packages, inspect variables, and more. Built on agent-jupyter-toolkit and the MCP Python SDK.
Features
- Rich MCP tool surface — notebook lifecycle, code execution, markdown, stable cell-ID operations, packages, kernel control, introspection, variables
- Optional PostgreSQL tools — enable on demand to create a DB client/connection in the kernel
- Real-time sync — Yjs collaboration transport shows cell edits instantly in JupyterLab
- Two session modes — connect to a remote Jupyter server or run a local kernel
- Three transports — stdio (for editors), SSE, or streamable HTTP
- MCP SDK compatibility — supports the 1.26 API and the 2.x
MCPServerAPI - Observable collaboration policy — required, preferred with classified fallback, or disabled
- Zero config defaults — sensible defaults with full override via CLI args or env vars
Quick Start
1. Start a Jupyter server
# With Docker (recommended — includes jupyter-collaboration)
cd quickstarts && docker compose up -d --build
# Or locally
pip install jupyterlab ipykernel jupyter-collaboration
jupyter lab --port 8888 --IdentityProvider.token=mcp-dev-token
2. Configure your editor
VS Code — create .vscode/mcp.json:
{
"servers": {
"jupyter": {
"type": "stdio",
"command": "uv",
"args": ["run", "--directory", "${workspaceFolder}", "mcp-jupyter-notebook"],
"env": {
"MCP_JUPYTER_SESSION_MODE": "server",
"MCP_JUPYTER_BASE_URL": "http://localhost:8888",
"MCP_JUPYTER_TOKEN": "mcp-dev-token",
"MCP_JUPYTER_NOTEBOOK_PATH": "agent_demo.ipynb"
}
}
}
}
See the quickstart guide for Cursor, Claude Desktop, and published (
uvx) vs local dev configs.
Optional: enable PostgreSQL tools
To add database helper tools, set either:
MCP_JUPYTER_ENABLE_TOOLS=postgresql(env var), or--enable-tools postgresql(CLI flag)
In server mode, the kernel runs on the Jupyter server, so database env vars (like PG_DSN) must be set in the Jupyter server environment (see quickstarts/docker-compose.yml with docker compose --profile postgres).
Note: enabling tools only controls tool registration. Your PostgreSQL service must still be running and ready to accept connections (the quickstart Compose profile includes a healthcheck).
The PostgreSQL tools will use PG_DSN / POSTGRES_DSN / DATABASE_URL (in that order), or fall back to libpq env vars.
3. Use it
Ask your agent:
"Create a notebook that generates 100 random numbers, plots a histogram, and adds a markdown summary."
Tools
Session operations accept an optional
notebook_path. When omitted, the manager's default notebook is used. Open and close tools require a path.
notebook_open(path) keeps an existing default; use
notebook_open(path, set_default=True) to switch subsequent pathless calls.
Explicit paths on execution tools affect only that call. Other sessions remain
open when switching. notebook_list shows the current default and open notebooks.
No session ID is required.
Session management is provided by the core toolkit's NotebookWorkspace,
running inside the MCP server process. Local and remote MCP connections use the
same behavior. Callers sharing a manager share its default; independent callers
should use explicit notebook paths when working through that shared manager.
Notebook Lifecycle
| Tool | Description |
|---|---|
notebook_open |
Open a notebook and create a session (kernel + document transport) |
notebook_close |
Close a notebook session and release its resources |
notebook_delete |
Delete a notebook file and close its session (server: Contents API, local: filesystem) |
notebook_list |
List all currently open notebook sessions |
notebook_files_list |
Discover .ipynb files on disk (local) or via Contents API (server) |
Code Execution
| Tool | Description |
|---|---|
notebook_code_run |
Append a new code cell, execute it, and return outputs (stdout, stderr, rich displays) |
notebook_code_run_existing |
Replace the source of an existing cell (by index) and re-execute it |
notebook_code_execute |
Execute code without creating a cell, optionally in a kernel subshell |
notebook_cells_run |
Execute multiple cells sequentially (code and/or markdown) |
notebook_run_all |
Execute every code cell in notebook order and return a per-cell summary |
notebook_restart_and_run_all |
Restart the kernel, then execute every code cell from a clean state |
Notebook Document
| Tool | Description |
|---|---|
notebook_markdown_add |
Add a markdown cell (append or insert at position) |
notebook_read |
Read all cells, sources, outputs, and metadata |
notebook_cell_delete |
Delete a cell by its 0-based index |
notebook_cell_delete_by_id |
Delete a cell by its stable Jupyter cell ID |
notebook_cell_source_set_by_id |
Replace a cell's source text using its stable cell ID |
notebook_cell_move |
Move a cell to a new index using its stable cell ID |
notebook_cell_move_before |
Move a cell immediately before another stable cell ID |
notebook_cell_move_after |
Move a cell immediately after another stable cell ID |
Cell Reads
| Tool | Description |
|---|---|
notebook_cell_read |
Read a single cell by index (full dict with type, source, outputs, metadata) |
notebook_cell_read_by_id |
Read a single cell by stable Jupyter cell ID |
notebook_cell_source |
Return only the source text of a cell |
notebook_cell_source_by_id |
Return only the source text using a stable cell ID |
notebook_cell_count |
Return the number of cells in the notebook |
Packages
| Tool | Description |
|---|---|
notebook_packages_install |
Install PEP 508 requirements in the kernel |
notebook_packages_uninstall |
Uninstall parsed distribution requirements from the kernel |
notebook_packages_check |
Check which packages are available without installing |
notebook_dependencies_list |
List canonical tracked requirements and resolved versions |
Kernel Control
| Tool | Description |
|---|---|
notebook_kernel_interrupt |
Interrupt a running computation (SIGINT) |
notebook_kernel_info |
Get kernel metadata (protocol version, language info, banner) |
notebook_session_info |
Get session info (kernel type, alive status, connections) |
notebook_kernel_history |
Retrieve recent execution history from the kernel |
notebook_kernel_restart |
Restart the kernel (destructive — clears all state) |
notebook_subshell_create |
Create a subshell when the kernel advertises support |
notebook_subshell_list |
List active subshell IDs |
notebook_subshell_delete |
Delete a subshell by ID |
notebook_debug_request |
Send a Debug Adapter Protocol request to a capable kernel |
Introspection
| Tool | Description |
|---|---|
notebook_inspect |
Inspect an object — returns docs, type info, docstrings |
notebook_complete |
Get tab-completion suggestions at a cursor position |
notebook_code_is_complete |
Check if a code fragment is syntactically complete |
notebook_variables_list |
List user-defined variables in the kernel's global scope |
notebook_variable_get |
Get the value of a specific variable |
notebook_variable_set |
Set a variable in the kernel's global scope |
Full tool reference with parameters and examples: Tool reference
Installation
# From PyPI (when published)
uvx mcp-jupyter-notebook
# From PyPI with toolkit DataFrame serialization support
uv pip install "mcp-jupyter-notebook[dataframe]"
# From source
git clone https://github.com/Cyb3rWard0g/mcp-jupyter-notebook.git
cd mcp-jupyter-notebook
uv pip install -e ".[dev]"
Configuration
All settings can be passed as CLI arguments or environment variables. CLI arguments take precedence.
| Variable | CLI Flag | Description | Default |
|---|---|---|---|
MCP_JUPYTER_SESSION_MODE |
--mode |
server (remote Jupyter) or local |
server |
MCP_JUPYTER_BASE_URL |
--base-url |
Jupyter server URL | — |
MCP_JUPYTER_TOKEN |
--token |
Jupyter API token | — |
MCP_JUPYTER_KERNEL_NAME |
--kernel-name |
Kernel spec name | python3 |
MCP_JUPYTER_NOTEBOOK_PATH |
--notebook-path |
Notebook file path (.ipynb) |
auto-generated |
MCP_JUPYTER_TRANSPORT |
--transport |
stdio, sse, streamable-http |
stdio |
MCP_JUPYTER_HOST |
--host |
Host for HTTP transports | 127.0.0.1 |
MCP_JUPYTER_PORT |
--port |
Port for HTTP transports | 8000 |
MCP_JUPYTER_LOG_LEVEL |
— | DEBUG, INFO, WARNING, ERROR |
INFO |
MCP_JUPYTER_HEADERS_JSON |
— | Extra HTTP headers as JSON object | — |
MCP_JUPYTER_PREFER_COLLAB |
— | Use Yjs real-time sync (true/false) |
true |
MCP_JUPYTER_COLLABORATION_MODE |
--collaboration-mode |
required, preferred, or disabled |
preferred |
Full configuration reference: docs/mcp-server/configuration.md
MCP_JUPYTER_PREFER_COLLAB remains a compatibility alias when the explicit
mode is unset. Session/list results show the selected document transport and a
fallback reason. Kernel execution results include stable cell/request identity,
persistence status, truncation accounting, and timeout/outcome fields.
Project Structure
src/mcp_jupyter_notebook/
├── __init__.py # CLI entry point (argparse)
├── server.py # FastMCP server, lifespan, config processing
├── context.py # AppContext dataclass (shared lifespan state)
└── tools/ # Tool registrations (notebook + optional domains)
├── notebook/ # Core notebook tool pack, split by concern
└── postgresql.py # Optional PostgreSQL helper tools
Development
git clone https://github.com/Cyb3rWard0g/mcp-jupyter-notebook.git
cd mcp-jupyter-notebook
uv pip install -e ".[dev]"
# Run tests
uv run pytest
# Lint
uv run ruff check src/ tests/
uv run ruff format src/ tests/
See docs/architecture.md for internals and CONTRIBUTING.md for the release process.
License
Metadata
Release files for mcp-jupyter-notebook 0.8.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| mcp_jupyter_notebook-0.8.0.tar.gz | 45.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| mcp_jupyter_notebook-0.8.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 86.4 kB
Release files / mcp_jupyter_notebook-0.8.0.tar.gz
| Download URL | mcp_jupyter_notebook-0.8.0.tar.gz |
|---|---|
| Size | 45.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
260321692fd141c16f6d57ca83bdf796d5ffa902ad427890c2c734f8a1d25824
|
|
BLAKE2b-256 checksum How to use checksums |
053627857504648c4edf9aa86d69e167faf878df3aea9fef2676eaa8c555e907
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 13, 2026.
Transparency logRelease files / mcp_jupyter_notebook-0.8.0-py3-none-any.whl
| Download URL | mcp_jupyter_notebook-0.8.0-py3-none-any.whl |
|---|---|
| Size | 41.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ab40d4c5511cde77f1efcc7aa8ff195b6722fbf3b76b445be91d8221958c7e4c
|
|
BLAKE2b-256 checksum How to use checksums |
310b67035539a2a01aba01f96fd04671878ad564a10ecf7e89ec04058d7c8107
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 13, 2026.
Transparency log