jupyter-rmcp (tmlksu/jupyter-rmcp) is an MCP server listed on the M8ven Trust Index. It scores 22 out of 100, grade F. It declares 31 tools. No publisher has claimed this listing.

F
Warning
22/100

jupyter-rmcp

A self-hosted MCP server providing Claude with an interactive Jupyter environment, including real kernels, persistent notebooks, and optional GPU offload to Google Colab.

Warning. Serious findings were identified. Review the full report before connecting. Grades reflect the full trust pyramid: code, verification depth, and reputation. New projects cap at C until adoption is earned.

How we verified

⚡ Live Monitored: not connected

Verified is a snapshot. Live keeps it current, and builds your track record.

⚡ Connect GitHub → continuous verification on every pushwhy connect →

Who stands behind it

tmlksu

Source: Glama

Is this your MCP?

Claim it to get a verified publisher badge, a free copy of our full audit findings, and direct contact for any high-priority issues we find. Or connect your repo for our deepest verification, Live Monitored: read-only, revoke anytime. What we access →

Install from

The grade above is for the source repository. Registries can serve a different version, so we mark the ones we were not able to read.

// key findings
⚠️
Tool annotations don’t match behaviour
1 read-only tool performs write/delete/exec — colab_log (line 256: os.unlink(tmp.name))
⚠️
Tool descriptions don’t match what handlers do
1 tool describes read intent but its handler mutates — colab_log (line 256: os.unlink(tmp.name))
No credential exfiltration, no sensitive file access, no obfuscation
Static analysis found nothing flowing your secrets to unexpected places.
Open source with a license and README
Anyone can audit the code, the license is declared, and the publisher documents what it does.
🔐
You'll be asked for 5 credentials: JUPYTER_TOKEN, KAGGLE_API_TOKEN, KAGGLE_KEY, HF_TOKEN, HUGGING_FACE_HUB_TOKEN
These are read from process.env at runtime. Make sure you trust where they’ll be sent.
// tools this server exposes31 tools

These names and descriptions are the publisher's own, read from the source code. We print them as written. Our assessment is the findings above, not this list.

execute_code

Run ad-hoc Python in the kernel (stateful; variables persist across calls) and **append** it as a new cell to the bound notebook (if any). For iterating on an EXISTING cell without duplicating it, use execute_cell / edit_cell instead. On timeout the kernel is interrupted. Works for local and colab b

get_job

Poll a background job started by execute_code(background=True): returns its `status` ("running_in_background" / "done" / "error" / "unknown") and a WINDOW of the stdout+stderr it has captured (unbuffered — live progress shows). Cheap, non-blocking; call repeatedly until status is no longer "running_

list_kernels

List running kernels across all backends (local + registered Colab), with their backend, notebook binding, state, idle/age seconds, and pin status.

start_kernel

Start a notebook kernel and return its kernel_id (use it with execute_code / add_cell / execute_cell). Work is saved to a notebook ON THE SERVER (viewable/editable in JupyterLab).

stop_kernel

Terminate a kernel (and its session, if any) and free its resources. For a COLAB kernel this DESTROYS the VM — all /content files and pip installs on it are lost, and a later start_kernel gives a brand-new empty VM. To merely reset Python state while keeping the VM + files, use restart_kernel instea

restart_kernel

Restart a kernel, clearing all in-memory state (variables) but keeping the same id. For a COLAB kernel this restarts ONLY the Python process — the VM survives, so /content files, the HuggingFace/model cache and pip-installed packages persist; just the interpreter (and its module cache) is fresh. Use

interrupt_kernel

Interrupt a running kernel (raise KeyboardInterrupt) to stop a runaway execution. LOCAL kernels only — Colab has no interrupt.

colab_log

Review a COLAB session's recent COMPLETED executions — each one's code AND the output it captured — WITHOUT re-running anything. Handy to retrieve a past cell's result or confirm what already ran on the VM. `limit` = how many recent executions to return. IMPORTANT: an execution is logged only when i

pin_kernel

Pin/unpin a kernel to exempt it from the IDLE reaper (e.g. a long-lived notebook). Note: pinning does NOT exempt it from the absolute max-age hard cap (KERNEL_MAX_AGE_SEC) — nothing lives past that. Pin state persists across MCP restarts (kept in the kernel registry).

list_variables

List the user-defined variables currently held in the kernel (name/type/size).

list_backends

List available compute backends for start_kernel: `local` (the server's own Jupyter) and `colab` (official colab-cli, GPU on demand) if configured. Shows kind, reachability, and `exec_enabled` — false for `local` when the server runs colab-only, meaning it still stores/serves notebooks but refuses t

notebook_rev

Current revision token of a notebook: {path, rev, cells}. `rev` is a content hash — pass it as `expected_rev` to an editing tool to guard against a concurrent external edit (e.g. a human in JupyterLab). Mutating tools also return the new rev.

list_cells

Overview of a notebook's cells (no full source): per cell {index, id, type, summary, num_lines, has_outputs, has_error}. `id` is stable across insert/delete/ move — prefer addressing later edits by `id`. Also returns the notebook `rev`.

read_cells

Read full source (+ a text summary of outputs) for specific cells, by `indices` OR `ids` (batch — one round-trip). Omit both to read all cells.

insert_cells

Insert several cells at once, contiguously BEFORE `index` (index == cell count appends). `cells` = list of {cell_type, source, summary?}. Prefer this over many single inserts. Returns {indices, ids, rev}.

insert_cell

Insert one cell BEFORE `index` (index == cell count appends). For a block of cells prefer insert_cells. Returns {index, id, rev}.

patch_cell

PREFERRED edit: replace a UNIQUE `old` substring with `new` in one cell (cheap — no full-source resend). Target by `cell_id` (stable, preferred) OR `index`. `old` must occur exactly once in the cell, else it errors (safer than a wrong guess). Does not touch outputs. Returns {index, id, rev}.

edit_cell

Replace a cell's ENTIRE source (for small changes prefer patch_cell). Target by `cell_id` (preferred) OR `index`. `summary` sets metadata summary ("" clears). Does not execute or touch outputs. Returns {index, id, rev}.

delete_cell

Delete a cell, addressed by `cell_id` (preferred) OR `index`. Returns {rev, remaining}.

move_cell

Move a cell to `to_index` (final 0-based position). Address the moved cell by `from_id` (preferred) OR `from_index`. Returns {rev}.

execute_cell

Run an EXISTING code cell in the kernel's bound notebook and update THAT cell's outputs in place (no duplicate). Target by `cell_id` (stable, preferred) OR `index`. Editing (patch_cell/edit_cell) is separate — this only runs a cell as-is.

create_notebook

Create a new notebook (.ipynb) under the work root, optionally seeded with `cells` (list of {cell_type, source, summary?}). To inspect/edit existing notebooks use list_cells / read_cells / patch_cell etc.

setup_kaggle

Make Kaggle usable in this kernel (`!kaggle datasets download …`). For LOCAL kernels this is already configured (no-op). For a COLAB kernel it injects the server-side token into that Colab VM: the token is uploaded as a file and loaded into the VM env (`KAGGLE_API_TOKEN`) + `~/.kaggle/`, so it never

setup_hf

Make a HuggingFace token available in this kernel WITHOUT it appearing in exec/session history — needed for gated/private repos (`hf_hub_download`, `from_pretrained`). Same masked-injection design as setup_kaggle: for a COLAB kernel the token is uploaded as a file and loaded into the VM env (`HF_TOK

upload_to_colab

Copy a file from the server workspace (uploaded via JupyterLab / upload_file / fetch_to_workspace) ONTO the Colab VM for this kernel, so the notebook can open it there. `remote_path` defaults to /content/<basename>. Local kernels already see workspace files directly (no copy needed).

download_from_colab

Copy a file FROM the Colab VM (e.g. a result/checkpoint the notebook produced) back into the server workspace so it persists and is visible in JupyterLab. `workspace_path` defaults to the remote basename at the work root. Colab kernels only.

list_notebooks

List notebooks and subdirectories under `path` (relative to the work root). For ALL files (data, images, etc.) use list_files.

list_files

List EVERYTHING (files + folders) under `path` in the workspace — notebooks, uploaded data, images, etc. Files live on the server (persistent) and are visible to kernels (cwd is the work root) and in JupyterLab.

create_folder

Create a folder (and any missing parent folders) under the work root. Notebook/ file writes also auto-create parents, so you rarely need this explicitly.

upload_file

Write a file into the workspace from base64 bytes (binary-safe; persists on the server, visible to kernels and JupyterLab). Auto-creates parent folders. For a human uploading from a phone/laptop, JupyterLab's Upload button is usually easier; use this when a client can provide the bytes (e.g. Claude

fetch_to_workspace

Download a URL to a file in the workspace, server-side (the server fetches it). Handy to bring in a test image/dataset by link when you can't upload from the device. Auto-creates parent folders; capped at 200 MB.

// environment variables
To run this server yourself, you supply these values. They go in your own MCP client configuration and stay on your machine. The secret label means the value is sensitive, not that the server mishandles it.
🔐 secretJUPYTER_TOKENand MCP_BEARER, then docker compose up -d --build.
configCOLAB_ONLYKaggle on a laptop: =1 makes every kernel a Colab VM under
configGOOGLE_APPLICATION_CREDENTIALS
🔐 secretKAGGLE_API_TOKENKaggle: set in .env (kaggle.com/settings/api →
configKAGGLE_USERNAME
🔐 secretKAGGLE_KEY
🔐 secretHF_TOKEN
🔐 secretHUGGING_FACE_HUB_TOKEN
// quality suggestions

Tool annotations

5/31 tools have annotations

Add readOnlyHint or destructiveHint annotations to every tool so hosts can warn users before invoking.

All four hints declared on every tool

31/31 tools missing one or more hints — execute_code (missing: readOnlyHint, destructiveHint, idempotentHint, openWorldHint); get_job (missing: destructiveHint, idempotentHint, openWorldHint); list_kernels (missing: readOnlyHint, destructiveHint, idempotentHint, openWorldHint), +28 more. OpenAI's directory rejects tools where any of the four hints are missing or non-boolean.

For every tool, set all four hints (readOnlyHint, destructiveHint, idempotentHint, openWorldHint) to explicit true/false values that match the handler’s actual behaviour.

Tool annotations match behaviour

1 read-only tool performs write/delete/exec — colab_log (line 256: os.unlink(tmp.name))

Either remove the readOnlyHint:true annotation, or remove the write/delete call from the tool handler.

Destructive tools are labelled

5 tools perform destructive updates without destructiveHint — colab_log deletes at line 256 (os.unlink(tmp.name)); setup_kaggle deletes at line 50 ("p.unlink(missing_ok=True); print('kaggle configured (token)')\n"); setup_hf deletes at line 107 ("p.unlink(missing_ok=True); print('hf token configured')\n")

Add destructiveHint:true to any tool whose handler calls .delete(), .upsert(), .update(), unlink, rm, DELETE, DROP, REPLACE INTO, or any operation that overwrites existing data.

Descriptions match behaviour

1 tool describes read intent but its handler mutates — colab_log (line 256: os.unlink(tmp.name))

Rename the tool, rewrite the description, or move the side-effect into a separate clearly-named tool.

Tool inputs are validated

29/31 tool handlers declare input schemas (94%)

Declare an inputSchema with zod/joi/yup on every tool definition.

Tool handlers catch errors

Only 10/31 tool handlers wrap calls in try/catch (32%)

Wrap each tool handler body in try/catch and return a structured error response.

Tests exist

No test files found

Add tests that exercise each declared tool.

Tool description accuracy

colab_log: description implies read-only but handler writes/deletes/executes

Update tool descriptions to accurately reflect all capabilities — especially write, delete, or execute operations.

Claim the listing to review these findings one by one and send us a correction where you disagree, straight to the team. Claiming also means we tell you when the grade moves, and reach you first if we find anything urgent.

// full audit trail
The findings above are the summary. The full trail, every check we ran, each deduction, the network hosts observed and the dependency advisories, goes to verified publishers, along with an alert whenever a new one lands. Verified publishers can also review each finding and dispute it in one click. Publisher corrections have sharpened several of our checks this month, because the maintainer knows the codebase better than any scanner.
// improvement guidance — verified publishers only
We have 9 concrete improvements we can share with the publisher of this MCP. Each comes with specific guidance to raise the trust score.
// embed badge in your README
[![M8ven Verified](https://m8ven.ai/badge/mcp/tmlksu/jupyter-rmcp?variant=verified)](https://m8ven.ai/mcp/tmlksu/jupyter-rmcp)
Shows verification status without the grade. Want the grade badge instead? Remove ?variant=verified from the URL.
commit: 23a2b2b7597c37f5065262d2bdbe38f40d0e97ac
code hash: 7adc2adf08810fcea50e1f39862129f84596e3ebe350dca9c3f967d8a42939d4
view raw JSON →
Check MCPs from inside your assistant
Tool Check · MCP

Vetting this one by hand? Tool Check is an MCP that scores other MCPs. Add it once and ask Claude, ChatGPT, or any MCP client to grade a server, surface CVEs, check the publisher, and suggest safer alternatives — before you install.

https://m8ven.ai/api/mcp/tool-check
check_toolsearch_toolscompare_toolsrecommend_alternativescheck_publisherreport_concern
How to add it →Free · no account needed · works in any MCP client