run-background-task
Execute long-running shell commands like development servers in the background while maintaining interactive control through the MCP Background Task Server.
Instructions
Runs a long-running command (like 'npm run dev') in background. When the command is running, you can interact with it using other tools.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Unique name of the task | |
| shell | Yes | Shell command to run in background |
Implementation Reference
- src/index.ts:85-102 (handler)The handler function for the 'run-background-task' tool. Creates and starts a background child process using the Child class if no existing task with the same name is running, stores it in the global processes map, and returns a confirmation message including the process PID.async ({ name, shell }) => { if (processes.has(name)) { throw new Error(`Task with name "${name}" is already running.`); } const child = new Child(shell); processes.set(name, child); return { content: [ { type: "text", text: `Task "${name}" started with PID ${child.getPid()}.`, }, ], }; }
- src/index.ts:80-83 (schema)Input schema for the 'run-background-task' tool defining the required 'name' and 'shell' parameters using Zod validation.inputSchema: { name: z.string().describe("Unique name of the task"), shell: z.string().describe("Shell command to run in background"), },
- src/index.ts:74-103 (registration)Registration of the 'run-background-task' tool on the McpServer instance, including name, schema (title, description, inputSchema), and handler function.server.registerTool( "run-background-task", { title: "Run Background Task", description: "Runs a long-running command (like 'npm run dev') in background. When the command is running, you can interact with it using other tools.", inputSchema: { name: z.string().describe("Unique name of the task"), shell: z.string().describe("Shell command to run in background"), }, }, async ({ name, shell }) => { if (processes.has(name)) { throw new Error(`Task with name "${name}" is already running.`); } const child = new Child(shell); processes.set(name, child); return { content: [ { type: "text", text: `Task "${name}" started with PID ${child.getPid()}.`, }, ], }; } );
- src/index.ts:6-63 (helper)The Child class is a helper that wraps a Node.js child process spawned from a shell command. It captures stdout/stderr, tracks state, provides getters for output/PID/state, allows writing to stdin, and killing the process. Used by the background task tools.class Child { process: childProcess.ChildProcess; state: "running" | "stopped" = "running"; stopCode: number | null = null; stdout: string = ""; stderr: string = ""; constructor(shell: string) { const child = childProcess.spawn(shell, { shell: true, }); child.stdout?.on("data", (data) => { this.stdout += data.toString(); }); child.stderr?.on("data", (data) => { this.stderr += data.toString(); }); child.on("exit", (code) => { this.state = "stopped"; this.stopCode = code; }); this.process = child; } public getStdout(): string { return this.stdout; } public getStderr(): string { return this.stderr; } public getState(): "running" | "stopped" { return this.state; } public getStopCode(): number | null { return this.stopCode; } public getPid(): number { return this.process.pid || -1; } public writeToStdin(data: string): void { if (this.process.stdin) { this.process.stdin.write(data); } else { throw new Error("Child process stdin is not available."); } } public kill(): void { if (this.process.killed) { return; } this.process.kill(); this.state = "stopped"; } }