From a30af618830ff15d4a71372b125ee88c228fcab7 Mon Sep 17 00:00:00 2001 From: Joakim Persson Date: Tue, 13 Oct 2026 00:17:02 +0200 Subject: [PATCH] pi bridge: RemoteMcpClient is now the only copy (pi-extensions retired mcp-loader.ts) pi-extensions 750b2a8 removed mcp-loader.ts in favour of pi's built-in MCP support (builtin:mcp, ~/.pi/agent/mcp.json). The bridge's RemoteMcpClient was vendored from that file and kept in step by an MCP-STREAMABLE-HTTP-CLIENT-SYNC token, checked by scripts/check-mcp-client-sync.sh. With the canonical copy gone the guard could only ever SKIP (or, on images that still bake /opt/pi-extensions/extensions/mcp-loader.ts, compare against a dead file), so it is removed rather than left looking like a check. Comment and README only; no code change. The bridge still type-strips and imports (node 24), and evaluateDormancy is exported as before. The README records why MemPalace itself does not move to the built-in: its wake-up, mailbox, feed and stamping need their own client, and built-in tools would be mcp__mempalace__* with codemode exposure by default. --- extensions/pi/README.md | 14 +++--- extensions/pi/mempalace.ts | 18 ++++---- scripts/check-mcp-client-sync.sh | 77 -------------------------------- 3 files changed, 17 insertions(+), 92 deletions(-) delete mode 100755 scripts/check-mcp-client-sync.sh diff --git a/extensions/pi/README.md b/extensions/pi/README.md index 21c078b..95bedfa 100644 --- a/extensions/pi/README.md +++ b/extensions/pi/README.md @@ -211,12 +211,16 @@ chosen at load time: also pins `Host`/`Origin`, so a request arriving under the wrong hostname is refused even when the port is open. - Implementation note: the HTTP client (`RemoteMcpClient`) is **vendored** from + Implementation note: the HTTP client (`RemoteMcpClient`) was **vendored** from [`pi-extensions`](https://gitea.jordbo.se/joakimp/pi-extensions)' - `mcp-loader.ts`. A `MCP-STREAMABLE-HTTP-CLIENT-SYNC` token keeps the two - copies from drifting — [`scripts/check-mcp-client-sync.sh`](../../scripts/check-mcp-client-sync.sh) - fails if they diverge (it skips gracefully when the `pi-extensions` checkout - isn't present). + `mcp-loader.ts`. That loader was retired on 2026-10-12 (pi-extensions + `750b2a8`) in favour of pi's built-in MCP support, so this copy is now the + only one. The sync token and `scripts/check-mcp-client-sync.sh` that guarded + the pair were removed with it. MemPalace itself does **not** move to the + built-in: the bridge's wake-up, mailbox, feed and provenance stamping need + their own client, and built-in MCP tools would be renamed + `mcp__mempalace__*` with `codemode` exposure (not declared to the model) by + default. ## Fail-soft diff --git a/extensions/pi/mempalace.ts b/extensions/pi/mempalace.ts index f8ff35d..c6b5b7b 100644 --- a/extensions/pi/mempalace.ts +++ b/extensions/pi/mempalace.ts @@ -576,17 +576,15 @@ class StdioMcpClient implements IMcpClient { // ─────────────────────────────────────────────────────────────────────── // RemoteMcpClient — EXTERNAL transport (streamable-HTTP / sessionless JSON-RPC). // -// VENDORED from pi-extensions/extensions/mcp-loader.ts (class RemoteMcpClient). -// Kept as a copy rather than a shared import because the two repos ship -// independently; the canonical implementation lives in mcp-loader.ts. Port -// protocol fixes in both directions. +// ORIGIN: vendored from pi-extensions/extensions/mcp-loader.ts (class +// RemoteMcpClient). mcp-loader.ts was RETIRED on 2026-10-12 (pi-extensions +// 750b2a8) in favour of pi's built-in MCP support, so THIS copy is now the only +// one. There is no canonical partner left to sync with, so the former +// MCP-STREAMABLE-HTTP-CLIENT-SYNC token and scripts/check-mcp-client-sync.sh +// were removed with it. The last canonical version is +// `git show a88fa99:extensions/mcp-loader.ts` in pi-extensions. // -// MCP-STREAMABLE-HTTP-CLIENT-SYNC: v1 -// This token must match the canonical block's. Bump it in BOTH files whenever -// the streamable-HTTP protocol handling changes; scripts/check-mcp-client-sync.sh -// fails when they diverge (skips gracefully if pi-extensions isn't checked out). -// -// Deltas from the canonical copy: +// Deltas from that last canonical copy: // • protocolVersion pinned to "2024-11-05" to match mempalace-mcp's stdio // handshake (the server echoes whatever it is sent, so cosmetic today, // but keeps both transports consistent). diff --git a/scripts/check-mcp-client-sync.sh b/scripts/check-mcp-client-sync.sh deleted file mode 100755 index 2d2a4a4..0000000 --- a/scripts/check-mcp-client-sync.sh +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/env bash -# check-mcp-client-sync.sh — drift guard for the vendored streamable-HTTP MCP client. -# -# The RemoteMcpClient in extensions/pi/mempalace.ts is a VENDORED copy of the -# canonical implementation in pi-extensions/extensions/mcp-loader.ts (the two -# repos ship independently, so a shared import isn't practical for one small, -# protocol-frozen class — see the annotated header in mempalace.ts). -# -# Both blocks carry a matching sync token: -# MCP-STREAMABLE-HTTP-CLIENT-SYNC: vN -# Bump it in BOTH files whenever the streamable-HTTP protocol handling changes. -# This guard fails when the tokens diverge, so a protocol fix in one file can't -# silently skip the other. -# -# It is a LOCAL developer guard: it needs the sibling pi-extensions checkout to -# compare against. If that isn't found it SKIPS (exit 0) rather than failing — -# so it's safe to wire into CI that only checks out this repo. -# -# Point it at a specific checkout with: PI_EXTENSIONS_DIR=/path/to/pi-extensions -set -euo pipefail - -REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" -VENDORED="$REPO_ROOT/extensions/pi/mempalace.ts" - -TOKEN_RE='MCP-STREAMABLE-HTTP-CLIENT-SYNC: v[0-9]+' -extract_token() { grep -oE "$TOKEN_RE" "$1" 2>/dev/null | head -1 | grep -oE 'v[0-9]+' || true; } - -if [[ ! -f "$VENDORED" ]]; then - echo "ERROR: vendored file not found: $VENDORED" >&2 - exit 1 -fi - -VENDORED_TOKEN="$(extract_token "$VENDORED")" -if [[ -z "$VENDORED_TOKEN" ]]; then - echo "FAIL: no '$TOKEN_RE' token in $VENDORED" >&2 - echo " The vendored RemoteMcpClient must carry a sync token." >&2 - exit 1 -fi - -# Locate the canonical mcp-loader.ts across common dev layouts. -CANDIDATES=( - "${PI_EXTENSIONS_DIR:-}/extensions/mcp-loader.ts" - "$REPO_ROOT/../pi-extensions/extensions/mcp-loader.ts" - "/workspace/pi-extensions/extensions/mcp-loader.ts" - "$HOME/src/pi-extensions/extensions/mcp-loader.ts" - "$HOME/src/src_local/pi-extensions/extensions/mcp-loader.ts" - "/opt/pi-extensions/extensions/mcp-loader.ts" -) -CANONICAL="" -for c in "${CANDIDATES[@]}"; do - [[ -n "$c" && -f "$c" ]] && { CANONICAL="$c"; break; } -done - -if [[ -z "$CANONICAL" ]]; then - echo "SKIP: canonical pi-extensions/extensions/mcp-loader.ts not found — cannot compare." - echo " (vendored token: $VENDORED_TOKEN). Set PI_EXTENSIONS_DIR to enable the check." - exit 0 -fi - -CANONICAL_TOKEN="$(extract_token "$CANONICAL")" -if [[ -z "$CANONICAL_TOKEN" ]]; then - echo "FAIL: no '$TOKEN_RE' token in canonical $CANONICAL" >&2 - exit 1 -fi - -if [[ "$VENDORED_TOKEN" != "$CANONICAL_TOKEN" ]]; then - echo "FAIL: MCP client sync token drift." >&2 - echo " vendored ($VENDORED): $VENDORED_TOKEN" >&2 - echo " canonical ($CANONICAL): $CANONICAL_TOKEN" >&2 - echo " A streamable-HTTP protocol change landed in one file but not the other." >&2 - echo " Reconcile RemoteMcpClient in both, then bump the token in BOTH to match." >&2 - exit 1 -fi - -echo "OK: MCP client sync token matches ($VENDORED_TOKEN)." -echo " vendored: $VENDORED" -echo " canonical: $CANONICAL"