Jupyter Server MCP
Provides tools for interacting with a Jupyter Server, enabling AI agents to manage notebooks, cells, and execute commands through the Jupyter platform.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Jupyter Server MCPlist the registered tools and functions"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Jupyter Server MCP Extension
A configurable MCP (Model Context Protocol) server extension for Jupyter Server that allows dynamic registration of Python functions as tools accessible to MCP clients from a running Jupyter Server.
https://github.com/user-attachments/assets/aa779b1c-a443-48d7-b3eb-13f27a4333b3
Overview
This extension provides a simplified, trait-based approach to exposing Jupyter functionality through the MCP protocol. It can dynamically load and register tools from various Python packages, making them available to AI assistants and other MCP clients.
Key Features
Simplified Architecture: Direct function registration without complex abstractions
Configurable Tool Loading: Register tools via string specifications (
module:function)Automatic Tool Discovery: Python packages can expose tools via entrypoints
Jupyter Integration: Seamless integration with Jupyter Server extension system
Streamable HTTP Transport: FastMCP-based HTTP server with proper MCP protocol support
Stdio Proxy: Stable
jupyter-server-mcp-proxy/python -m jupyter_server_mcp.proxyentry point that auto-discovers the running Jupyter MCP server — client configuration stays the same even if the port changes, and it is launchable viauvxfrom outside the Jupyter environmentMulti-Instance Ready: Set
mcp_port = 0to ask the OS for a free ephemeral port, so multiple Jupyter servers can run in parallel; the stdio proxy auto-discovers whichever port was chosenTraitlets Configuration: Full configuration support through Jupyter's traitlets system
Installation
Install jupyter-server-mcp into the same environment as Jupyter Server or JupyterLab.
pip
python -m pip install jupyter-server-mcpconda / mamba / micromamba
conda install -c conda-forge jupyter-server-mcp
mamba install -c conda-forge jupyter-server-mcp
micromamba install -c conda-forge jupyter-server-mcppixi
In an existing Pixi workspace:
# If conda-forge is not already configured for the workspace
pixi project channel add conda-forge
pixi add jupyter-server-mcpQuick Start
1. Basic Configuration
Create a jupyter_config.py file:
c = get_config()
# Basic MCP server settings
c.MCPExtensionApp.mcp_name = "My Jupyter MCP Server"
# The MCP server listens on port 3001 by default. Override it with:
# c.MCPExtensionApp.mcp_port = 8080
# Set to 0 to let the OS pick a free port — useful when running multiple
# Jupyter servers side by side. The stdio proxy (below) auto-discovers the
# chosen port, so clients do not need to be reconfigured.
# c.MCPExtensionApp.mcp_port = 0
# Register tools from existing packages
c.MCPExtensionApp.mcp_tools = [
# Standard library tools
"os:getcwd",
"json:dumps",
"time:time",
# Jupyter AI Tools - Notebook operations
"jupyter_ai_tools.toolkits.notebook:read_notebook",
"jupyter_ai_tools.toolkits.notebook:edit_cell",
# JupyterLab Commands Toolkit
"jupyterlab_commands_toolkit.tools:list_all_commands",
"jupyterlab_commands_toolkit.tools:execute_command",
]2. Start Jupyter Server
jupyter lab --config=jupyter_config.pyBy default, the MCP server listens on port 3001. If that port is already in
use — for example when a second Jupyter server is already running — startup
fails with a clear error instead of silently choosing another port. To run
multiple Jupyter servers side-by-side, set c.MCPExtensionApp.mcp_port = 0 so
the OS assigns a free port. The stdio proxy (see below) auto-discovers
whichever port was chosen, so client configuration does not need to change.
Any trait can also be set on the command line:
jupyter lab --MCPExtensionApp.mcp_port=80803. CLI MCP Client Configuration
There are two supported ways to wire an MCP client to this extension:
Stdio proxy (recommended) — the client launches a small stdio proxy (
jupyter-server-mcp-proxyorpython -m jupyter_server_mcp.proxy), which auto-discovers the running Jupyter MCP server and bridges stdio to its HTTP endpoint. This keeps working unchanged when multiple Jupyter servers run side-by-side or whenmcp_port = 0picks a different port each run.Direct HTTP — point the client at
http://localhost:3001/mcp(or whichever port you configured). Works well when you run a single Jupyter server on a stable port.
When multiple Jupyter servers are running on the same machine, the stdio proxy picks the one whose Jupyter root directory is the most specific ancestor of the MCP client's current working directory. If no server's root directory contains that working directory, or if several tie, the proxy refuses to guess and asks you to disambiguate with --url or by setting JUPYTER_SERVER_MCP_URL.
The list below is intentionally curated rather than exhaustive and focuses on terminal-based coding agents. For a broader, community-maintained directory of MCP-compatible clients, see the MCP client directory: https://modelcontextprotocol.io/clients.
Option A — Stdio proxy (recommended)
The proxy can be launched in two ways:
uvx— ideal for MCP clients that are not installed inside the same Python environment as Jupyter. uv installsjupyter-server-mcpinto a cached, ephemeral environment and runs itsjupyter-server-mcp-proxyconsole script. The runtime info file the extension writes is stored in the per-user Jupyter runtime directory, so auto-discovery works across environments.python -m jupyter_server_mcp.proxy— use when the client is already running in an environment that hasjupyter-server-mcpinstalled.
The examples below show the uvx form. Swap in the python -m form by
replacing "command": "uvx", "args": ["--from", "jupyter-server-mcp", "jupyter-server-mcp-proxy"]
with "command": "python", "args": ["-m", "jupyter_server_mcp.proxy"].
Claude Code
Add the following to .mcp.json:
{
"mcpServers": {
"jupyter-mcp": {
"command": "uvx",
"args": ["--from", "jupyter-server-mcp", "jupyter-server-mcp-proxy"]
}
}
}Or use the claude CLI:
claude mcp add jupyter-mcp -- uvx --from jupyter-server-mcp jupyter-server-mcp-proxyCodex
Use the codex CLI:
codex mcp add jupyter-mcp -- uvx --from jupyter-server-mcp jupyter-server-mcp-proxyOr add the following to ~/.codex/config.toml:
[mcp_servers.jupyter-mcp]
command = "uvx"
args = ["--from", "jupyter-server-mcp", "jupyter-server-mcp-proxy"]OpenCode
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"jupyter-mcp": {
"type": "local",
"command": ["uvx", "--from", "jupyter-server-mcp", "jupyter-server-mcp-proxy"],
"enabled": true
}
}
}Gemini CLI
{
"mcpServers": {
"jupyter-mcp": {
"command": "uvx",
"args": ["--from", "jupyter-server-mcp", "jupyter-server-mcp-proxy"]
}
}
}Copilot CLI
{
"mcpServers": {
"jupyter-mcp": {
"type": "local",
"command": "uvx",
"args": ["--from", "jupyter-server-mcp", "jupyter-server-mcp-proxy"],
"tools": ["*"]
}
}
}Pin to a specific version with --from jupyter-server-mcp==X.Y.Z when you
need to match the server side exactly.
The proxy accepts a few optional arguments (append them to args):
--url URL— bypass auto-discovery and connect to an explicit MCP endpoint--runtime-dir DIR— look in a specific Jupyter runtime directory--cwd DIR— use a different directory when disambiguating between servers
JUPYTER_SERVER_MCP_URL is equivalent to --url and takes precedence over discovery when set.
Option B — Direct HTTP
The extension exposes a FastMCP streamable HTTP endpoint at
http://localhost:3001/mcp by default. Override the port with
c.MCPExtensionApp.mcp_port if you need a different one; replace 3001
below with whatever you chose. If a client asks for a transport type,
pick HTTP or Streamable HTTP.
Note: Direct HTTP requires a fixed, known port. If you set
c.MCPExtensionApp.mcp_port = 0for multi-instance support, use the stdio proxy instead — the ephemeral port is not suitable as a stable URL.
OpenCode
Use opencode mcp add, or add the following to opencode.json or ~/.config/opencode/opencode.json:
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"jupyter-mcp": {
"type": "remote",
"url": "http://localhost:3001/mcp",
"enabled": true
}
}
}Mistral Vibe
Add the following to ./.vibe/config.toml or ~/.vibe/config.toml:
[[mcp_servers]]
name = "jupyter-mcp"
transport = "streamable-http"
url = "http://localhost:3001/mcp"Claude Code
Add the following to .mcp.json:
{
"mcpServers": {
"jupyter-mcp": {
"type": "http",
"url": "http://localhost:3001/mcp"
}
}
}Or use the claude CLI:
claude mcp add --transport http jupyter-mcp http://localhost:3001/mcpCodex
Use the codex CLI:
codex mcp add jupyter-mcp --url http://localhost:3001/mcpOr add the following to ~/.codex/config.toml:
[mcp_servers.jupyter-mcp]
url = "http://localhost:3001/mcp"Gemini CLI
Add the following to .gemini/settings.json:
{
"mcpServers": {
"jupyter-mcp": {
"httpUrl": "http://localhost:3001/mcp"
}
}
}Copilot CLI
Use /mcp add in interactive mode, or add the following to ~/.copilot/mcp-config.json:
{
"mcpServers": {
"jupyter-mcp": {
"type": "http",
"url": "http://localhost:3001/mcp",
"tools": ["*"]
}
}
}Architecture
Core Components
MCPServer (jupyter_server_mcp.mcp_server.MCPServer)
A simplified LoggingConfigurable class that manages FastMCP integration:
from jupyter_server_mcp.mcp_server import MCPServer
# Create server
server = MCPServer(name="My Server", port=8080)
# Register functions
def my_tool(message: str) -> str:
return f"Hello, {message}!"
server.register_tool(my_tool)
# Start server
await server.start_server()Key Methods:
register_tool(func, name=None, description=None)- Register a Python functionregister_tools(tools)- Register multiple functions (list or dict)list_tools()- Get list of registered toolsstart_server(host=None)- Start the HTTP MCP server
MCPExtensionApp (jupyter_server_mcp.extension.MCPExtensionApp)
Jupyter Server extension that manages the MCP server lifecycle:
Configuration Traits:
mcp_name- Server name (default: "Jupyter MCP Server")mcp_port- Server port (default: 3001). Set to 0 to let the OS pick a free port — useful when running multiple servers side by side.mcp_tools- List of tools to register (format: "module:function")use_tool_discovery- Enable automatic tool discovery via entrypoints (default: True)
Tool Registration
Tools can be registered in two ways:
1. Manual Configuration
Specify tools directly in your Jupyter configuration using module:function format:
c.MCPExtensionApp.mcp_tools = [
"os:getcwd",
"jupyter_ai_tools.toolkits.notebook:read_notebook",
]2. Automatic Discovery via Entrypoints
Python packages can expose tools automatically using the jupyter_server_mcp.tools entrypoint group.
In your package's pyproject.toml:
[project.entry-points."jupyter_server_mcp.tools"]
my_package_tools = "my_package.tools:TOOLS"In my_package/tools.py:
# Option 1: Define as a list
TOOLS = [
"my_package.operations:create_file",
"my_package.operations:delete_file",
]
# Option 2: Define as a function
def get_tools():
return [
"my_package.operations:create_file",
"my_package.operations:delete_file",
]Tools from entrypoints are discovered automatically when the extension starts. To disable automatic discovery:
c.MCPExtensionApp.use_tool_discovery = FalseConfiguration Examples
Minimal Setup
c = get_config()
# The MCP server defaults to port 3001. Override it with:
# c.MCPExtensionApp.mcp_port = 8080
# Or set to 0 to let the OS pick a free port (requires the stdio proxy).Full Configuration
c = get_config()
# MCP Server Configuration
c.MCPExtensionApp.mcp_name = "Advanced Jupyter MCP Server"
c.MCPExtensionApp.mcp_port = 8080
c.MCPExtensionApp.mcp_tools = [
# File system operations (jupyter-ai-tools)
"jupyter_ai_tools.toolkits.file_system:read",
"jupyter_ai_tools.toolkits.file_system:write",
"jupyter_ai_tools.toolkits.file_system:edit",
"jupyter_ai_tools.toolkits.file_system:ls",
"jupyter_ai_tools.toolkits.file_system:glob",
# Notebook operations (jupyter-ai-tools)
"jupyter_ai_tools.toolkits.notebook:read_notebook",
"jupyter_ai_tools.toolkits.notebook:edit_cell",
"jupyter_ai_tools.toolkits.notebook:add_cell",
"jupyter_ai_tools.toolkits.notebook:delete_cell",
"jupyter_ai_tools.toolkits.notebook:create_notebook",
# Git operations (jupyter-ai-tools)
"jupyter_ai_tools.toolkits.git:git_status",
"jupyter_ai_tools.toolkits.git:git_add",
"jupyter_ai_tools.toolkits.git:git_commit",
"jupyter_ai_tools.toolkits.git:git_push",
# JupyterLab operations (jupyterlab-commands-toolkit)
"jupyterlab_commands_toolkit.tools:clear_all_outputs_in_notebook",
"jupyterlab_commands_toolkit.tools:open_document",
"jupyterlab_commands_toolkit.tools:open_markdown_file_in_preview_mode",
"jupyterlab_commands_toolkit.tools:show_diff_of_current_notebook",
# Utility functions
"os:getcwd",
"json:dumps",
"time:time",
"platform:system",
]Running Tests
# Install development dependencies
pip install -e ".[dev]"
# Run tests
pytest tests/ -v
# Run with coverage
pytest --cov=jupyter_server_mcp tests/Project Structure
jupyter_server_mcp/
├── jupyter_server_mcp/
│ ├── __init__.py
│ ├── mcp_server.py # Core MCP server implementation
│ ├── extension.py # Jupyter Server extension
│ ├── proxy.py # Stdio MCP proxy entrypoint (python -m jupyter_server_mcp.proxy)
│ └── runtime.py # Runtime info-file helpers shared between the extension and the proxy
├── tests/
│ ├── test_mcp_server.py # MCPServer tests
│ ├── test_extension.py # Extension tests
│ ├── test_proxy.py # Stdio proxy tests
│ └── test_runtime.py # Runtime info-file helper tests
├── demo/
│ ├── jupyter_config.py # Example configuration
│ └── *.py # Debug/diagnostic scripts
└── pyproject.toml # Package configurationContributing
Fork the repository
Create a feature branch
Add tests for new functionality
Ensure all tests pass:
pytest tests/Submit a pull request
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
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/jupyter-ai-contrib/jupyter-server-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server