Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions dev/content/new.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "a70f6bd9",
"metadata": {},
"source": [
"# A New Notebook"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "3c3442e4",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Hello, World!\n"
]
}
],
"source": [
"print(\"Hello, World!\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "68d7d9e9",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "base",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.13.5"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
68 changes: 52 additions & 16 deletions docs/docs/tools/index.mdx
Original file line number Diff line number Diff line change
@@ -1,8 +1,49 @@
# Tools

The server currently offers 11 tools:
The server currently offers 15 tools organized into two categories:

#### 1. `insert_cell`
## Multi-Notebook Management Tools (5 tools)

#### 1. `connect_notebook`

- Connect to a notebook file or create a new one.
- Input:
- `notebook_name`(string): Unique identifier for the notebook
- `notebook_path`(string): Path to the notebook file, relative to the Jupyter server root (e.g. "./notebook.ipynb")
- `mode`(string): "connect" to connect to existing, "create" to create new (default: "connect")
- `kernel_id`(string, optional): Specific kernel ID to use (optional, will create new if not provided)
- Returns: Success message with notebook information

#### 2. `list_notebook`

- List all currently connected notebooks with their information.
- Input: None
- Returns: TSV formatted table with notebook information (Name, Path, Status, Current)

#### 3. `switch_notebook`

- Switch the currently active notebook.
- Input:
- `notebook_name`(string): Notebook identifier to switch to
- Returns: Success message with new active notebook information

#### 4. `restart_notebook`

- Restart the kernel for a specific notebook.
- Input:
- `notebook_name`(string): Notebook identifier to restart
- Returns: Success message

#### 5. `disconnect_notebook`

- Disconnect from a specific notebook and release its resources.
- Input:
- `notebook_name`(string): Notebook identifier to disconnect
- Returns: Success message

## Cell Tools (10 tools)

#### 6. `insert_cell`

- Insert a cell to specified position with unified API.
- Input:
Expand All @@ -11,55 +52,50 @@ The server currently offers 11 tools:
- `cell_source`(string): Source content for the cell.
- Returns: Success message and the structure of its surrounding cells (up to 5 cells above and 5 cells below).

#### 2. `insert_execute_code_cell`
#### 7. `insert_execute_code_cell`

- Insert and execute a code cell in a Jupyter notebook.
- Input:
- `cell_index`(int): Index of the cell to insert (0-based). Use -1 to append at end and execute.
- `cell_source`(string): Code source.
- Returns: List of outputs from the executed cell (supports multimodal output including images).

#### 3. `delete_cell`
#### 8. `delete_cell`

- Delete a specific cell from the notebook.
- Input:
- `cell_index`(int): Index of the cell to delete (0-based).
- Returns: Success message.

#### 4. `get_notebook_info`

- Get basic information about the notebook.
- Returns: Dictionary with notebook path, total cells, and cell type counts.

#### 5. `read_cell`
#### 9. `read_cell`

- Read a specific cell from the notebook.
- Input:
- `cell_index`(int): Index of the cell to read (0-based).
- Returns: Dictionary with cell index, type, source, and outputs (for code cells).

#### 6. `read_all_cells`
#### 10. `read_all_cells`

- Read all cells from the notebook.
- Returns: List of cell information including index, type, source, and outputs (for code cells).

#### 7. `list_cell`
#### 11. `list_cell`

- List the basic information of all cells in the notebook.
- Returns a formatted table showing the index, type, execution count (for code cells), and first line of each cell.
- Provides a quick overview of the notebook structure and is useful for locating specific cells for operations.
- Input: None
- Returns: Formatted table string with cell information (Index, Type, Count, First Line).

#### 8. `overwrite_cell_source`
#### 12. `overwrite_cell_source`

- Overwrite the source of an existing cell.
- Input:
- `cell_index`(int): Index of the cell to overwrite (0-based).
- `cell_source`(string): New cell source - must match existing cell type.
- Returns: Success message and diff style.

#### 9. `execute_cell_streaming`
#### 13. `execute_cell_streaming`

- Execute cell with streaming progress updates. To be used for long-running cells.
- Input:
Expand All @@ -69,7 +105,7 @@ The server currently offers 11 tools:
- Returns:
- `list[Union[str, ImageContent]]`: List of outputs including progress updates (supports multimodal output including images)

#### 10. `execute_cell_simple_timeout`
#### 14. `execute_cell_simple_timeout`

- Execute a cell with simple timeout (no forced real-time sync). To be used for short-running cells. This won't force real-time updates but will work reliably.
- Input:
Expand All @@ -78,7 +114,7 @@ The server currently offers 11 tools:
- Returns:
- `list[Union[str, ImageContent]]`: List of outputs from the executed cell (supports multimodal output including images)

#### 11. `execute_cell_with_progress`
#### 15. `execute_cell_with_progress`

- Execute a specific cell with timeout and progress monitoring.
- Input:
Expand Down
98 changes: 98 additions & 0 deletions jupyter_mcp_server/notebook_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ class NotebookManager:
def __init__(self):
self._notebooks: Dict[str, Dict[str, Any]] = {}
self._default_notebook_name = "default"
self._current_notebook: Optional[str] = None # Currently active notebook

def __contains__(self, name: str) -> bool:
"""Check if a notebook is managed by this instance."""
Expand Down Expand Up @@ -100,6 +101,11 @@ def add_notebook(
"path": path or config.document_id
}
}

# For backward compatibility: if this is the first notebook or it's "default",
# set it as the current notebook
if self._current_notebook is None or name == self._default_notebook_name:
self._current_notebook = name

def remove_notebook(self, name: str) -> bool:
"""
Expand All @@ -121,6 +127,18 @@ def remove_notebook(self, name: str) -> bool:
pass
finally:
del self._notebooks[name]

# If we removed the current notebook, update the current pointer
if self._current_notebook == name:
# Set to another notebook if available, prefer "default" for compatibility
if self._default_notebook_name in self._notebooks:
self._current_notebook = self._default_notebook_name
elif self._notebooks:
# Set to the first available notebook
self._current_notebook = next(iter(self._notebooks.keys()))
else:
# No notebooks left
self._current_notebook = None
return True
return False

Expand Down Expand Up @@ -198,3 +216,83 @@ def ensure_kernel_alive(self, name: str, kernel_factory) -> KernelClient:
self.add_notebook(name, new_kernel)
return new_kernel
return kernel

def set_current_notebook(self, name: str) -> bool:
"""
Set the currently active notebook.

Args:
name: Notebook identifier

Returns:
True if set successfully, False if notebook doesn't exist
"""
if name in self._notebooks:
self._current_notebook = name
return True
return False

def get_current_notebook(self) -> Optional[str]:
"""
Get the name of the currently active notebook.

Returns:
Current notebook name or None if no active notebook
"""
return self._current_notebook

def get_current_connection(self) -> NotebookConnection:
"""
Get the connection for the currently active notebook.
For backward compatibility, defaults to "default" if no current notebook is set.

Returns:
NotebookConnection context manager for the current notebook

Raises:
ValueError: If no notebooks exist and no default config is available
"""
current = self._current_notebook or self._default_notebook_name

# For backward compatibility: if the requested notebook doesn't exist but we're
# asking for default, create a connection using the default config
if current not in self._notebooks and current == self._default_notebook_name:
# Return a connection using default configuration
config = get_config()
return NotebookConnection({
"server_url": config.document_url,
"token": config.document_token,
"path": config.document_id
})

return self.get_notebook_connection(current)

def list_all_notebooks(self) -> Dict[str, Dict[str, Any]]:
"""
Get information about all managed notebooks.

Returns:
Dictionary with notebook names as keys and their info as values
"""
result = {}
for name, notebook_data in self._notebooks.items():
kernel = notebook_data["kernel"]
notebook_info = notebook_data["notebook_info"]

# Check kernel status
kernel_status = "unknown"
if kernel:
try:
kernel_status = "alive" if hasattr(kernel, 'is_alive') and kernel.is_alive() else "dead"
except Exception:
kernel_status = "error"
else:
kernel_status = "not_initialized"

result[name] = {
"path": notebook_info.get("path", ""),
"kernel_status": kernel_status,
"is_current": name == self._current_notebook
}

return result
Loading
Loading