Skip to main content
Glama
README.md
# πŸ› οΈ MCP Linux Tools – Complete Tool Reference for LLMs

## πŸ“– Description

MCP Linux Tools is an MCP (Model Context Protocol) server that exposes a secure, whitelisted set of operations on a Linux server. It allows AI assistants (such as VS Code, Claude or Cursor) to perform controlled system administration tasks like reading logs, checking service status, managing cron jobs, running WP-CLI commands, and executing sandboxed Python codeβ€”all through a uniform API with strict security constraints.

The server runs as a systemd service and communicates over HTTP. All operations are restricted by configurable whitelists (directories, services, WordPress sites). Tools return a uniform response contract `{success, data, error, meta}`.

## ✨ Features

- **πŸ” Metadata & Discovery** – Server info, service whitelist, WordPress allowed sites
- **πŸ“‚ File Operations** – Read files, list directories, head/tail logs (whitelisted paths only)
- **βš™οΈ System Services** – Check status, reload or restart whitelisted services
- **🐍 Python Sandbox** – Execute Python code (no network, 8s timeout)
- **⏰ Cron Management** – List, add, remove, enable/disable cron jobs
- **🌐 WordPress** – WP-CLI runner, cache flush, plugin/user listing, log tailing
- **πŸ—„οΈ Database** – Read-only MySQL queries (dangerous queries blocked)
- **πŸ“‘ Network** – Ping for connectivity testing
- **πŸ“Œ Git** – Safe Git commands (no push/force)

## πŸ“¦ Installation

### Requirements
- Python 3.13 or higher
- Root access (for systemctl and crontab)
- Linux system with systemd

### Step 1: Clone Repository
```bash
# Clone the MCP server repository to /opt/mcp
sudo mkdir -p /opt
cd /opt
sudo git clone https://github.com/gerard-kanters/mcp-linux-tools.git mcp
cd /opt/mcp
```

### Step 2: Create Python Virtual Environment
```bash
# Create virtual environment
sudo python3.13 -m venv /opt/mcp/venv

# Install dependencies
sudo /opt/mcp/venv/bin/pip install --upgrade pip
sudo /opt/mcp/venv/bin/pip install -r requirements.txt --break-system-packages
```

### Step 3: Configure
Edit `config.json` and adjust the settings for your server:
- Set `server_type` (development or production)
- Set `server_ip` to your server's IP address
- Set `server_name` to identify this server
- Configure directory whitelists, service whitelist, and other settings as needed

See the [Configuration](#-configuration) section below for detailed information about all configuration options.

### Step 4: Create Sandbox Directory
```bash
sudo mkdir -p /opt/mcp/sandbox
sudo chown root:root /opt/mcp/sandbox
sudo chmod 755 /opt/mcp/sandbox
```

### Step 5: Install Systemd Service
Create a service file: `/etc/systemd/system/mcp-linux-tools.service`

```ini
[Unit]
Description=MCP Linux Tools Server
After=network.target

[Service]
Type=simple
User=root
WorkingDirectory=/opt/mcp
ExecStart=/opt/mcp/venv/bin/python /opt/mcp/server.py
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal

# Security settings
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/log /opt/mcp/sandbox

[Install]
WantedBy=multi-user.target
```

Enable and start the service:
```bash
sudo systemctl daemon-reload
sudo systemctl enable mcp-linux-tools.service
sudo systemctl start mcp-linux-tools.service
sudo systemctl status mcp-linux-tools.service
```

### Step 6: Cursor MCP Configuration
Add to your Cursor MCP configuration (usually `~/.cursor/mcp.json` or in Cursor settings):

```json
{
  "mcpServers": {
    "linux-tools": {
      "command": "curl",
      "args": [
        "-X", "POST",
        "http://192.168.1.22:8765/mcp",
        "-H", "Content-Type: application/json",
        "-d", "@-"
      ]
    }
  }
}
```

Or use direct HTTP transport in Cursor MCP settings with:
- URL: `http://192.168.1.22:8765/mcp`
- Transport: HTTP

### Verification
Check if the server is running:
```bash
# Check service status
sudo systemctl status mcp-linux-tools.service

# Check logs
sudo journalctl -u mcp-linux-tools.service -f

# Test HTTP endpoint
curl -X POST http://localhost:8765/mcp -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","method":"tools/list","id":1}'
```

### Installing Updates
To update the MCP server:

```bash
cd /opt/mcp
sudo git pull origin main  # or master, depending on your branch
sudo /opt/mcp/venv/bin/pip install -r requirements.txt --break-system-packages
sudo systemctl restart mcp-linux-tools.service
```

**Important**: After an update, check if `config.json` is still correct. New configuration options may have been added.

---

## πŸ—οΈ Architecture

The server follows a modular MCP architecture:

- `server.py` – Entrypoint: config loading, MCP setup, tool registration, run/retry/signal handling
- `config.py` – Config loading and validation (fail-fast on missing fields)
- `register_tools.py` – Central tool registration
- `core/` – Core modules:
  - `errors.py` – Error codes (DENIED_PATH, INVALID_INPUT, COMMAND_BLOCKED, etc.)
  - `models.py` – Pydantic models for uniform response contract
  - `response.py` – ok(), err(), err_denied_* helpers
  - `security.py` – Allowlist and path validation
  - `process.py` – Subprocess runner
- `tools/` – Tool modules per domain:
  - `discovery.py`, `filesystem.py`, `logs.py`, `systemd.py`
  - `python_exec.py`, `wordpress.py`, `cron_tools.py`, `ops.py`

All tools return a uniform response contract: `{success, data, error, meta}`.

---

## βš™οΈ Configuration

All configuration is done via `config.json` in the root of the MCP server directory (`/opt/mcp/config.json`).

### Configuration Sections

#### Server Identification
- `server_type`: "development" or "production"
- `server_ip`: IP address of the server
- `server_name`: Name for the MCP server

#### Server Listen (optional)
- `server.host`: Bind address (default: "0.0.0.0")
- `server.port`: HTTP port (default: 8765)

#### Logging
- `logging.log_file`: Path to log file

#### Limits
- `limits.max_bytes`: Maximum file size for reading (default: 524288 = 512KB)
- `limits.max_items`: Maximum items in directory listings (default: 500)

#### Python Sandbox
- `python.bin`: Path to Python interpreter (must be in venv)
- `directories.sandbox_cwd`: Working directory for Python sandbox

#### Directory Whitelists
- `directories.allowed_read`: Directories from which files can be read
- `directories.allowed_log`: Directories where log files can be read
- `directories.allowed_write`: Directories where write operations are allowed

#### Services
- `services.whitelist`: List of service names that can be managed

#### WordPress
- `wordpress.allowed_sites`: Absolute paths to WordPress roots
- `wordpress.bin_candidates`: Possible locations for WP-CLI binary
- `wordpress.log_candidates`: Possible locations for WordPress debug logs

**Important**: After changes to `config.json`, the service must be restarted:
```bash
sudo systemctl restart mcp-linux-tools.service
```

---

## πŸ”’ SECURITY OVERVIEW

**LINUX SERVER Tools** with limited write operations:

### βœ… WHAT IS ALLOWED:
- **READ Files** (in allowed directories)
- **VIEW Logs** (system logs)
- **CHECK Service STATUS** and **RESTART** (only whitelisted services)
- **EXECUTE Python CODE** (sandboxed, no network, 8s timeout)
- **MANAGE Cron JOBS** (only within MCP-managed section)

### ❌ WHAT IS NOT ALLOWED:
- Access to arbitrary directories (strict whitelisting)
- Services **STOP/START/ENABLE** (only restart allowed)
- Sudo/root operations
- Python with network access
- Modifying system crontab outside MCP section

---

## πŸ“‚ ALLOWED DIRECTORIES

Directory whitelists are configured in `config.json` under `directories`.

### Read Access (allowed_read):
Default: `/var/log`, `/etc`, `/tmp`, `/opt/`, `/root/scripts`, `/var/www`

### Log Access (allowed_log):
Default: `/var/log`, `/tmp`, `/var/www`

### Write Access (allowed_write):
Default: `/var/www`, `/opt/`

**Note**: All directory paths are configurable via `config.json`. Changes require a service restart.

---

## πŸ› οΈ ALLOWED SERVICES (SERVICE_WHITELIST)

The service whitelist is configured in `config.json` under `services.whitelist`. Only services in this list can be checked or restarted.

**Default whitelist** (as configured in config.json):
- `apache2` - Apache webserver
- `php8.4-fpm` - PHP FastCGI Process Manager
- `postfix` - Mail server
- `opendkim` - DomainKeys email authentication
- `sshd` - SSH daemon
- `docker` - Container runtime
- `memcached` - Memory cache daemon
- `postgresql` - PostgreSQL database server
- `odoo` - Odoo ERP system

**Note**: Service names may vary by distribution. Use `get_service_whitelist()` to query the active whitelist.

---

## πŸ“š TOOL CATEGORIES

### 1️⃣ METADATA & DISCOVERY (Read-Only)
- `get_server_info()` - Server identification (type, IP, name)
- `get_service_whitelist()` - List of manageable services
- `get_wp_allowed_sites()` - List of allowed WordPress sites

### 2️⃣ FILE OPERATIONS
- `list_dir(path, pattern, include_files, include_dirs, max_items)` - Directory listing (Read-Only)
- `read_file(path, max_bytes)` - Read file (max 512KB, Read-Only)
- `head(path, n)` - First N lines (Read-Only)
- `tail(path, n)` - Last N lines (for logs, Read-Only)
- `log_search(keywords, path, n)` - Search literal keywords in recent log lines (Read-Only)
- `create_directory(path, owner, group, mode, parents)` - Create directory ⚠️ (only /var/www and /opt/)
- `chmod_file(path, mode)` - Change file permissions ⚠️ (only /var/www and /opt/)
- `chown_path(path, owner, group)` - Change owner ⚠️ (only /var/www and /opt/)

### 3️⃣ SYSTEM SERVICES
- `service_status(name)` - Check status (Read-Only)
- `reload_service(name)` - Reload service via `systemctl reload` (preferred action, low impact)
- `restart_service(name, force_restart)` - Service modification: default is reload, use `force_restart=True` for full restart ⚠️ (Live impact!)

### 4️⃣ PYTHON EXECUTION
- `python_run(code)` - Sandboxed Python (no network, 8s timeout)

### 5️⃣ CRON MANAGEMENT
- `cron_list()` - View crontab (Read-Only)
- `cron_add(job_id, schedule, command)` - Add job ⚠️ (Live impact!)
- `cron_remove(job_id)` - Remove job ⚠️ (Live impact!)
- `cron_enable(job_id, enabled)` - Enable/disable job ⚠️ (Live impact!)
- `cron_next_runs(schedule, n)` - Validate schedule (Read-Only)

### 6️⃣ WORDPRESS OPERATIONS
- `wp_cli(site_path, args, as_www_data)` - WP-CLI runner for allowed sites
- `wp_cache_flush(site_path, as_www_data)` - WordPress cache flush
- `wp_plugin_list(site_path, as_www_data)` - List all plugins (JSON)
- `wp_user_list(site_path, as_www_data)` - List all users (JSON)
- `log_pick_path()` - Find WordPress debug log path

### 7️⃣ DATABASE OPERATIONS
- `mysql_query(query, database)` - Execute MySQL query (Read-Only, dangerous queries blocked)

### 8️⃣ NETWORK OPERATIONS
- `ping_host(host, count)` - Test network connectivity (Read-Only)

### 9️⃣ GIT OPERATIONS
- `git_command(path, command)` - Execute Git commands (only safe commands, no push/force)

### πŸ”Ÿ SYSTEM COMMANDS
- `execute_shell_command(command, user)` - Execute shell command ⚠️ (Live impact!)

---

## πŸ’‘ USAGE EXAMPLES

### Server Info:
```json
{"tool": "get_server_info", "args": {}}
```

### Service Whitelist:
```json
{"tool": "get_service_whitelist", "args": {}}
```

### Service Status:
```json
{"tool": "service_status", "args": {
  "name": "nginx"
}}
```

### Restart Service:
```json
{"tool": "restart_service", "args": {
  "name": "mysql"
}}
```

### View Log File:
```json
{"tool": "tail", "args": {
  "path": "/var/log/nginx/error.log",
  "n": 100
}}
```

### Execute Python:
```json
{"tool": "python_run", "args": {
  "code": "import sys; print(sys.version)"
}}
```

### WordPress Cache Flush:
```json
{"tool": "wp_cache_flush", "args": {
  "site_path": "/var/www/netcare.nl"
}}
```

### WordPress Plugin List:
```json
{"tool": "wp_plugin_list", "args": {
  "site_path": "/var/www/netcare.nl"
}}
```

### MySQL Query:
```json
{"tool": "mysql_query", "args": {
  "query": "SHOW DATABASES;",
  "database": ""
}}
```

### Network Ping:
```json
{"tool": "ping_host", "args": {
  "host": "8.8.8.8",
  "count": 4
}}
```

### Git Status:
```json
{"tool": "git_command", "args": {
  "path": "/var/www/example",
  "command": "status"
}}
```

### Add Cron Job:
```json
{"tool": "cron_add", "args": {
  "job_id": "backup_daily",
  "schedule": "0 3 * * *",
  "command": "/usr/bin/backup.sh"
}}
```

---

## ⚠️ IMPORTANT NOTES FOR LLMs

1. **Read-Only Default**: Most tools are read-only. Write operations are limited to:
   - `reload_service()` / `restart_service()` - Service reload/restart
   - `cron_add/remove/enable()` - Cron modifications
   - `create_directory()` - Create directory (only /var/www and /opt/)
   - `chmod_file()` - Change file permissions (only /var/www and /opt/)
   - `chown_path()` - Change owner (only /var/www and /opt/)
   - `execute_shell_command()` - Shell commands (use with caution!)

2. **Whitelisting**: Everything is whitelisted. Tools return "Denied" if you work outside the whitelist.

3. **Service Names**: Different distributions use different service names. For example:
   - DNS: `systemd-resolved`, `bind9`, or `named`
   - DHCP: `isc-dhcp-server` or `dhcpd`
   - MySQL: `mysql`, `mariadb`, or `mysqld`
   - SMB: `smbd` or `samba`

4. **Security First**: 
   - No blind `rm -rf` possible
   - No arbitrary file writes
   - Python is sandboxed
   - Cron commands must use absolute paths

5. **Error Handling** – Uniform response contract `{success, data, error, meta}`:
   - `success=true`: data contains result, error is null
   - `success=false`: error contains `{code, message, hint}`, data is null
   - Error codes: DENIED_PATH, DENIED_SERVICE, DENIED_SITE, INVALID_INPUT, COMMAND_BLOCKED, NOT_FOUND, TIMEOUT, etc.
   - meta: server_type, server_ip, server_name

6. **Return Types**:
   - Strings for simple output
   - Dicts for structured data (Python, MySQL, etc.)
   - Lists for directories and cron schedules

---

## 🎯 BEST PRACTICES

1. **Server identification**: Use `get_server_info()` to verify which server you're working on
2. **Check whitelists first**: Call `get_service_whitelist()` before managing services
3. **Read-only first**: Check status/logs before restarting services
4. **Validate cron schedules**: Use `cron_next_runs()` to validate schedules
5. **Service names**: Check which service name is used on the system
6. **Error handling**: Always check for "Denied" or {"error": ...} in responses
7. **Log locations**: Use `list_dir()` to explore log directories before reading logs
8. **Config changes**: Always restart the service after changes to `config.json`

---

## πŸ“Š TESTED & VERIFIED

All tools have been tested and work correctly:
βœ… Service status and restart functionality
βœ… Log file reading
βœ… Python 3.13 execution (sandboxed)
βœ… Cron schedule validation
βœ… File operations (read-only)
βœ… Directory listing

**Last Updated**: 2026-03-03
**Server**: Linux (generic)
**Environment**: Production/Development
**Configuration**: Via `config.json` (no hardcoded values)
**Architecture**: Modular (server.py entrypoint, core/, tools/)

TDQS

A3.7/5.0

Scored across 29 tools

Disambiguation3/5

Most tools have clearly distinct purposes, but several boundaries overlap: reload_service and restart_service both perform a reload by default, and wp_cli overlaps with wp_cache_flush, wp_plugin_list, and wp_user_list while execute_shell_command overlaps with python_run, git_command, and mysql_query. The detailed descriptions help an agent choose, but the redundancy still creates moderate selection risk.

Naming Consistency3/5

Names are consistently lowercase snake_case, but the verb/noun ordering is mixed: verb-first names like read_file and create_directory sit alongside noun-first names like cron_add, service_status, and wp_plugin_list, plus get_* info tools. This is readable and predictable within subsystems, but there is no single global naming convention.

Tool Count2/5

With 29 tools, the set exceeds the 25+ threshold and feels heavy for its scope. Several tools are redundant, notably reload_service versus restart_service, wp_cli versus the specialized wp_* helpers, and execute_shell_command versus python_run, git_command, and mysql_query. A tighter set of around 20 tools would be clearer.

Completeness4/5

Core Linux administration workflows are covered: service status/reload/restart, directory and file reading, log inspection, WP-CLI operations, cron lifecycle management, SQL queries, git, and generic shell execution. Minor gaps exist, such as no dedicated file write/delete or explicit service start/stop, but execute_shell_command provides a workaround for those cases.

Maintenance

ActivitySlowing
ResponsivenessUnresponsive