Introduce MCP server launch argument --multi-user and adjust NPM scripts

(adding :multi-user variants) #20
This commit is contained in:
Dominik Jain 2025-12-15 14:21:36 +01:00
parent 66af0d6b72
commit 3766124961
6 changed files with 381 additions and 763 deletions

File diff suppressed because it is too large Load Diff

View File

@ -10,7 +10,9 @@
"build:types": "tsc --emitDeclarationOnly --outDir dist",
"build:full": "npm run build && npm run build:types",
"start": "node dist/index.js",
"dev": "node --loader ts-node/esm src/index.ts"
"start:multi-user": "node dist/index.js --multi-user",
"dev": "node --loader ts-node/esm src/index.ts",
"dev:multi-user": "node --loader ts-node/esm src/index.ts --multi-user"
},
"keywords": [
"mcp",

View File

@ -44,7 +44,8 @@ export class PenpotMcpServer {
constructor(
private port: number = 4401,
private webSocketPort: number = 4402,
replPort: number = 4403
replPort: number = 4403,
private isMultiUser: boolean = false
) {
this.configLoader = new ConfigurationLoader();
this.apiDocs = new ApiDocs();
@ -66,6 +67,10 @@ export class PenpotMcpServer {
this.registerTools();
}
public isMultiUserMode(): boolean {
return this.isMultiUser;
}
public getInitialInstructions(): string {
let instructions = this.configLoader.getInitialInstructions();
instructions = instructions.replace("$api_types", this.apiDocs.getTypeNames().join(", "));

View File

@ -25,8 +25,7 @@ export class PluginBridge {
constructor(
private mcpServer: PenpotMcpServer,
private port: number,
private taskTimeoutSecs: number = 30,
private isMultiUser: boolean = false
private taskTimeoutSecs: number = 30
) {
this.wsServer = new WebSocketServer({ port: port });
this.setupWebSocketHandlers();
@ -45,7 +44,7 @@ export class PluginBridge {
const userToken = url.searchParams.get("userToken");
// require userToken if running in multi-user mode
if (this.isMultiUser && !userToken) {
if (this.mcpServer.isMultiUserMode() && !userToken) {
this.logger.warn("Connection attempt without userToken in multi-user mode - rejecting");
ws.close(1008, "Missing userToken parameter");
return;
@ -146,7 +145,7 @@ export class PluginBridge {
* @throws Error if no suitable connection is found or if configuration is invalid
*/
private getClientConnection(): ClientConnection {
if (this.isMultiUser) {
if (this.mcpServer.isMultiUserMode()) {
const sessionContext = this.mcpServer.getSessionContext();
if (!sessionContext?.userToken) {
throw new Error("No userToken found in session context. Multi-user mode requires authentication.");

View File

@ -22,6 +22,7 @@ async function main(): Promise<void> {
try {
const args = process.argv.slice(2);
let port = 4401; // default port
let multiUser = false; // default to single-user mode
// parse command line arguments
for (let i = 0; i < args.length; i++) {
@ -42,18 +43,21 @@ async function main(): Promise<void> {
if (i + 1 < args.length) {
process.env.LOG_DIR = args[i + 1];
}
} else if (args[i] === "--multi-user") {
multiUser = true;
} else if (args[i] === "--help" || args[i] === "-h") {
logger.info("Usage: node dist/index.js [options]");
logger.info("Options:");
logger.info(" --port, -p <number> Port number for the HTTP/SSE server (default: 4401)");
logger.info(" --log-level, -l <level> Log level: trace, debug, info, warn, error (default: info)");
logger.info(" --log-dir <path> Directory for log files (default: mcp-server/logs)");
logger.info(" --multi-user Enable multi-user mode (default: single-user)");
logger.info(" --help, -h Show this help message");
process.exit(0);
}
}
const server = new PenpotMcpServer(port);
const server = new PenpotMcpServer(port, undefined, undefined, multiUser);
await server.start();
// keep the process alive

View File

@ -6,7 +6,9 @@
"install:all": "concurrently --names \"COMMON,MCP-SERVER,PLUGIN\" --prefix-colors \"green,cyan,magenta\" \"npm --prefix common install\" \"npm --prefix mcp-server install\" \"npm --prefix penpot-plugin install\"",
"build:all": "concurrently --names \"COMMON,MCP-SERVER,PLUGIN\" --prefix-colors \"green,cyan,magenta\" --success first \"npm --prefix common install && npm --prefix common run build\" \"npm --prefix mcp-server run build\" \"npm --prefix penpot-plugin run build\"",
"start:all": "concurrently --names \"MCP-SERVER,PLUGIN-SERVER\" --prefix-colors \"cyan,magenta\" --kill-others-on-fail \"npm --prefix mcp-server start\" \"npm --prefix penpot-plugin run dev\"",
"start:all-multi-user": "concurrently --names \"MCP-SERVER,PLUGIN-SERVER\" --prefix-colors \"cyan,magenta\" --kill-others-on-fail \"npm --prefix mcp-server run start:multi-user\" \"npm --prefix penpot-plugin run dev\"",
"bootstrap": "npm run install:all && npm run build:all && npm run start:all",
"bootstrap:multi-user": "npm run install:all && npm run build:all && npm run start:all-multi-user",
"format": "prettier --write .",
"format:check": "prettier --check ."
},