mcp-systemctl
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-systemctlshow status of nginx"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mcp-systemctl
An MCP (Model Context Protocol) server that reports on and manages systemd services via systemctl and journalctl. Works with any MCP client — Claude Desktop, AI coding agents, or custom tooling.
Quick Start
npm install && npm run build
node dist/index.jsThe server speaks JSON-RPC over stdio (the standard MCP transport). Connect it to your MCP client — see MCP_SYSTEMCTL_USAGE.md for client configuration and all available tools.
Related MCP server: Linux MCP Server
Tools
Tool | Description |
| List systemd units with state/pattern/type filters |
| Detailed status of a specific service (PID, memory, CPU, uptime, etc.) |
| All services in a failed/error state |
| Recent journald log entries for a service |
| Start, stop, restart, reload, enable, or disable a service |
Full parameter details in MCP_SYSTEMCTL_USAGE.md.
Architecture
The project follows a clean three-layer separation:
src/index.ts — Server setup, tool registration
src/tools/*.ts — Zod input schemas + handler functions (thin glue)
src/systemctl.ts — Core logic: systemctl/journalctl exec, parsing, formatting┌──────────────┐ stdio (JSON-RPC) ┌──────────────────────┐
│ MCP Client │ ◄──────────────────────► │ mcp-systemctl │
│ │ │ (Node.js process) │
│ │ │ │
│ │ │ tools/*.ts │
│ │ │ → systemctl.ts │
│ │ │ → systemd │
└──────────────┘ └──────────────────────┘Layer Responsibilities
src/index.ts — Entry point. Creates the McpServer instance, calls server.registerTool() for each tool, then connects to the StdioServerTransport. Adding a new tool means importing its schema and handler and adding one more registerTool call here.
src/tools/ — One file per tool. Each exports:
A schema object (Zod-defined input parameters with
describe()for documentation)A handler function conforming to
ToolCallback<T>— receives validated args, calls intosystemctl.ts, formats the response as MCPcontentblocks
src/systemctl.ts — The engine. All systemctl and journalctl interactions live here:
Shell execution via
execFile(no shell injection risk)Structured result type
SystemctlResult<T>— every function returns{ ok: true, data }or{ ok: false, error, code, stderr }Parsers for the systemctl table and key=value output formats
Human-readable formatters for bytes, nanoseconds, etc.
Extending the Server
Adding a new tool takes four steps. This example adds a get_service_unit_file tool that returns a service's unit file contents.
1. Add the core logic in src/systemctl.ts
export async function getUnitFile(name: string): Promise<SystemctlResult<string>> {
const unitName = name.includes(".") ? name : `${name}.service`;
// Run: systemctl cat <unit>
const args = ["cat", unitName, "--no-pager", "-l"];
return await runSystemctl(args);
}Use the existing helpers — runSystemctl() and runJournalctl() handle timeouts, permission errors, and missing commands consistently. If you need to parse new output formats, add a parser alongside the existing ones.
2. Create the tool file src/tools/getUnitFile.ts
import * as z from "zod";
import type { ToolCallback } from "@modelcontextprotocol/sdk/server/mcp.js";
import { getUnitFile as getUnitFileCore } from "../systemctl.js";
export const getUnitFileSchema = {
name: z
.string()
.min(1)
.describe("Service name (e.g. 'sshd', 'cron.service')"),
};
export const getUnitFileHandler: ToolCallback<typeof getUnitFileSchema> = async (args) => {
try {
const result = await getUnitFileCore(args.name);
if (!result.ok) {
return {
content: [{ type: "text", text: `Error: ${result.error}` }],
isError: true,
};
}
return {
content: [{ type: "text", text: result.data }],
};
} catch (err) {
return {
content: [{ type: "text", text: `Internal error: ${err instanceof Error ? err.message : String(err)}` }],
isError: true,
};
}
};The pattern is always: import the core function → call it → check result.ok → format the response. Every handler returns { content: [...], isError?: boolean }.
3. Register the tool in src/index.ts
Add the imports:
import { getUnitFileSchema, getUnitFileHandler } from "./tools/getUnitFile.js";Add the registration (alongside the existing ones):
server.registerTool(
"get_unit_file",
{
description: "Print the unit file contents of a systemd service.",
inputSchema: getUnitFileSchema,
},
getUnitFileHandler,
);4. Build and test
npm run build
node dist/index.jsYour MCP client will now discover the new get_unit_file tool automatically — no client-side config changes needed.
Design conventions to follow
Convention | Why |
Every core function returns | Caller always handles errors explicitly; no thrown exceptions |
Use | Prevents shell injection through service names or patterns |
Schema parameters use | MCP clients use this description to document the parameter to the LLM |
Handlers wrap core calls in try/catch | Last-resort safety net for unexpected errors (not for expected failures) |
Permission errors handled in | Consistent messaging across all tools |
Source files use | Required by NodeNext module resolution with ESM |
What not to do
Don't put shell execution logic in tool handlers — keep it in
systemctl.tsDon't throw exceptions for expected failures (missing service, permission denied) — return error responses
Don't skip error handling on
result.ok— everySystemctlResultmust be checkedDon't use
anytypes — the Zod schema provides full type inferenceDon't add new dependencies without evaluating whether the existing patterns suffice
Project Structure
mcp-systemctl/
├── src/
│ ├── index.ts # Server entry point, tool registration
│ ├── systemctl.ts # Core systemctl/journalctl logic
│ └── tools/
│ ├── listServices.ts
│ ├── getServiceStatus.ts
│ ├── listFailedServices.ts
│ ├── getServiceLogs.ts
│ └── serviceControl.ts
├── dist/ # Build output (gitignored)
├── node_modules/ # Dependencies (gitignored)
├── MCP_SYSTEMCTL_USAGE.md
├── package.json
├── tsconfig.json
└── .gitignoreLicense
MIT
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/rileylsmith1997/sample-mcp-systemctl'
If you have feedback or need assistance with the MCP directory API, please join our Discord server