Skip to content

Commit db23c1c

Browse files
Append insert execute code cell (#175)
* feat: add Plotly output parsing and rename health endpoint - Update `extract_output` in `utils.py` to detect and serialize Plotly data structures into formatted JSON strings. - Filter out non-standard `transient` fields from execution outputs to improve `nbformat` schema compliance. - Change health check route from `/api/healthz` to `/api/health` in `server.py`. - Add debug logging for output data keys to assist with visualization detection. * Modify insert_execute_code_cell index validation Updated cell_index parameter to allow -1 as a valid index. * Enhance tests for inserting code cells Added test for appending code cell to notebook. * removed plotly parsing, healthz rename --------- Co-authored-by: Nico McGill <[email protected]>
1 parent 38c9b9d commit db23c1c

File tree

3 files changed

+15
-5
lines changed

3 files changed

+15
-5
lines changed

jupyter_mcp_server/server.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,7 @@ async def execute_cell(
410410

411411
@mcp.tool()
412412
async def insert_execute_code_cell(
413-
cell_index: Annotated[int, Field(description="Index of the cell to insert and execute (0-based)", ge=0)],
413+
cell_index: Annotated[int, Field(description="Index of the cell to insert and execute (0-based)", ge=-1)],
414414
cell_source: Annotated[str, Field(description="Code source for the cell")],
415415
timeout: Annotated[int, Field(description="Maximum seconds to wait for execution")] = 90,
416416
) -> Annotated[list[str | ImageContent], Field(description="List of outputs from the executed cell")]:
@@ -743,4 +743,4 @@ async def get_registered_tools():
743743

744744
tools.append(tool_dict)
745745

746-
return tools
746+
return tools

jupyter_mcp_server/utils.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import re
66
import asyncio
77
import time
8+
import json
89
from typing import Any, Union
910
from mcp.types import ImageContent
1011
from jupyter_mcp_server.config import ALLOW_IMG_OUTPUT
@@ -83,7 +84,9 @@ def extract_output(output: Union[dict, Any]) -> Union[str, ImageContent]:
8384
return strip_ansi_codes(str(text))
8485

8586
elif output_type in ["display_data", "execute_result"]:
86-
data = output.get("data", {})
87+
88+
data = output.get("data", {})
89+
8790
if "image/png" in data:
8891
if ALLOW_IMG_OUTPUT:
8992
try:
@@ -93,6 +96,8 @@ def extract_output(output: Union[dict, Any]) -> Union[str, ImageContent]:
9396
return "[Image Output (PNG) - Error processing image]"
9497
else:
9598
return "[Image Output (PNG) - Image display disabled]"
99+
100+
96101
if "text/plain" in data:
97102
plain_text = data["text/plain"]
98103
if hasattr(plain_text, 'source'):
@@ -943,4 +948,4 @@ async def get_notebook_model(serverapp: Any, notebook_path: str):
943948
return None
944949
nb = NotebookModel()
945950
nb._doc = ydoc
946-
return nb
951+
return nb

tests/test_tools.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,11 @@ async def check_and_delete_cell(client: MCPClient, index, expected_type, content
108108
expected_result = eval(code_content)
109109
assert int(code_result['result'][0]) == expected_result
110110

111+
# Testing appending code cell to bottom of notebook
112+
code_result = await mcp_client_parametrized.insert_execute_code_cell(-1, code_content)
113+
expected_result = eval(code_content)
114+
assert int(code_result['result'][0]) == expected_result
115+
111116
# Test overwrite_cell_source
112117
new_code_content = f"({code_content}) * 2"
113118
result = await mcp_client_parametrized.overwrite_cell_source(1, new_code_content)
@@ -267,4 +272,4 @@ async def test_list_kernels(mcp_client_parametrized: MCPClient):
267272
kernel_list = await mcp_client_parametrized.list_kernels()
268273
logging.debug(f"Kernel list: {kernel_list}")
269274
# Check for either TSV header or "No kernels found" message
270-
assert "ID\tName\tDisplay_Name\tLanguage\tState\tConnections\tLast_Activity\tEnvironment" in kernel_list
275+
assert "ID\tName\tDisplay_Name\tLanguage\tState\tConnections\tLast_Activity\tEnvironment" in kernel_list

0 commit comments

Comments
 (0)