Skip to main content
Glama
nanoseil
by nanoseil

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
NameRequiredDescriptionDefault
nameYesUnique name of the task
shellYesShell command to run in background

Implementation Reference

  • 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()}.`, }, ], }; }
  • 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()}.`, }, ], }; } );
  • 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"; } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/nanoseil/mcp-bgtask'

If you have feedback or need assistance with the MCP directory API, please join our Discord server