Skip to main content
Glama
block

Jupyter MCP Server

by block

Jupyter MCP Server

⚠️ API Compatibility Notice: This project is currently focused on MCP (Model Context Protocol) usage. There are no API compatibility guarantees between versions as the interface is actively evolving. Breaking changes may occur in any release.

Jupyter MCP Server allows you to use tools like Goose or Cursor to pair with you in a JupyterLab notebook where the state of your variables is preserved by the JupyterLab Kernel. This enables seamless collaboration where agents can install packages, fix errors, and hand off to you for data exploration at any time.

Architecture: Uses Jupyter's REST API for reliable agent operations while maintaining real-time user synchronization through RTC. See Architecture Documentation for detailed technical information.

Key Features

  • 4 Consolidated MCP Tools (reduced from 11):

    • query_notebook - All read-only operations (view source, check server, etc.)

    • modify_notebook_cells - All cell modifications (add, edit, delete cells)

    • execute_notebook_code - All execution operations (run cells, install packages)

    • setup_notebook - Notebook initialization and kernel connection

  • Workflow-oriented design optimized for AI agent collaboration

  • State preservation across notebook sessions

  • Automatic parameter validation with float-to-int conversion

This works with any client that supports MCP but will focus on using Goose for the examples.

Related MCP server: JupyterMCP

Requirements

You will need UV is required to be installed.

Installation

This MCP server supports multiple transport modes and can be added to client with the command uvx mcp-jupyter.

Transport Modes

The server supports two transport protocols:

  • stdio (default) - Standard input/output communication, ideal for local IDE integrations

  • http - Streamable HTTP transport with session management, enabling serverless deployments and remote access

Use Cases for HTTP Transport

  • Serverless deployments: Host the MCP server in cloud environments (AWS Lambda, Google Cloud Functions, etc.)

  • Remote access: Connect to the server from different machines or networks

  • Web integrations: Build web-based AI assistants that connect to the MCP server

  • Stateless operations: Use --stateless-http for environments where session persistence isn't needed

To use a specific transport:

# Default stdio transport
uvx mcp-jupyter

# HTTP transport on custom port (stateful - maintains session)
uvx mcp-jupyter --transport http --port 8080

# HTTP transport in stateless mode (no session persistence)
uvx mcp-jupyter --transport http --port 8080 --stateless-http

Using HTTP Transport with Cursor

To connect Cursor to an HTTP MCP server:

  1. Start the server separately:

uvx mcp-jupyter --transport http --port 8090
  1. Configure Cursor's .cursor/mcp.json:

{
  "mcpServers": {
    "notebook-http": {
      "url": "http://localhost:8090/mcp/"  // ⚠️ Trailing slash is REQUIRED
    }
  }
}

Important: The trailing slash (/mcp/) is required for Cursor to connect properly to the HTTP endpoint.

Usage

Start Jupyter

The server expects that a server is already running on a port that is available to the client. If the environmental variable TOKEN is not set, it will default to "BLOCK".

Option 1: With Real-Time Collaboration (Recommended)

Real-time collaboration (jupyter-collaboration) enables automatic synchronization between the AI agent and your notebook interface. Changes made by the agent appear instantly in your browser.

# Using uv venv
uv venv
source .venv/bin/activate  # On Windows: .venv\Scripts\activate
uv pip install jupyterlab jupyter-collaboration ipykernel
jupyter lab --port 8888 --IdentityProvider.token BLOCK --ip 0.0.0.0

# OR using uv project
uv init jupyter-workspace && cd jupyter-workspace
uv add jupyterlab jupyter-collaboration ipykernel
uv run jupyter lab --port 8888 --IdentityProvider.token BLOCK --ip 0.0.0.0

Option 2: Without Real-Time Collaboration

You can use MCP Jupyter without jupyter-collaboration, but you'll need to manually sync changes:

# Using uv venv
uv venv
source .venv/bin/activate  # On Windows: .venv\Scripts\activate
uv pip install jupyterlab ipykernel
jupyter lab --port 8888 --IdentityProvider.token BLOCK --ip 0.0.0.0

# OR using uv project
uv init jupyter-workspace && cd jupyter-workspace
uv add jupyterlab ipykernel
uv run jupyter lab --port 8888 --IdentityProvider.token BLOCK --ip 0.0.0.0

Important Workflow Differences Without RTC:

  • After the agent makes changes: Use the "Reload Notebook from Disk" command in JupyterLab to see the updates

  • After you edit in the notebook: Click Save (Ctrl+S / Cmd+S) so the agent can see your changes

With RTC enabled, these manual steps are not needed - changes sync automatically.

Goose Usage

Here's a demonstration of the tool in action:

MCP Jupyter Demo

You can view the Generated notebook here: View Demo Notebook

Development

Steps remain similar except you will need to clone this mcp-jupyter repository and use that for the server instead of the precompiled version.

MCP Server

  1. Clone and setup the repository:

mkdir ~/Development
cd ~/Development
git clone https://github.com/block/mcp-jupyter.git
cd mcp-jupyter

# Sync all dependencies
uv sync

Using editable mode allows you to make changes to the server and only have you need to restart Goose, etc. goose session --with-extension "uv run --directory $(pwd) mcp-jupyter"

LLM Evaluation

This project includes a comprehensive testing infrastructure for validating how well different LLMs can generate MCP tool calls from natural language prompts.

Test Architecture

The LLM testing system uses a pluggable provider architecture:

  • LLMProvider: Abstract base class that all providers implement

  • LLMResponse: Standardized response format with success metrics and metadata

  • Parameterized tests: Same test runs against all available providers

Current Providers

  • ClaudeCodeProvider: Uses the Claude Code SDK (no API key required)

Running LLM Tests

# Run LLM tool call generation tests
uv run pytest -m llm -v

# See LLM working in real-time (shows detailed progress)
uv run pytest -m llm -v -s

# Run all tests except LLM tests (default behavior)
uv run pytest -v

What the Tests Validate

Each LLM provider is tested on its ability to:

  1. Understand natural language prompts about Jupyter notebook tasks

  2. Generate correct MCP tool calls (query_notebook, setup_notebook, modify_notebook_cells)

  3. Successfully execute the calls to create notebooks with expected content

  4. Handle errors gracefully when operations fail

Adding New Providers

To add a new LLM provider:

  1. Implement the interface:

# tests/llm_providers/my_llm.py
from .base import LLMProvider, LLMResponse

class MyLLMProvider(LLMProvider):
    @property
    def name(self) -> str:
        return "my-llm"

    async def send_task(self, prompt: str, server_url: str, verbose: bool = False):
        # Implement LLM interaction
        pass

    async def get_final_response(self) -> LLMResponse:
        # Return standardized response
        pass

    async def cleanup(self):
        # Clean up resources
        pass
  1. Update configuration:

# tests/llm_providers/config.py - add to get_available_providers()
if os.getenv("MY_LLM_API_KEY"):
    from .my_llm import MyLLMProvider
    providers.append(MyLLMProvider())
  1. Test automatically: Your provider will be included in parameterized tests when its environment variables are set.

This infrastructure makes it easy to validate and compare how different LLMs perform at generating MCP tool calls for Jupyter notebook automation.

Available Tools

4 tools
execute_notebook_codeA

Execute code in a Jupyter notebook on the user-provided server.

This consolidates all code execution operations into a single tool following MCP best practices.

IMPORTANT: Server URL Configuration

This tool requires that you first call setup_notebook with the correct server URL:

Required setup: setup_notebook("my_notebook", server_url="http://localhost:9999\")

Then you can use this tool: execute_notebook_code("my_notebook", "execute_cell", position_index=0)

Without setup_notebook, this will try to connect to http://localhost:8888 by default.

Args: notebook_path: Path to the notebook file (.ipynb extension will be added if missing), relative to the Jupyter server root. execution_type: Type of execution operation. Options: - 'execute_cell': Execute an existing code cell - 'install_packages': Install packages using uv pip in the notebook environment position_index: (For execute_cell) Positional index of cell to execute package_names: (For install_packages) Space-separated list of package names to install

Returns

Union[dict, str]:
    - execute_cell: dict with execution_count, outputs, status
    - install_packages: str with installation result message

Raises

ValueError: If invalid execution_type or missing required parameters
McpError: If there's an error connecting to the Jupyter server
IndexError: If position_index is out of range
RuntimeError: If kernel execution fails
ParametersJSON Schema
NameRequiredDescriptionDefault
notebook_pathYes
execution_typeYes
position_indexNo
package_namesNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description covers setup dependency, default URL, execution types, return types, and errors. However, it does not disclose side effects (modifying notebook state) or safety considerations (e.g., code execution risks). Good but not fully comprehensive.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well-structured with sections for setup, args, returns, raises. Front-loaded with purpose. Example code block is helpful. Minor bloat: redundant 'MCP best practices' line and repeated text. Still efficient for the complexity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers all parameters, returns, errors, and setup dependency. Output schema exists, so return details not required. Lacks explanation of invalid notebook_path handling or deeper return structure usage. Adequate for a tool with moderate complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so description compensates fully. Explains notebook_path with .ipynb addition, execution_type with two named options, position_index for execute_cell, and package_names for install_packages. Adds critical meaning beyond types and defaults.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clearly states 'Execute code in a Jupyter notebook on the user-provided server.' Differentiates from sibling tools (modify_notebook_cells, query_notebook, setup_notebook) by focusing on execution operations. Consolidates all execution types into one tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit setup requirement (must call setup_notebook first) and describes default behavior. Lists two execution types with corresponding parameters. Lacks explicit alternatives (e.g., when to use modify_notebook_cells instead), but the context is strong enough for an agent to infer.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

modify_notebook_cellsA

Modify notebook cells (add, edit, delete) on the user-provided server.

This consolidates all cell modification operations into a single tool following MCP best practices. Default to execute=True unless the user requests otherwise or you have good reason not to execute immediately.

IMPORTANT: Server URL Configuration

This tool requires that you first call setup_notebook with the correct server URL:

Required setup: setup_notebook("my_notebook", server_url="http://localhost:9999\")

Then you can use this tool: modify_notebook_cells("my_notebook", "add_code", "print('Hello')")

Without setup_notebook, this will try to connect to http://localhost:8888 by default.

Args: notebook_path: Path to the notebook file (.ipynb extension will be added if missing), relative to the Jupyter server root. operation: Type of cell operation. Options: - 'add_code': Add (and optionally execute) a code cell at end or specific position - 'edit_code': Edit a code cell at specific position - 'add_markdown': Add a markdown cell at end or specific position - 'edit_markdown': Edit an existing markdown cell at specific position - 'delete': Delete a cell at specific position cell_content: Content for the cell (required for add_code, edit_code, add_markdown, edit_markdown) position_index: Position index (0-indexed cell location) for operations. Must be an integer. - Optional for add_code/add_markdown: if provided, inserts at that position; if not, adds at end - Required for edit_code/edit_markdown/delete: specifies which cell to modify Examples: position_index=0 (first cell), position_index=2 (third cell) execute: Whether to execute code cells after adding/editing (default: True)

Returns

dict: Operation results containing:
    - For add_code/edit_code with execute=True: execution_count, outputs, status
    - For add_code/edit_code with execute=False: empty dict
    - For add_markdown/edit_markdown: message and error fields
    - For delete: message and error fields

Raises

ValueError: If invalid operation or missing required parameters
McpError: If there's an error connecting to the Jupyter server
IndexError: If position_index is out of range
ParametersJSON Schema
NameRequiredDescriptionDefault
notebook_pathYes
operationYes
cell_contentNo
position_indexNo
executeNo

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description fully bears the burden of disclosing behavior. It details execution default, error types (ValueError, McpError, IndexError), and return values per operation, leaving no behavioral ambiguity.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but well-organized with clear sections (Args, Returns, Raises) and front-loaded purpose. Minor redundancy exists (e.g., repeating default execute behavior), but overall it is efficient for the information provided.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, the description comprehensively covers return values for all operations and lists potential errors. It also clarifies the dependency on setup_notebook, making the tool fully self-contained in context.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must explain each parameter. It does so thoroughly, including examples, default values, and conditionally required fields (e.g., position_index for edit/delete). This adds significant value beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool modifies notebook cells (add, edit, delete) and explicitly distinguishes from siblings by noting it consolidates all cell modification operations. The verb 'modify' and specific operations listed make the purpose unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit guidance on prerequisite setup (calling setup_notebook) and default behavior (execute=True). It does not explicitly contrast with siblings like execute_notebook_code, but the context is clear enough for an agent to infer appropriate usage.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

query_notebookA

Query notebook information and metadata on the user-provided server.

This consolidates all read-only operations into a single tool following MCP best practices.

IMPORTANT: Server URL Configuration

This tool requires a server URL to connect to your Jupyter server. You have two options:

Option 1 - Call setup_notebook first (RECOMMENDED): setup_notebook("my_notebook", server_url="http://localhost:9999") query_notebook("my_notebook", "view_source") # Uses stored URL automatically

Option 2 - Pass server_url explicitly every time: query_notebook("my_notebook", "view_source", server_url="http://localhost:9999")

If neither is done, it defaults to http://localhost:8888 which may not be correct.

Args: notebook_path: Path to the notebook file (.ipynb extension will be added if missing), relative to the Jupyter server root. query_type: Type of query to perform. Options: - 'view_source': View source code of notebook (single cell or all cells) - 'check_server': Check if Jupyter server is running and accessible - 'list_sessions': List all notebook sessions on the server - 'get_position_index': Get the index of a code cell execution_count: (For view_source/get_position_index) The execution count to look for. IMPORTANT: This is the number shown in square brackets like [3] in Jupyter UI. Only available for executed code cells. Must be an integer (e.g., 3). COMMON MISTAKE: Don't confuse with position_index! - execution_count=3 finds the cell that was executed 3rd (shows [3] in Jupyter) - position_index=3 finds the 4th cell in the notebook (0-indexed position) position_index: (For view_source) The position index to look for. This is the cell's physical position in the notebook (0-indexed). Examples: first cell = 0, second cell = 1, third cell = 2, etc. Works for all cell types (code, markdown, raw). Must be an integer. cell_id: (For get_position_index) Cell ID like "205658d6-093c-4722-854c-90b149f254ad". This is a unique identifier for each cell, visible in notebook metadata. server_url: Server URL to connect to. If not provided, uses the URL stored by setup_notebook, or falls back to http://localhost:8888

Returns

Union[dict, list, str, int]:
    - view_source: dict (single cell) or list[dict] (all cells) with cell contents/metadata
    - check_server: str status message
    - list_sessions: list of notebook sessions
    - get_position_index: int positional index

Examples

# View all cells in notebook
query_notebook("my_notebook.ipynb", "view_source")

# View cell by execution count (the [3] shown in Jupyter UI)
query_notebook("my_notebook.ipynb", "view_source", execution_count=3)

# View cell by position (first cell=0, second=1, etc)
query_notebook("my_notebook.ipynb", "view_source", position_index=0)

# Get position index of cell with execution count [5]
query_notebook("my_notebook.ipynb", "get_position_index", execution_count=5)

# Get position index by cell ID
query_notebook("my_notebook.ipynb", "get_position_index", cell_id="205658d6-093c-4722-854c-90b149f254ad")

Raises

ValueError: If invalid query_type or missing required parameters
McpError: If there's an error connecting to the Jupyter server
ParametersJSON Schema
NameRequiredDescriptionDefault
notebook_pathYes
query_typeYes
execution_countNo
position_indexNo
cell_idNo
server_urlNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Without annotations, the description fully discloses behavioral traits: it's read-only (no mutations), handles connection to Jupyter server with defaults, and enumerates all query types with their effects. It also lists possible exceptions (ValueError, McpError) for error handling transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with clear sections (introduction, configuration note, args, returns, examples, raises). However, it is somewhat verbose, especially with the configuration note being repeated in the args section. A slightly more concise version would be ideal, but the organization is good.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite no annotations, the description is comprehensive: it covers all 6 parameters, 4 query types with behaviors, return types, default values, error cases, and provides multiple examples. The output schema is effectively described in the Returns section, making the tool fully understandable without external documentation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description compensates thoroughly. It explains each parameter in detail, including the distinction between execution_count and position_index, the automatic .ipynb extension, and the purpose of server_url. This adds essential meaning beyond the bare schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it queries notebook information and metadata, consolidating all read-only operations. It distinguishes itself from sibling tools like execute_notebook_code and modify_notebook_cells, making its purpose unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit guidance on when to use this tool (read-only queries) versus alternatives (execute or modify). It also offers a recommended workflow with setup_notebook, explains server URL configuration, and warns against common parameter confusion, leaving no doubt about usage context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

setup_notebookA

Prepare notebook for use and connect to the kernel on the user-provided server. Will create a new empty Jupyter notebook if needed on the server.

CALL THIS FIRST - This tool must be called before using other notebook tools to establish the server URL connection. All subsequent notebook operations will use the server URL stored by this tool.

This tool creates an empty notebook. To add content, use the modify_notebook_cells tool after creation:

Example usage: # Step 1: REQUIRED - Setup notebook with correct server URL setup_notebook("demo", server_url="http://localhost:9999")

# Step 2: Add cells (these now use the stored server URL automatically)
modify_notebook_cells("demo", "add_markdown", "# Title\\n\\nDescription")
modify_notebook_cells("demo", "add_code", "print('Hello World')")

This tool assumes a Jupyter server is already running and accessible at the specified server_url. It connects to this existing server to manage the notebook.

Note that notebook_path must be relative to the Jupyter server root, not an absolute filesystem path.

Args: notebook_path: Path to the notebook, relative to the Jupyter server root. server_url: Jupyter server URL (HIGHLY RECOMMENDED to specify explicitly). This URL will be stored and used for subsequent interactions with this notebook. If not provided, defaults to http://localhost:8888 which may not be correct for your setup. Common values: http://localhost:8888, http://localhost:9999, etc.

Returns

dict: Information about the notebook and status message.
ParametersJSON Schema
NameRequiredDescriptionDefault
notebook_pathYes
server_urlNo

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Discloses that it connects to an existing server, stores the server URL for subsequent calls, and creates an empty notebook if needed. Does not mention overwriting behavior or authentication, but covers core behavioral traits. Annotations are absent, so description carries the burden.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with bold emphasis on key points, an example, and bullet-style parameter explanations. It is somewhat lengthy but each part adds value; slight redundancy in storage explanation could be trimmed.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, the description sufficiently explains the return value as a dict with status. It covers the tool's role in the workflow, parameter details, environmental assumption, and positioning relative to siblings. Complete for a setup tool with two parameters.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description compensates fully: explains notebook_path as relative to Jupyter server root, and server_url with explicit recommendation, default, common values, and storage behavior. This provides essential meaning beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool prepares a notebook and connects to a kernel, with specific actions: 'Prepare notebook for use and connect to the kernel' and 'Will create a new empty Jupyter notebook if needed'. This distinguishes it from sibling tools like modify_notebook_cells and execute_notebook_code.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly declares 'CALL THIS FIRST' and states it must be called before other notebook tools. Provides example usage showing the correct sequence and mentions alternatives like modify_notebook_cells for adding content. Also notes the required prerequisite of a running Jupyter server.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 4 tool updatesv2.0.2
    • First observedexecute_notebook_code
    • First observedmodify_notebook_cells
    • First observedquery_notebook
    • First observedsetup_notebook

TDQS

A4.6/5.0
Disambiguation5/5

Each tool has a clearly distinct purpose: setup_notebook initializes and connects, execute_notebook_code runs code, modify_notebook_cells edits cells, and query_notebook retrieves information. No overlap in functionality.

Naming Consistency5/5

All tools follow a consistent verb_noun pattern with underscores (setup_notebook, execute_notebook_code, modify_notebook_cells, query_notebook). The naming is predictable and clear.

Tool Count4/5

With 4 tools, the count is appropriate for a Jupyter notebook server. Each tool is well-scoped, though some tools encapsulate multiple sub-operations, which could be split but is not problematic.

Completeness4/5

The tool surface covers the essential operations: setup, code execution, cell modification, and querying. Minor gaps like kernel management or file uploads are absent but not critical for basic notebook interaction.

Maintenance

ActivityInactive
ResponsivenessUnresponsive

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/block/mcp-jupyter'

If you have feedback or need assistance with the MCP directory API, please join our Discord server