From acc078064bcdd414cd5bf65e2deaccad3c3dd559 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 7 Sep 2026 13:19:32 +0200 Subject: [PATCH] :bug: Do not register developer tools in multi-user MCP mode (#11310) Prevent developer tools from being exposed when the MCP server runs in multi-user mode. Keep them available for local devenv usage and document the mode restriction. Add regression coverage for the registration policy. Closes #11291 AI-assisted-by: gpt-5.6-luna Co-authored-by: niwinz <843689+niwinz@users.noreply.github.com> --- mcp/README.md | 2 +- mcp/packages/server/src/PenpotMcpServer.test.ts | 14 +++++++++++++- mcp/packages/server/src/PenpotMcpServer.ts | 9 ++++++++- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/mcp/README.md b/mcp/README.md index 1b8dc3ea29..6842adce7e 100644 --- a/mcp/README.md +++ b/mcp/README.md @@ -267,7 +267,7 @@ The Penpot MCP server can be configured using environment variables. | `PENPOT_MCP_REPL_PORT` | Port for the REPL server (development/debugging) | `4403` | | `PENPOT_MCP_REPL_ENABLE` | Explicitly enable/disable the REPL server. Set to `true` to enable. When unset, defaults to the value of `PENPOT_MCP_DEVENV`. | (unset) | | `PENPOT_MCP_REMOTE_MODE` | Enable remote mode (disables file system access). Set to `true` to enable. | `false` | -| `PENPOT_MCP_DEVENV` | Enable Penpot development environment tools. Set to `true` to enable. | `false` | +| `PENPOT_MCP_DEVENV` | Enable Penpot development environment tools in local single-user mode. Set to `true` to enable. | `false` | | `PENPOT_MCP_TOOL_TIMEOUT_S` | Timeout, in seconds, for tool calls dispatched to the Penpot plugin | `120` | | `PENPOT_MCP_EXPORT_SHAPE_MAX_PARALLEL_REQUESTS` | Maximum number of parallel export shape requests (multi-user mode only). | `0` (no limit) | | `PENPOT_MCP_REDIS_URI` | Redis connection URI (e.g. `redis://host:6379`) enabling multi-instance horizontal scaling via Redis pub/sub task routing (multi-user mode only). When unset, the server runs in single-instance mode, requiring the plugin and MCP client to connect to the same instance. | (unset) | diff --git a/mcp/packages/server/src/PenpotMcpServer.test.ts b/mcp/packages/server/src/PenpotMcpServer.test.ts index 5c04e50400..68665359f5 100644 --- a/mcp/packages/server/src/PenpotMcpServer.test.ts +++ b/mcp/packages/server/src/PenpotMcpServer.test.ts @@ -1,6 +1,18 @@ import assert from "node:assert/strict"; import test from "node:test"; -import { PenpotMcpServer } from "./PenpotMcpServer"; +import { PenpotMcpServer, shouldRegisterDeveloperTools } from "./PenpotMcpServer"; + +test("registers developer tools in local devenv mode", () => { + assert.equal(shouldRegisterDeveloperTools(true, false), true); +}); + +test("does not register developer tools in multi-user devenv mode", () => { + assert.equal(shouldRegisterDeveloperTools(true, true), false); +}); + +test("does not register developer tools when devenv mode is disabled", () => { + assert.equal(shouldRegisterDeveloperTools(false, false), false); +}); // ── Pure function tests ──────────────────────────────────────── diff --git a/mcp/packages/server/src/PenpotMcpServer.ts b/mcp/packages/server/src/PenpotMcpServer.ts index 09849c9316..c620aca3fc 100644 --- a/mcp/packages/server/src/PenpotMcpServer.ts +++ b/mcp/packages/server/src/PenpotMcpServer.ts @@ -50,6 +50,13 @@ class ToolInfo { ) {} } +/** + * Indicates whether developer tools may be registered for the current server mode. + */ +export function shouldRegisterDeveloperTools(isDevEnv: boolean, isMultiUserMode: boolean): boolean { + return isDevEnv && !isMultiUserMode; +} + export class PenpotMcpServer { /** * Timeout, in minutes, for idle sessions (Streamable HTTP and SSE) before they are automatically closed and removed. @@ -259,7 +266,7 @@ export class PenpotMcpServer { if (this.isFileSystemAccessEnabled()) { toolInstances.push(new ImportImageTool(this)); } - if (this.isDevEnv()) { + if (shouldRegisterDeveloperTools(this.isDevEnv(), this.isMultiUserMode())) { const nreplClient = new NreplClient(); toolInstances.push(new CljsReplTool(this, nreplClient)); toolInstances.push(new ImportPenpotFileTool(this, nreplClient));