Jupyter MCP Server: connect an AI agent to a live Jupyter notebook
🪐 🔧 Model Context Protocol (MCP) Server for Jupyter.
At a glance
- What is it?
- Datalayer's MCP server lets an agent read, edit and execute cells in a running Jupyter notebook. It is a single Python package with a CLI, a Docker image and a hosted endpoint, and the main thing to get right is version pairing.
- Who is it for?
- Adopt it if you already run Jupyter and want an agent to work inside a real notebook rather than a pasted-in script; skip it if you have no Jupyter server to point at, since the server is a bridge and not a notebook environment. Before rolling it out, verify the two version pairs: jupyter-mcp-server >= 1.5.0 with code-sandboxes >= 1.1.1, and jupyter-mcp-server >= 2.0.0 with mcp >= 2.
- Can I use it commercially?
- Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What Jupyter MCP Server actually connects
The Model Context Protocol defines how an AI client talks to a tool provider. Jupyter MCP Server is the provider side for Jupyter: it exposes notebooks as MCP tools so a client such as Claude Code or Cursor can list notebooks, read cells, write cells and execute code without the user copying anything between windows. The README describes it as 'an MCP server developed for AI to connect and manage Jupyter Notebooks in real-time'.
The audience is narrow and specific. You need a Jupyter deployment already running, local or JupyterHub, and an MCP-capable client. If you have neither, nothing here helps you. The README states that the project is free and open source under BSD 3-Clause and can be pointed at any Jupyter you already run, local or JupyterHub, with no account needed. That last part matters: the hosted endpoint is an option, not a requirement.
The project is developed by Datalayer, and the same server drives their commercial product. That shapes the repository: there is a hosted path at https://mcp.datalayer.run/mcp and a self-hosted path through the Python package. Both are documented, and the self-hosted one is not crippled to push you toward the account.
How the server sits between the agent and the kernel
The dependency list in pyproject.toml is the clearest description of the architecture. The server depends on jupyter-server-client and jupyter-nbmodel-client for talking to Jupyter, jupyter-collaboration and pycrdt for the collaborative document model behind notebooks, fastapi and uvicorn for the HTTP surface, and mcp[cli] for the protocol layer. It also depends on code-sandboxes, which is what lets the same server target a local Jupyter or a remote sandbox on Kaggle, Google Colab, Modal, Daytona, E2B, CoreWeave or Cloudflare through optional extras.
So the data flow is: an MCP client calls a tool, the server translates that call into an operation against the Jupyter server's notebook model, and the notebook's collaborative state is what changes. pycrdt is a CRDT implementation, which is why the README can describe real-time management rather than a batch file rewrite. The agent is editing the same document a human would edit in JupyterLab.
That design has a consequence worth stating plainly. Because the server leans on jupyter-collaboration and jupyter-server-nbmodel, it is not a standalone notebook runtime. It is a client of a Jupyter deployment that must have the right server extensions available. The README does not spell out the minimum Jupyter server configuration beyond the pinned jupyter_server>=2.10,<3 dependency, so if you run a stripped-down Jupyter installation, expect to check that the nbmodel and collaboration pieces are present before debugging anything else.
Installing Jupyter MCP Server and running a first notebook call
The package is on PyPI as jupyter-mcp-server, and the project also publishes a Docker image at datalayer/jupyter-mcp-server. The README gives two install lines that differ only in version pinning, and the choice depends on which server version you are running. On 1.5.0 or later, the README's command is:
pip install "jupyter-mcp-server>=1.5.0" "code-sandboxes>=1.1.1"If you are staying on an earlier jupyter-mcp-server, the README gives the mirror image:
pip install "jupyter-mcp-server<1.5.0" "code-sandboxes<=1.0.9"The reason is a rename: the sandbox variant jupyter became jupyter-server in code-sandboxes 1.1.1, and the two packages have to agree on the name. Getting this wrong does not fail at install time. The README states that an older server with a newer code-sandboxes installs cleanly and then fails on the first execution with Unknown sandbox variant: jupyter. That error message is the one to search for if a first run dies immediately.
The package also installs a console script. pyproject.toml declares jupyter-mcp as the entry point for jupyter_mcp_server.cli.cli, so after installation the command is available on the path. The Dockerfile builds a python:3.12-slim image, installs the package in editable mode, exposes port 4040 and sets the entry point to python -m jupyter_mcp_server. If you prefer containers, that image is the starting point rather than a finished deployment, since it does not configure a Jupyter server for you.
For Claude Code specifically, the README documents a plugin route that avoids manual MCP configuration and adds three slash commands, /datalayer:notebook, /datalayer:run and /datalayer:status:
/plugin marketplace add datalayer/jupyter-mcp-server
/plugin install datalayerThere is also an optional extra for JupyterLab integration, jupyterlab = ["jupyter-mcp-tools>=0.1.7"], which is separate from the server itself. The README does not document a rollback procedure for any of these installs, so pin versions in your environment file if you need to reverse a change.
The version pairing is the failure mode you will actually hit
Most MCP servers fail in obvious ways: the client cannot reach the endpoint, or the tool list is empty. This one has a subtler failure that the README calls out with a hot-fix badge, and it is worth treating as the primary operational risk. Two packages, jupyter-mcp-server and code-sandboxes, must agree on a sandbox variant name. Install a mismatched pair and pip reports success. The failure surfaces later, on the first execution, with Unknown sandbox variant: jupyter.
The second pairing is the MCP SDK. From v2.0.0 the project runs on the MCP Python SDK 2, pinned as mcp>=2,<3. Before 2.0.0 it pinned mcp<2. The README notes that pip sorts this out because both are pinned in the package, but that an environment holding another package which still pins mcp<2 has to stay on jupyter-mcp-server<2 until that package moves. In a shared environment with several MCP-related packages, that constraint can block an upgrade for reasons that have nothing to do with Jupyter.
A third limitation is scope. The server manages notebooks; it does not create a Jupyter deployment, provision a kernel, or replace JupyterHub. If your problem is 'I have no Jupyter', this is the wrong tool. It is also the wrong tool if you want an agent to write a standalone script: the whole value here is operating on a live notebook document, and running it against a scratch file gains you nothing over a normal code-execution tool.
Datalayer's hosted endpoint versus running it yourself
The README is explicit that Datalayer now hosts this server at https://mcp.datalayer.run/mcp, described as one endpoint for every agent and every notebook, with browser sign-in and approval of what the agent may do. The stated advantage is continuity: work keeps running on the server after the agent disconnects.
The self-hosted path is the same server code, installed from PyPI or run from the Docker image, pointed at a Jupyter you control. The difference is not features but who holds the process and the credentials. Self-hosted, you supply the Jupyter server and the network path to it; the README says no account is needed. Hosted, you sign in through the browser and the agent never sees your password. The README describes the authorization model as two separate decisions: scopes such as notebooks:read, notebooks:write, code:execute and data:read say what kind of operation an agent may perform, while your own Datalayer permissions still determine which notebooks it can touch. Personal access tokens remain supported and the README calls them the simpler path for a CLI or a script.
For a team that already runs JupyterHub and has opinions about where notebook data lives, self-hosting is the obvious default, and the hosted endpoint is a convenience for individuals or for work that should outlive a laptop session. That is a genuine architectural difference, not a pricing tier.
Maintenance, licence and upgrade cost
The repository is not archived, and the last push was on 2026-09-10. Releases have been frequent and small: v2.1.12 and v2.1.11 both landed on 2026-09-09, with v2.1.7 on 2026-09-05. That cadence suggests active work, and it also means version numbers move quickly enough that pinning is the sane default for anything beyond a personal setup.
The licence is BSD 3-Clause, which is permissive and imposes no copyleft obligation on code that merely depends on the package. The licence file is at the repository root, and the README and pyproject.toml both carry the BSD 3-Clause header. One thing to note for anyone embedding this: the project depends on code-sandboxes, which carries its own extras for each target platform (docker, google-colab, kaggle, modal, datalayer, daytona, cloudflare, coreweave, e2b, and an all-in-one sandboxes extra). Those extras pull platform-specific dependencies, so the effective licence and dependency surface of your install depends on which extra you choose. That is a packaging observation, not legal advice; check the licences of the extras you enable.
The upgrade cost is concentrated in the two version pairs described above. Upgrading across the 1.5.0 boundary or the 2.0.0 boundary means checking code-sandboxes and mcp at the same time. Within a major line, the README states that nothing changes in how you start or configure the server, in the tools, or for MCP clients connecting to it, because the protocol is negotiated per client. If you write an extension or a custom token verifier against the MCP SDK, the 2.0.0 release notes mention renamed imports, so that code needs a review rather than a version bump.
Alternatives and when they fit better
The closest alternative is not another MCP server but a different integration shape: giving the agent a shell or a Python execution tool and letting it run jupyter nbconvert or papermill against a notebook file. That approach needs no Jupyter server running, no collaboration extensions and no MCP client configuration. What it loses is state. Each invocation starts from a file on disk, so a long-lived kernel with loaded data and warm caches is not available, and there is no live document for a human to watch or edit alongside the agent.
If your notebooks are short-lived batch jobs, the file-based route is simpler and has fewer moving parts. If a human and an agent need to work in the same notebook at the same time, or the kernel state itself is expensive to rebuild, the MCP route is the one that matches the problem. The dependency list here, with jupyter-collaboration and pycrdt, exists precisely to support that second case, and it is the reason the install is heavier than a single script.
A second alternative is to skip the agent entirely and use Jupyter's own scheduling and parameterization tooling. That is not a competitor so much as a statement that this project is for interactive, agent-driven notebook work, not for production pipelines.
Editorial conclusion
Adopt it if you already run Jupyter and want an agent to work inside a real notebook rather than a pasted-in script; skip it if you have no Jupyter server to point at, since the server is a bridge and not a notebook environment. Before rolling it out, verify the two version pairs: jupyter-mcp-server >= 1.5.0 with code-sandboxes >= 1.1.1, and jupyter-mcp-server >= 2.0.0 with mcp >= 2. An older server with a newer code-sandboxes installs cleanly and then fails on the first execution with 'Unknown sandbox variant: jupyter', so check the pins before the first run, not after.
Frequently asked questions
Can Claude Code be used with Jupyter MCP Server?
Yes. The README documents a Claude Code plugin that installs with two commands and adds the /datalayer:notebook, /datalayer:run and /datalayer:status slash commands on top of the standard MCP connection.
How do I install Jupyter MCP Server?
Install it from PyPI with pip, choosing the pin that matches your server version: jupyter-mcp-server>=1.5.0 with code-sandboxes>=1.1.1, or jupyter-mcp-server<1.5.0 with code-sandboxes<=1.0.9. A Docker image is also published as datalayer/jupyter-mcp-server.
What goes wrong if the code-sandboxes version does not match?
The README states that an older server with a newer code-sandboxes installs cleanly and then fails on the first execution with the message Unknown sandbox variant: jupyter. The cause is a rename of the sandbox variant jupyter to jupyter-server in code-sandboxes 1.1.1.
Does Jupyter MCP Server need a Datalayer account?
No. The README says the project is free and open source under BSD 3-Clause and can be pointed at any Jupyter you already run, local or JupyterHub, with no account needed. Datalayer also hosts an endpoint at https://mcp.datalayer.run/mcp for those who prefer not to run the process themselves.
Which MCP SDK version does Jupyter MCP Server use?
From v2.0.0 the project runs on the MCP Python SDK 2, pinned as mcp>=2,<3; earlier versions pin mcp<2. The README notes that an environment containing another package which still pins mcp<2 has to stay on jupyter-mcp-server<2 until that package moves.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/datalayer-jupyter-mcp-server)