kill_server
Stop a local dev server by its process ID or port number. Requires confirmation to prevent accidental termination.
Instructions
Kill a dev server by pid or port. Defaults to dry-run; pass confirm=true to actually kill. SIGTERM first, escalates to SIGKILL after 5s. Refuses system PIDs (<1000).
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| pid | No | Process ID | |
| port | No | TCP port (alternative to pid) | |
| confirm | No | Must be true to actually kill | |
| force | No | Use SIGKILL immediately, skip SIGTERM |
Implementation Reference
- src/killer.ts:13-78 (handler)Core handler function that implements the kill_server tool logic. It resolves a target by port or PID, validates safety (refuses system PIDs <1000), supports dry-run mode (confirm=false), sends SIGTERM by default (or SIGKILL if force=true), and escalates to SIGKILL after a 5-second grace period if the process hasn't exited.
export async function killServer(opts: { pid?: number; port?: number; confirm: boolean; force?: boolean; }): Promise<KillResult> { let target: DevServer | null = null; if (opts.port !== undefined) { target = await portInfo(opts.port); if (!target) { return { killed: false, pid: 0, signal: null, message: `No dev server on port ${opts.port}` }; } } else if (opts.pid !== undefined) { if (opts.pid < 1000) { return { killed: false, pid: opts.pid, signal: null, message: `Refused: PID ${opts.pid} is system process` }; } const info = await getProcessInfo(opts.pid); if (!info) { return { killed: false, pid: opts.pid, signal: null, message: `PID ${opts.pid} not found` }; } } else { return { killed: false, pid: 0, signal: null, message: "Must provide pid or port" }; } const pid = target?.pid ?? opts.pid!; if (pid < 1000) { return { killed: false, pid, signal: null, message: `Refused: PID ${pid} is system process`, target: target ?? undefined }; } if (!opts.confirm) { return { killed: false, pid, signal: null, message: `Dry run. Would SIGTERM pid ${pid}${target ? ` (${target.process} :${target.port})` : ""}. Re-call with confirm=true.`, target: target ?? undefined, }; } const signal: "SIGTERM" | "SIGKILL" = opts.force ? "SIGKILL" : "SIGTERM"; try { process.kill(pid, signal); } catch (e: any) { return { killed: false, pid, signal, message: `kill failed: ${e.message}`, target: target ?? undefined }; } if (signal === "SIGTERM") { // wait up to 5s for graceful exit for (let i = 0; i < 10; i++) { await sleep(500); if (!alive(pid)) { return { killed: true, pid, signal, message: `SIGTERM succeeded`, target: target ?? undefined }; } } // escalate try { process.kill(pid, "SIGKILL"); return { killed: true, pid, signal: "SIGKILL", message: `SIGTERM timeout, escalated to SIGKILL`, target: target ?? undefined }; } catch (e: any) { return { killed: false, pid, signal: "SIGKILL", message: `SIGKILL failed: ${e.message}`, target: target ?? undefined }; } } return { killed: true, pid, signal, message: `SIGKILL sent`, target: target ?? undefined }; } - src/index.ts:75-80 (schema)Zod schema for kill_server arguments validation: pid (optional positive int), port (optional 1-65535), confirm (boolean, default false), force (boolean, default false).
const KillArgs = z.object({ pid: z.number().int().positive().optional(), port: z.number().int().min(1).max(65535).optional(), confirm: z.boolean().default(false), force: z.boolean().default(false), }); - src/index.ts:32-45 (registration)Tool registration entry in the TOOLS array: declares the tool name 'kill_server', description, and JSON Schema input schema with pid, port, confirm, force properties.
{ name: "kill_server", description: "Kill a dev server by pid or port. Defaults to dry-run; pass confirm=true to actually kill. SIGTERM first, escalates to SIGKILL after 5s. Refuses system PIDs (<1000).", inputSchema: { type: "object", properties: { pid: { type: "number", description: "Process ID" }, port: { type: "number", description: "TCP port (alternative to pid)" }, confirm: { type: "boolean", description: "Must be true to actually kill", default: false }, force: { type: "boolean", description: "Use SIGKILL immediately, skip SIGTERM", default: false }, }, additionalProperties: false, }, }, - src/index.ts:95-99 (registration)Handler dispatch in the CallToolRequestSchema handler: parses args with KillArgs zod schema, calls killServer, and returns the result.
case "kill_server": { const parsed = KillArgs.parse(args ?? {}); const result = await killServer(parsed); return ok(result); } - src/killer.ts:80-87 (helper)Helper function 'alive' that checks if a process is still running using process.kill(pid, 0). Used in the graceful shutdown wait loop.
function alive(pid: number): boolean { try { process.kill(pid, 0); return true; } catch { return false; } }