From 9eed982f1a69aec6e9bb9a22d2baa4e111cf3c45 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 1 May 2026 03:44:10 -0500 Subject: [PATCH] mcp-server: /_go/* pass-through for G5 cutover slice MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds an opt-in pass-through that routes Bun mcp-server requests to the Go gateway when GO_LAKEHOUSE_URL is set. /_go/v1/embed, /_go/v1/matrix/search etc. flow through Bun frontend → Go backend without touching any existing tool. Off-by-default (empty GO_LAKEHOUSE_URL → 503 with rationale); enabled via systemd drop-in at: /etc/systemd/system/lakehouse-agent.service.d/go-cutover.conf This is the first slice of real Bun-fronted traffic hitting the Go substrate. The /api/* pass-through (Rust gateway) and every existing tool are unmodified — fully additive cutover step. Reversible: unset GO_LAKEHOUSE_URL or remove the systemd drop-in and restart lakehouse-agent.service. Verified end-to-end against persistent Go stack on :4110: /_go/health → {"status":"ok","service":"gateway"} /_go/v1/embed → nomic-embed-text-v2-moe vectors (dim=768) /_go/v1/matrix/search → 3/3 Forklift Operators (role+geo match) Co-Authored-By: Claude Opus 4.7 (1M context) --- mcp-server/index.ts | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/mcp-server/index.ts b/mcp-server/index.ts index 5576f79..c144b43 100644 --- a/mcp-server/index.ts +++ b/mcp-server/index.ts @@ -23,6 +23,13 @@ import { roleBand, SCENES, SCENES_VERSION, FACE_RENDER_DIM, type RoleBand } from import { ICONS, ICONS_VERSION, DEFAULT_NEGATIVE, certToSlug, type IconRecipe } from "./icon_recipes.js"; const BASE = process.env.LAKEHOUSE_URL || "http://localhost:3100"; +// G5 cutover prep (2026-05-01): when GO_LAKEHOUSE_URL is set, the +// `/_go/*` pass-through routes to the Go gateway. Off-by-default +// (empty = disabled, returns 503 on /_go/*). Reversible via unset. +// Doesn't modify any existing tool — additive parallel path so +// operators can validate Go-side handlers under real Bun-frontend +// shape without touching the production Rust path. +const GO_BASE = process.env.GO_LAKEHOUSE_URL || ""; const PORT = parseInt(process.env.MCP_PORT || "3700"); // ─── Staffer roster — used by the per-staffer hot-swap index (G). ──── @@ -711,6 +718,26 @@ async function main() { return new Response(await r.text(), { status: r.status, headers: { "Content-Type": "application/json" } }); } + // G5 cutover slice: pass-through to GO_BASE (Go gateway). Same + // shape as /api/* but points at the Go side. Returns 503 when + // GO_LAKEHOUSE_URL isn't set so callers know the cutover slice + // is off rather than silently routing to Rust. No body + // transformation — caller responsible for sending Go-shaped + // requests (e.g. /v1/embed not /ai/embed). + if (url.pathname.startsWith("/_go/")) { + if (!GO_BASE) { + return err("GO_LAKEHOUSE_URL not set; /_go/* cutover slice is disabled", 503); + } + const path = url.pathname.replace("/_go", ""); + const body = req.method !== "GET" ? await req.text() : undefined; + try { + const r = await fetch(`${GO_BASE}${path}`, { method: req.method, headers: { "Content-Type": "application/json" }, body }); + return new Response(await r.text(), { status: r.status, headers: { "Content-Type": "application/json" } }); + } catch (e) { + return err(`Go gateway unreachable at ${GO_BASE}: ${e}`, 502); + } + } + // Proof — narrative HTML served from mcp-server/proof.html. // Live tests consumed client-side via /proof.json. if (url.pathname === "/proof") {