• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

apowers313 / servherd / 20961701317

13 Jan 2026 03:07PM UTC coverage: 82.727% (+1.2%) from 81.563%
20961701317

push

github

apowers313
test: improved test coverage to 81.56%

901 of 1027 branches covered (87.73%)

Branch coverage included in aggregate %.

3601 of 4415 relevant lines covered (81.56%)

13.72 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.75
/src/mcp/tools/stop.ts
1
import { z } from "zod";
1✔
2
import { executeStop } from "../../cli/commands/stop.js";
3
import type { StopResult } from "../../cli/output/formatters.js";
4

5
export const stopToolName = "servherd_stop";
1✔
6

7
export const stopToolDescription =
1✔
8
  "Stop one or more running development servers. " +
1✔
9
  "Use this tool when you need to gracefully shut down servers that are no longer needed or before making configuration changes. " +
10
  "Can target a specific server by name, all servers with a particular tag, or all managed servers at once. " +
11
  "Returns a list of results for each server with success status and a summary message. " +
12
  "Stopped servers remain in the registry and can be restarted later with servherd_start.";
13

14
export const stopToolSchema = z.object({
1✔
15
  name: z.string().optional().describe("Name of the server to stop, e.g., 'frontend-dev' or 'brave-tiger'"),
1✔
16
  all: z.boolean().optional().describe("Set to true to stop all managed servers"),
1✔
17
  tag: z.string().optional().describe("Stop all servers with this tag, e.g., 'frontend' or 'development'"),
1✔
18
  force: z.boolean().optional().describe("Force stop using SIGKILL instead of SIGTERM"),
1✔
19
});
1✔
20

21
export type StopToolInput = z.infer<typeof stopToolSchema>;
22

23
export interface StopToolResult {
24
  results: StopResult[];
25
  summary: string;
26
}
27

28
export async function handleStopTool(input: StopToolInput): Promise<StopToolResult> {
6✔
29
  // Validate input
30
  if (!input.name && !input.all && !input.tag) {
6✔
31
    throw new Error("Either name, all, or tag must be provided");
1✔
32
  }
1✔
33

34
  const results = await executeStop({
5✔
35
    name: input.name,
5✔
36
    all: input.all,
5✔
37
    tag: input.tag,
5✔
38
    force: input.force,
5✔
39
  });
5✔
40

41
  const successCount = results.filter((r) => r.success).length;
5✔
42
  const failCount = results.length - successCount;
5✔
43

44
  let summary: string;
5✔
45
  if (results.length === 0) {
6!
46
    summary = "No servers found to stop";
×
47
  } else if (failCount === 0) {
6✔
48
    summary = `Successfully stopped ${successCount} server${successCount !== 1 ? "s" : ""}`;
4✔
49
  } else {
5✔
50
    summary = `Stopped ${successCount} server${successCount !== 1 ? "s" : ""}, ${failCount} failed`;
1!
51
  }
1✔
52

53
  return {
5✔
54
    results,
5✔
55
    summary,
5✔
56
  };
5✔
57
}
5✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc