feat(lanes): add POST /:id/mcp/sync route (F1)

This commit is contained in:
2026-08-05 15:28:31 +07:00
parent 2731b7c8ce
commit 8471b3a757
+23
View File
@@ -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
* <lane>/.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({