mcp-jupyter
Provides MCP tools and an embedded panel for managing Jupyter notebooks: browsing/creating/opening .ipynb files, editing and executing cells, managing kernels, streaming outputs, exporting notebooks to Markdown or HTML, and connecting to local or remote Jupyter Servers with shared JupyterLab kernels.
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
dsh-jupyter-notebook
给 DeepSeek Harness(DSH) 用的 Jupyter Notebook 集成:Agent 通过 MCP 工具管理 notebook,同时在 Harness 侧栏提供内嵌编辑/查看面板,可浏览、编辑、运行 .ipynb 单元格并查看文本和图片输出。Notebook 文件保持标准 nbformat 4.5,可继续用 JupyterLab / VS Code 打开。
面板通过 DSH 原生 Client slot 和 Host HTTP 路由提供,另起的面板 Kernel 与 MCP 子进程 Kernel 独立;面板读写的仍是相同磁盘 .ipynb 文件。它支持切换 Notebook 根目录、创建文件、增删改 cell、单步或全部运行,以及显示纯文本和 PNG 输出。HTML 输出为安全起见不执行、不渲染。
DSH 会话
└── @deepseek-ai/dsh-mcp-client(DSH 自带)
└── src/server.mjs 12 个 mcp__jupyter__* 工具,负责 .ipynb 读写与调度
├── 本地后端:kernel/dsh_kernel.py IPython 子进程,零端口、零 token
└── 服务器后端:src/jupyter-server.mjs
REST /api/contents + /api/kernels,执行走 /api/kernels/<id>/channels (WebSocket)两种后端
本地后端(默认) | 服务器后端( | |
notebook 在哪 | 工作区里的普通文件 | Jupyter Server 上,路径相对 server root |
内核 | 本插件起的 IPython 子进程 | 服务器上的内核,和你 JupyterLab 里打开的是同一个 |
变量共享 | 只有本会话 | 与 JupyterLab / 其它客户端共享 |
需要什么 | 插件自己的 | 一台在跑的 Jupyter Server + token |
运行环境 | 固定为本机 venv | 服务器的 Python 环境( |
Related MCP server: mcp-server-jupyter
嵌入式面板
面板从侧栏进入,顶部下拉框决定 notebook 的来源:
来源 | notebook 在哪 | 内核 |
| 配置根目录或已登记 Workspace 下的文件 | 面板自起的 Python 子进程,与 MCP / JupyterLab 互不共享 |
| 本机发现到的 Jupyter Server(读 runtime 文件拿 token),路径相对 server 根目录 | 复用 JupyterLab 已为该 notebook 打开的 kernel;没有则新建。共享时状态栏显示 |
| 手填 URL + token 的 Jupyter Server(远程也行),token 只存在内存里 | 同上 |
两种来源都支持:浏览、新建、打开、重命名、删除、cell 类型切换、保存、插入、删除、上移/下移、清空输出(单格或全部)、单步运行、全部运行、中断、重启内核、停止内核。执行结果写回 notebook(本地写磁盘,服务走 contents API);PNG 内嵌显示,HTML 只显示安全占位文本。
内核按 notebook 常驻(和 JupyterLab 一样,切走不会丢变量):工具栏 停止内核 主动释放,重启内核 清空命名空间,插件卸载时释放面板自己起的那些;服务上共享给 JupyterLab 的内核不会被面板删除。连服务时,没起内核前工具栏提供 kernelspec 下拉,决定这次用哪个内核启动。
执行是流式的:点运行后输出边产生边显示(Host 用 NDJSON 分帧推送,本地内核按行 flush,服务内核走 iopub),单元格标题栏显示 运行中…;跑完最后一帧带回整篇 notebook,覆盖运行期间的临时输出。
markdown / raw 单元默认渲染成只读预览(标题、列表、引用、代码块、表格、链接),点正文或标题栏的铅笔图标进入编辑,眼睛图标回到预览。渲染器把内容建成 React 元素,notebook 里的 HTML 永远不会被注入执行;链接只认 http(s) 与相对路径。有未保存修改时,切换 notebook 或来源会先确认。
文件被外部改动时会拒绝用旧 revision 覆盖:本地文件显示 从磁盘重载,服务上的 notebook 同样提示冲突,重载即重新读服务。面板只在检测到本机 Jupyter Server 时列出该选项;连不上或 token 不对会在面板顶部报错(错误提示可关闭)。
移动 notebook 到别的目录会释放面板自己起的那个内核(内核的工作目录停在旧目录,继续用会写错相对路径);同一目录内改名则保留内核。共享给 JupyterLab 的内核只解绑、不删除。
已知边界
一次只打开一个 notebook,没有多标签页;内核按 notebook 保留,切回不需要重跑。
HTML 输出只显示占位文本,不渲染(避免把 notebook 里的 HTML 注入页面)。
markdown 渲染是子集:标题、列表、引用、代码块、表格、链接、粗斜/行内代码;不处理图片、脚注、嵌套列表。
单元格只能按按钮上下移动,不支持拖拽排序。
与 JupyterLab 同时编辑同一文件时,靠 revision 挡住「基于旧版本保存」;两边都基于同一 revision 时后写的一方生效。
远程服务器要手填 token,没有 OAuth / 密码登录流程。
面板不提供 notebook 的上传/下载。
安装
从 npm 安装(推荐)
dsh plugin --profile desktop add dsh-jupyter-notebook或者在 DSH 的 插件 → 添加插件 里输入包名 dsh-jupyter-notebook。安装后重启 DSH,侧栏就会出现 Notebook 图标。
插件自己起的 Python 内核需要本机有一套 Python 环境(ipython + matplotlib,数据类 notebook 再加 pandas)。默认优先用插件目录下的 .venv,找不到时用 DSH_JUPYTER_PYTHON:
python -m venv .venv
.venv/Scripts/python -m pip install ipython matplotlib pandas # Windows
.venv/bin/python -m pip install ipython matplotlib pandas # macOS / Linux从源码安装
git clone https://github.com/alice0721021-web/dsh-jupyter-notebook.git
cd dsh-jupyter-notebook
npm install # MCP 服务端 SDK(只在用 MCP 工具时需要)然后在 Plugin Manager 里安装这个目录。
配置
cordis.patch.yml 里的 config.root 决定面板能浏览的默认根目录,config.python 决定面板内核使用的解释器;两者省略时回退到 DSH_JUPYTER_ROOT / 进程工作目录 / 包内 .venv。要改配置就在 你的 profile 的 cordis.patch.yml 里覆盖同名 row:
- id: dsh-jupyter-notebook
config:
root: F:\notebooks
python: F:\notebooks\.venv\Scripts\python.exeMCP 服务与面板互不替代:scripts/install.mjs 只负责写 profile 里那段 mcp-jupyter 配置并做一次握手自检,不装 bundle;只要 MCP 工具就够时可以只跑脚本,要面板就必须装 bundle。
面板 API 的边界
Host 路由 /api/dsh-jupyter-notebook 只接受来自本机回环地址、且 Content-Type: application/json 的请求;带 Origin 头的请求必须也是本机来源。这样别的网站无法用一个简单表单把请求发进来(跨站写文件/执行代码),而面板自身的 fetch 不受影响。根目录永远限制在配置目录与已登记 Workspace 之内,服务目标只允许「本机发现到的」或回环地址。
工具
工具 | 作用 |
| 发现本机在跑的 Jupyter Server(读 jupyter runtime 目录并探活),列出已连接的服务 |
| 用 URL(本机可省略 token,自动用 runtime 里的)连上,得到连接名 |
| 忘记一个连接;notebook 和内核都不动 |
| 列目录下的文件夹与 |
| 打开或 |
| 读 cell 全文与输出,可按 |
|
|
| 按顺序或 |
| 尽力中断当前 cell(本地注入异常;服务器发 |
| 重启内核清空状态,可 |
| 打开的 notebook、内核 pid / kernel id、是否与 JupyterLab 共享、已连接的服务 |
| 导出 Markdown 或自包含 HTML(图片内嵌),配合 |
连接已有的 Jupyter Server
list_servers # 本机自动发现:http://localhost:8888/ pid 43188 token: found
connect_server { url: "http://localhost:8888/" } # 本机:token 从 runtime 文件里取
connect_server { url: "https://host/user/me/", token: "…" } # 远程:token 自己带
list_notebooks { server: "localhost:8888" }
open_notebook { server: "localhost:8888", path: "analysis.ipynb" }
execute_cells { server: "localhost:8888", path: "analysis.ipynb", all: true }细节:
发现:读
%APPDATA%\jupyter\runtime\jpserver-*.json(或$JUPYTER_RUNTIME_DIR), 逐个GET /api/status探活,死掉的 PID 直接跳过。token 只留在 MCP 服务进程里,不回显。共享内核:执行前先查
GET /api/sessions,如果这个 notebook 已经有会话(JupyterLab 里 开着),直接用它的 kernel id——所以你在 JupyterLab 里定义的变量,Agent 也能用,反之亦然。 没会话时才POST /api/kernels起一个。kernel_status会标(shared with JupyterLab)。执行协议:
ws(s)://<base>api/kernels/<id>/channels,发execute_request, 按parent_header.msg_id收集stream/execute_result/display_data/error, 收到execute_reply+ iopubidle才算结束。图片(image/png)照旧回聊天。保存:
PUT /api/contents/<path>,JupyterLab 那边会看到文件变化。base_url:粘贴
.../lab?token=xxx或.../tree都能识别,自动裁成 base 并把 token 取出来。连不上/令牌错会明确报「server rejected the token (401/403)」,不会静默换成别的服务器。
设计要点
cell 身份与乐观锁:每个 cell 有稳定
id,rev是源码的 sha1 前 10 位;update可带expectedRevision,对不上返回revision_conflict而不是覆盖。notebook 级revision同理。整批原子:
edit_notebook的多个操作在内存里全部成功才写盘,任何一步抛错都不落盘。内核按 notebook 隔离(本地后端):一个 notebook 一个 Python 进程,cwd 是该 notebook 所在目录, 所以
pd.read_csv("data.csv")这类相对路径和 Jupyter 里一致;不同 notebook 不会互相污染变量。协议通道防污染(本地后端):Python 侧把真正的 stdout
dup出来当协议通道,再把 fd 1 指向 stderr, 用户代码os.write(1, ...)也破坏不了 JSON 流。输出取舍:
.ipynb里保留 Jupyter 原样的 MIME bundle(text/plain+text/html+image/png),聊天侧只取可读的部分:HTML 表格转 Markdown(两条后端各有一份转换器, 因为本地后端在 Python 里转、服务器后端在 Node 里转),图片转 PNG。图片双通道:既作为 MCP image 内容回到会话(deepseek-flash 能直接看),也写到
<notebook 目录>/.dsh-jupyter/figures/(服务器后端写到<workspace>/.dsh-jupyter/figures/), 方便present或后续引用。
环境注记
信任边界:
execute_cells能在内核里跑任意代码,权限等于运行 DSH 的那个用户,和原插件 一样。DSH 的审批策略对 MCP 工具调用同样生效(当前会话是never,即自动放行,相当于免确认)。 只在你信任的机器与工作区里开这个集成。内核写文件只落在工作区/插件目录。本机上 Python 子进程写
%USERPROFILE%会被拒绝 (PermissionError: WinError 5,Node/PowerShell 不受限),所以MPLCONFIGDIR默认放<插件>/.data/mpl,图片放 notebook 同目录,不使用用户目录。PyPI 直连很慢,装
ipython/matplotlib用了清华镜像;pip install卡住时先换源。内核认证:
DSH_JUPYTER_PYTHON指定解释器;没设置时按--python→ 环境变量 →<插件>/.venv的顺序找。
开发与测试
npm run smoke # 本地后端:用 @modelcontextprotocol/client 2.2.0(与 DSH 同代)跑完整链路
node scripts/smoke-server.mjs http://127.0.0.1:8899/ smoke-token test # 服务器后端:连真 Jupyter Server
node scripts/kernel-probe.mjs .\.venv\Scripts\python.exe # 只测内核协议scripts/smoke.mjs 覆盖:建 notebook、批量插入、执行整篇、错误 cell、revision 冲突、
restart、interrupt,最后校验落盘 nbformat 4.5 与图片文件。
scripts/smoke-server.mjs 覆盖:发现/连接(含错 token 的报错)、contents 读写、经 WebSocket
执行、表格转 Markdown、图片回传、跨工具调用复用内核、restart 后变量确实消失、
复用 JupyterLab 已开会话的内核(shared with JupyterLab)、导出、断开。
起一个测试服务器(独立 runtime/data 目录,避免污染真实 JupyterLab):
$env:JUPYTER_RUNTIME_DIR="$PWD\.data\jupyter-runtime"; $env:JUPYTER_DATA_DIR="$PWD\.data\jupyter-data"
.\.venv\Scripts\jupyter-server.exe --no-browser --port 8899 --ServerApp.root_dir="$PWD\.data\server-workspace" --IdentityProvider.token=smoke-token目录
src/server.mjs MCP 工具与调度(独立 stdio 服务入口)
index.js Host 插件:localhost 面板 API bridge
src/panel-service.mjs 面板操作:本地文件读写与独立 Kernel 会话
src/panel-server.mjs 面板操作:Jupyter Server 上的文件与共享 Kernel
client.js Client 侧栏 Notebook 编辑/查看面板
src/notebook.mjs nbformat 4.5 读写、cell id、revision
src/kernel.mjs 本地后端:Python 子进程管理、JSON 行协议客户端
src/jupyter-server.mjs 服务器后端:runtime 发现、REST contents/kernels、WebSocket 执行
kernel/dsh_kernel.py IPython 内核侧车(执行 / 输出捕获 / matplotlib / 中断)
skill/SKILL.md 给 Agent 的工作流提示词
scripts/smoke-panel.mjs 面板本地后端冒烟(真实 Python Kernel)
scripts/smoke-panel-server.mjs 面板服务后端冒烟(临时起一个 Jupyter Server)
scripts/test-markdown.mjs 面板 markdown 渲染器单测
scripts/test-streaming.mjs 面板执行流式输出时序测试
scripts/test-route.mjs 面板 Host 路由:来源校验、分发、流式响应
scripts/smoke.mjs 本地后端端到端冒烟
scripts/smoke-server.mjs 服务器后端端到端冒烟
scripts/install.mjs 写入/更新 profile 里的 MCP 服务配置块
examples/tour.ipynb 测试时生成的演示 notebookThis server cannot be deployed
Maintenance
Related MCP Connectors
System-of-record notebook for AI coding agents: pages, datastores, tasks, skills over MCP.
Use your Mac, Windows or Linux computer from ChatGPT, Claude or Codex: files, commands, documents.
Control a real browser from AI agents: navigate, click, type, screenshot, read the page.
PDF, image, video, OCR, screenshot, SQL, QR and text tools for agents. No API key, no signup.
Related MCP Servers
- AlicenseAqualityCmaintenanceEnables AI agents to interact with Jupyter notebooks via MCP tools for querying, modifying, executing, and setting up notebooks, with state preservation and real-time collaboration.445Apache 2.0
- AlicenseAqualityDmaintenanceEnables programmatic interaction with Jupyter notebooks, allowing reading, editing, and executing cells via Claude.646 PyPI34MIT
- AlicenseAqualityCmaintenanceEnables AI agents to create, read, edit, and execute Jupyter notebook cells, manage kernels, and connect to remote Jupyter servers.2123 PyPIMIT
- FlicenseNot gradedqualityDmaintenanceEnables AI agents to execute Jupyter notebook cells with persistent kernel state, output persistence, and structured JSON control surface.2-