From 8471b3a7570f0cf2d3b144d29de9f52fe3487e10 Mon Sep 17 00:00:00 2001 From: nntrivi2001 Date: Wed, 5 Aug 2026 15:28:31 +0700 Subject: [PATCH] feat(lanes): add POST /:id/mcp/sync route (F1) --- server/routes/lanes.js | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/server/routes/lanes.js b/server/routes/lanes.js index 557badf..b40cca5 100644 --- a/server/routes/lanes.js +++ b/server/routes/lanes.js @@ -34,6 +34,7 @@ const { const { withLaneLock } = require("../lib/lane-lock"); const { checkSync, mergeSync, continueSync } = require("../lib/lane-sync"); const { installAgents } = require("../lib/lane-agents"); +const { syncMcp } = require("../lib/lane-mcp"); const { HOOKS, runHook, resolveProfile } = require("../lib/lane-profile"); const { slotDirs } = require("../lib/lane-slots"); const { @@ -349,6 +350,27 @@ router.post("/:id/agents/install", sameOriginGuard, async (req, res) => { } }); +/** + * Give this lane the same MCP servers as its source repo — relocates the + * source repo's already-configured mcpServers (from ~/.claude.json) into + * /.mcp.json, pins Playwright's proof output dir, seeds Chromium + * profiles. Never automatic, same as proof-link/agents-install: a session + * calls this explicitly. Never touches permissions/settings.local.json — + * see the F1 design spec for why. + */ +router.post("/:id/mcp/sync", sameOriginGuard, async (req, res) => { + const lane = lanesLib.getLane(req.params.id); + if (!lane) return res.status(404).json({ error: { code: "ENOLANE", message: "lane not found" } }); + try { + res.json(await syncMcp(lane)); + } catch (err) { + if (err.code === "ENOMCPCONFIG") { + return res.status(400).json({ error: { code: err.code, message: err.message } }); + } + res.status(500).json({ error: { code: err.code || "ERUNTIME", message: err.message } }); + } +}); + /** * A lane's working-copy facts: branch, short HEAD, that commit's subject, and * the uncommitted counts. Read-only, so no same-origin guard — that guard @@ -593,6 +615,7 @@ function sendRuntimeError(res, err) { "EBADBRANCH", "EUNRESOLVED", "EMERGEUNCOMMITTED", + "ENOMCPCONFIG", ]; if (badRequest.includes(err.code)) { return res.status(400).json({