Commit 22dafb7
Fix: Access ywebsocket_server via extension_manager to enable RTC mode (#135)
## Problem
When using jupyter-mcp-server as a Jupyter Server Extension with jupyter-collaboration,
MCP tools fall back to "file mode" instead of using RTC (Real-Time Collaboration) mode.
**Symptoms:**
- User executes cells successfully from JupyterLab UI
- MCP client (Claude Code) modifies/executes cells via MCP tools (works fine)
- After MCP modifications, user's UI becomes unresponsive
- Cells don't execute from UI, execution counter doesn't update
- Browser refresh required to restore UI functionality
- Kernel stays alive but WebSocket connection is broken
**Environment Tested:**
- jupyter-mcp-server 0.17.0 (Jupyter Server Extension mode)
- jupyterlab 4.4.1
- jupyter-collaboration 4.0.2
- Python 3.13.7
- Claude Code as MCP client
**MCP Configuration (.mcp.json):**
```json
{
"mcpServers": {
"jupyter": {
"command": "npx",
"args": ["mcp-remote", "http://127.0.0.1:8888/mcp"]
}
}
}
```
**Server logs show:**
```
[INFO] Notebook <id> not open, using file mode
[INFO] Wrote outputs to cell <n> in <path>
[INFO] Out-of-band changes. Overwriting the content in room json:notebook:<id>
```
The "Out-of-band changes" message indicates MCP wrote to the file directly,
bypassing the Y.js collaboration layer, which breaks the UI's WebSocket connection.
## Root Cause
1. MCP tools access collaboration via `serverapp.web_app.settings.get("yroom_manager")`
2. jupyter-collaboration never adds `yroom_manager` to web_app.settings
3. YDocExtension stores it as `self.ywebsocket_server` but doesn't expose it in settings
4. When yroom_manager lookup returns None, tools fall back to direct file writes
5. Direct file writes bypass Y.js CRDT layer → "Out-of-band changes" → WebSocket disconnect
## Solution
Access ywebsocket_server via the extension_manager:
```python
serverapp.extension_manager.extension_points['jupyter_server_ydoc'].app.ywebsocket_server
```
Also fixed DocumentRoom API - access document via `room._document` instead of
calling non-existent `get_jupyter_ydoc()` method.
## Impact
✅ MCP now uses true RTC mode when jupyter-collaboration is available
✅ No more WebSocket disconnections after MCP cell modifications
✅ UI stays responsive - no browser refresh required
✅ Enables true simultaneous editing between MCP clients and human users
✅ Works with Claude Code, VS Code, Cursor, and other MCP clients
## Files Changed
- execute_cell_tool.py
- overwrite_cell_source_tool.py
- insert_cell_tool.py
- insert_execute_code_cell_tool.py
- delete_cell_tool.py
## Testing
Verified with:
- JupyterLab 4.4.1 + jupyter-collaboration 4.0.2 + datalayer-pycrdt 0.12.17
- jupyter-mcp-server 0.17.0 as Jupyter Server Extension
- Claude Code as MCP client (npx mcp-remote transport)
- Confirmed MCP cell modifications no longer break UI WebSocket
- Confirmed execution from both MCP and UI works simultaneously without refresh
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude <[email protected]>1 parent 88f914d commit 22dafb7
File tree
5 files changed
+130
-45
lines changed- jupyter_mcp_server/tools
5 files changed
+130
-45
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
30 | 30 | | |
31 | 31 | | |
32 | 32 | | |
33 | | - | |
34 | | - | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
35 | 47 | | |
36 | | - | |
| 48 | + | |
37 | 49 | | |
38 | | - | |
39 | | - | |
40 | | - | |
41 | | - | |
42 | | - | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
43 | 60 | | |
44 | 61 | | |
45 | 62 | | |
46 | | - | |
| 63 | + | |
47 | 64 | | |
48 | 65 | | |
49 | 66 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
24 | 24 | | |
25 | 25 | | |
26 | 26 | | |
27 | | - | |
28 | | - | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
29 | 41 | | |
30 | 42 | | |
31 | 43 | | |
32 | 44 | | |
33 | | - | |
34 | | - | |
35 | | - | |
36 | | - | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
37 | 54 | | |
38 | 55 | | |
39 | 56 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
19 | 19 | | |
20 | 20 | | |
21 | 21 | | |
22 | | - | |
| 22 | + | |
23 | 23 | | |
24 | 24 | | |
25 | | - | |
| 25 | + | |
26 | 26 | | |
27 | 27 | | |
28 | 28 | | |
29 | | - | |
| 29 | + | |
30 | 30 | | |
31 | 31 | | |
32 | 32 | | |
33 | 33 | | |
34 | | - | |
35 | | - | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
36 | 48 | | |
37 | | - | |
| 49 | + | |
38 | 50 | | |
39 | | - | |
40 | | - | |
41 | | - | |
42 | | - | |
43 | | - | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
44 | 61 | | |
45 | 62 | | |
46 | 63 | | |
47 | | - | |
| 64 | + | |
48 | 65 | | |
49 | 66 | | |
50 | 67 | | |
| |||
Lines changed: 26 additions & 9 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
23 | 23 | | |
24 | 24 | | |
25 | 25 | | |
26 | | - | |
27 | | - | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
28 | 40 | | |
29 | | - | |
| 41 | + | |
30 | 42 | | |
31 | | - | |
32 | | - | |
33 | | - | |
34 | | - | |
35 | | - | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
36 | 53 | | |
37 | 54 | | |
38 | | - | |
| 55 | + | |
39 | 56 | | |
40 | 57 | | |
41 | 58 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
20 | 20 | | |
21 | 21 | | |
22 | 22 | | |
23 | | - | |
24 | | - | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
25 | 37 | | |
26 | | - | |
| 38 | + | |
27 | 39 | | |
28 | | - | |
29 | | - | |
30 | | - | |
31 | | - | |
32 | | - | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
33 | 50 | | |
34 | 51 | | |
35 | | - | |
| 52 | + | |
36 | 53 | | |
37 | 54 | | |
38 | 55 | | |
| |||
0 commit comments