Skip to main content
Glama

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

TableJSON Schema
NameRequiredDescriptionDefault
pidNoProcess ID
portNoTCP port (alternative to pid)
confirmNoMust be true to actually kill
forceNoUse SIGKILL immediately, skip SIGTERM

Implementation Reference

  • 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 };
    }
  • 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);
    }
  • 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;
      }
    }
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, but the description fully discloses key behaviors: dry-run, SIGTERM then SIGKILL after 5s, PID refusal below 1000, and force parameter for immediate kill.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two packed sentences, front-loaded with purpose, no wasted words. Every sentence adds critical info.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema, but tool is side-effect oriented. Missing explicit mention of success/failure indication, but behaviors are well covered. Adequate for a kill command.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema covers all params, but description adds context: default values, escalation behavior, and relationship between confirm and force, enhancing beyond schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clearly states action 'kill' and resource 'dev server', with specific methods (pid or port). Sibling tools are distinct (find, list, conflict, info), so no confusion.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Describes dry-run default and need for confirm=true, refusal of system PIDs. Does not explicitly compare to siblings, but usage context is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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/HasanJahidul/localhost-mcp'

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