Skip to content

v2.5.0 — fastmcp 4 / mcp 2, notebook persistence, page liveness

Latest

Choose a tag to compare

@BB-84C BB-84C released this 06 Oct 05:39
84c7ece

Upgrade notes

  • Dependencies move to fastmcp 4 / mcp 2. instrMCP now requires fastmcp>=4.0.10,<5 and mcp>=2.2.0,<3 (2.4.4 capped them at <4 / <2). Upgrade with:

    pip install --upgrade "instrmcp==2.5.0"
  • Reload JupyterLab after upgrading. The frontend extension and the kernel package must come from the same build: the kernel now expects the toolbar's page heartbeat (see "Page liveness" below), and an old frontend bundle never sends it.

  • Behaviour changes worth knowing before you upgrade:

    • notebook_add_cell and cell execution save the notebook before they report success. A failed save reports status: "persistence_error", and a failed add rolls the inserted cell back.
    • The unattended save never opens a dialog. It refuses, with a reason, when the notebook's source or metadata changed on disk; it writes when only outputs or execution counts differ.
    • notebook_add_cell and notebook_apply_patch pass cell source through unchanged; literal \n and \t are no longer converted.
    • %mcp_restart, %mcp_start and the toolbar restart reuse the endpoint of the server they replace instead of falling back to 127.0.0.1:8123. A port that cannot be re-bound raises instead of silently moving.

fastmcp 4 / mcp 2 migration (#41)

  • The four call sites removed in fastmcp 4 are migrated: the stdio proxy uses create_proxy and the new ProxyClient import path, dynamic tools are removed through the local provider, tool transformations use ToolTransform, and resources are listed with list_resources().
  • Clients that initialize with MCP protocol 2024-11-05 keep working.
  • After a server restart, a request carrying the old session id is answered with HTTP 404, so streamable-HTTP clients re-initialize and retry instead of failing.

Added

  • OS-assigned server port. _do_start_server(host=..., port=0) lets the OS pick a free port; the server records the bound port and _get_current_config()["port"] reports it.
  • Frontend connection attestation. The kernel publishes qdevbot_instrmcp_frontend in its user namespace (schemaVersion, connected, target, connectedAt, connectionCount, nonce, package), republished whenever a toolbar comm opens, closes, dies or expires.
  • Page liveness. The toolbar heartbeats every 5 s and announces a page close on pagehide; the kernel expires a toolbar comm that has been silent for 20 s. The attestation now goes to connected: false after a page reload, a closed tab or a crashed tab, and back to true when a page attaches again.
  • Notebook persistence. save_active_notebook(timeout_s=None) and a {"type": "save_notebook"} request.
  • Analysis-kernel isolation. The JupyterLab extension attaches nothing (no extension, no comm targets, no active-cell tracking) to kernels named qdevbot-analysis.
  • Cold-kernel readiness. The bridge-independent execution path waits max(30 s, execution timeout) for a freshly started kernel instead of 10 s.
  • JupyterLab policy tests run in CI (jlpm test:policy).

Fixed

  • Adding a markdown cell no longer waits out the 10 s frontend timeout. Converting the new cell's type replaced the active cell, and the next snapshot treated the replaced cell as a dead comm and dropped it; the add reply could then never be sent. A stale cell no longer drops the comm.
  • A refused notebook_add_cell now says why in its concise result (for example "Notebook source or metadata changed on disk; refusing to overwrite it with the active frontend"), consistent with cell execution.
  • Adding a cell no longer reports a false failure when the frontend answers just as the wait expires.

Known issues

  • A cell that blocks the kernel for more than about 20 s makes the page read as gone until the cell finishes, because heartbeats queue behind the running request (#51).
  • A consent request has no bounded wait and is not cancelled when its page disconnects; a client can wait indefinitely if the page dies after the request was sent. Nothing executes in that case (#50).

Verification

  • CI (lint and tests, 3 operating systems × 3 Python versions) is green on this revision.
  • A desktop client ran the release acceptance on Windows and on macOS against this revision: port in use, cold start, late frontend, page close/reload/hard kill, external notebook edit, append-only output, escape preservation, analysis-kernel isolation, slow page, and session recovery after all three restart paths. Results: #48.

Full Changelog: v2.4.4...v2.5.0