Skip to main content
Glama
GrumpyMetalGuy

MCP Linux Log Server

README.md
# MCP Linux Log Server

A distributed MCP (Model Context Protocol) server that exposes Linux system logs to AI for diagnostic and predictive analysis.

## Overview

MCP Log Server allows Claude and other AI assistants to read and analyze your system logs, including:

- **systemd journal** (journalctl) - Structured system logs
- **Traditional syslog** - /var/log/syslog, auth.log, etc. (Phase 3)
- **Kernel logs** - dmesg output (Phase 3)
- **Application logs** - nginx, apache, postgresql, etc. (Phase 3)

**Architecture**: One MCP server per machine (distributed model)
- Local PC: stdio transport → Claude Desktop
- Remote machines: HTTP/SSE transport over network
- Each server reads only its local logs (no SSH complexity)

## Current Status: Phase 3 Complete

✅ **Implemented**:
- **Systemd journal** reading with rich filtering
  - Time filtering (relative and absolute)
  - Priority/severity filtering
  - Unit-specific filtering
  - Boot filtering
- **Syslog files** (auth.log, syslog, kern.log)
  - Secure file reading with path validation
  - Text search and line limits
  - Tail mode for recent entries
- **Kernel logs** (dmesg)
  - Time and priority filtering
  - Direct kernel ring buffer access
- **Application logs** (nginx, apache, postgresql)
  - Auto-detection based on file existence
  - Support for log rotation patterns (globs)
  - Error and access logs
- **Configuration management** (YAML)
- **Transport modes**: stdio (Claude Desktop) and HTTP/SSE (remote)

⏳ **Planned** (Phases 4-5):
- Enhanced deployment automation
- Systemd service files for remote servers
- TLS/HTTPS support
- Real-time log streaming
- Log aggregation across machines

## Features

### Resource URIs

Access logs via hierarchical URIs with query parameters:

**Systemd Journal:**
```
log://systemd/journal?since=now-24h&priority=err&limit=500
log://systemd/errors
log://systemd/current-boot
log://systemd/journal/nginx.service
```

**Syslog Files:**
```
log://syslog/syslog?tail=true&limit=1000
log://syslog/auth?grep=failed
log://syslog/kern
```

**Kernel Logs (dmesg):**
```
log://kernel/dmesg?since=1 hour ago
log://kernel/errors
```

**Application Logs:**
```
log://app/nginx/error?tail=true&limit=500
log://app/nginx/access?grep=404
log://app/apache2/error
log://app/postgresql/main
```

**Docker Container Logs:**
```
log://docker/containers                          # List all containers
log://docker/containers?all=true                 # Include stopped containers
log://docker/myapp?tail=200&since=now-1h
log://docker/postgres-db?grep=error
```

### Query Parameters

- `since` / `until` - Time filters (ISO 8601 or relative like "now-24h", "2d")
- `priority` - Log level (emerg, alert, crit, err, warning, notice, info, debug)
- `limit` - Max entries (default: 1000, max: 10000)
- `grep` - Text search filter
- `unit` - Filter by systemd unit
- `boot` - Boot ID or relative (0=current, -1=previous)

## Deployment

The server runs in two deployment modes:

- **Direct (native) install** — best for stdio clients on the same machine (Claude Desktop, Claude Code, LM Studio).
- **Docker** — best for long-running HTTP deployments and remote AI clients.

A full step-by-step guide for both modes, plus client-specific setup for
Claude Desktop, Claude Code, OpenCode, LM Studio, Open WebUI, Continue,
Cline, Cursor, and Zed, is in **[RUNNING.md](RUNNING.md)**. The condensed
quick-start lives below.

### Prerequisites (direct install)

- Linux system with systemd
- Python 3.10 or higher
- [uv](https://docs.astral.sh/uv/) - Modern Python package manager
- System dependencies:
  - `libsystemd-dev` - Required for systemd-python bindings

Install system dependencies on Debian/Ubuntu:
```bash
sudo apt install libsystemd-dev
```

Install uv if not already installed:
```bash
curl -LsSf https://astral.sh/uv/install.sh | sh
```

### Quick Install (direct)

1. Clone or download this repository:
   ```bash
   cd /path/to/mcp-log-server
   ```

2. Run the installation script:
   ```bash
   ./scripts/install.sh
   ```

3. **Important**: Log out and log back in for group membership to take effect

4. Test the installation:
   ```bash
   python3 scripts/test-access.py
   ```

### Quick Install (Docker)

```bash
cd /path/to/mcp-log-server
docker compose up -d
docker compose logs -f
```

The HTTP endpoint is published on host port **3001** by default, mapped to
container port 8000. Connect MCP clients at `http://<host-ip>:3001/mcp`.
For volume mounts, build details, and capability tuning see
[DOCKER.md](DOCKER.md).

### Manual Installation

If you prefer manual installation:

1. Install system dependencies:
   ```bash
   sudo apt install libsystemd-dev
   ```

2. Create virtual environment and install:
   ```bash
   uv venv
   uv pip install -e .
   ```

3. Add your user to the `systemd-journal` group:
   ```bash
   sudo usermod -aG systemd-journal $USER
   ```

4. Log out and log back in

5. Create config directory:
   ```bash
   mkdir -p ~/.config/mcp-log-server
   ```

## Configuration

### Connecting an AI client

See **[RUNNING.md](RUNNING.md#part-2--client-integration)** for full,
copy-pasteable configs for:

- Claude Desktop
- Claude Code (`claude mcp add ...`)
- OpenCode
- LM Studio
- Open WebUI (via `mcpo` bridge)
- Continue, Cline, Cursor, Zed
- Generic MCP clients (stdio + Streamable HTTP at `/mcp`)

Minimum example — Claude Desktop pointing at a local install:

```json
{
  "mcpServers": {
    "local-logs": {
      "command": "/path/to/mcp-log-server/.venv/bin/mcp-log-server"
    }
  }
}
```

Restart the client after editing its config.

### Remote / HTTP access

Run the server with `--http` (native) or via `docker compose up -d` (Docker).
Clients then connect at `http://<host>:<port>/mcp` — for example:

```json
{
  "mcpServers": {
    "remote-logs": {
      "url": "http://192.0.2.100:3001/mcp",
      "transport": "http"
    }
  }
}
```

> Use the `/mcp` path, not `/sse`. The legacy SSE transport is not served
> in `--http` mode — see [RUNNING.md](RUNNING.md#legacy-sse-clients) for the
> workaround if a client only speaks SSE.

### Custom Configuration

Create `~/.config/mcp-log-server/local.yaml` to override defaults:

```yaml
server:
  machine_name: my-server
  max_entries: 2000

sources:
  systemd:
    enabled: true

security:
  max_file_size: 209715200  # 200MB
```

See `config/default.yaml` for all available options.

## Usage with Claude Desktop

Once installed and configured with Claude Desktop, you can ask Claude questions like:

- "Show me systemd errors from the last 24 hours"
- "What's happening with nginx?"
- "Show me kernel boot messages"
- "Are there any failed systemd units?"
- "Check authentication logs for failed login attempts"
- "Show me recent nginx errors"
- "What kernel errors occurred in the last hour?"
- "Check postgres logs for issues"
- "Show me failed SSH login attempts"

Claude will:
1. See available log resources via MCP
2. Determine appropriate resource URI and filters
3. Read and analyze the logs
4. Provide insights and recommendations

## Usage with Ollama (Local Models)

For fully-local, offline log analysis the project ships scripts that call the
readers directly and pipe results through Ollama — no MCP client required.
See **[RUNNING.md — Part 3](RUNNING.md#part-3--local-analysis-with-ollama)**
for model recommendations, the analysis scripts, and cron-based monitoring.

**Quick start with Ollama:**

```bash
uv pip install -e ".[ollama]"
ollama pull qwen2.5:14b
uv run python scripts/analyze-logs.py
```

### Command Line Usage

You can also run the server directly:

```bash
# stdio mode (for Claude Desktop)
uv run mcp-log-server

# HTTP/SSE mode (for remote access)
uv run mcp-log-server --http --port 8000

# Custom config file
uv run mcp-log-server --config /path/to/config.yaml

# Or using python -m
uv run python -m mcp_log_server.server
```

## Security

- **Read-Only**: Server never modifies logs or system
- **No Root Required**: Uses `systemd-journal` group for journal access
- **Path Validation**: File-based logs restricted to allowed paths
- **Resource Limits**: Max entries, file sizes, and response sizes enforced
- **Container Security**: Docker deployment uses minimal capabilities (SYSLOG vs SYS_ADMIN)
- **Network Security**: Designed for reverse proxy deployment with HTTPS and authentication

## Troubleshooting

### Permission Denied Errors

If you get permission errors when reading the journal:

1. Check group membership:
   ```bash
   groups
   ```
   You should see `systemd-journal` in the list.

2. If not, run:
   ```bash
   sudo usermod -aG systemd-journal $USER
   ```

3. **Important**: Log out and log back in (or reboot)

4. Verify again:
   ```bash
   groups
   journalctl -n 10  # Should work without sudo
   ```

### Claude Desktop Not Seeing Server

1. Check the config file path is correct:
   - Use absolute paths, not `~`
   - Use `/home/$(whoami)/.local/bin/mcp-log-server`

2. Verify the command exists:
   ```bash
   which mcp-log-server
   ls -l ~/.local/bin/mcp-log-server
   ```

3. Test manually:
   ```bash
   mcp-log-server
   ```
   Should start without errors.

4. Check Claude Desktop logs for errors

### No Entries Returned

1. Test journal access:
   ```bash
   journalctl -n 10
   ```

2. Run pre-flight checks:
   ```bash
   python3 scripts/test-access.py
   ```

3. Check time filters - relative times like "now-24h" may not match if your journal is older

## Development

### Project Structure

```
mcp-log-server/
├── src/mcp_log_server/
│   ├── server.py              # Main FastMCP server
│   ├── config.py              # Configuration management
│   ├── resources/
│   │   └── systemd.py         # systemd journal resources
│   ├── readers/
│   │   └── journal_reader.py  # Journal reading logic
│   ├── filters/               # Query filters (future)
│   └── utils/                 # Utilities (future)
├── config/
│   ├── default.yaml           # Default configuration
│   └── claude-desktop.json.example
├── scripts/
│   ├── install.sh             # Installation script
│   ├── setup-permissions.sh   # Permission setup
│   └── test-access.py         # Pre-flight checks
└── pyproject.toml
```

### Running Tests

```bash
pip install -e ".[dev]"
pytest
```

## Roadmap

### Phase 2: Enhanced Filtering ✅ (Integrated into Phase 3)
- Advanced time parsing ✅
- Complex query combinations ✅
- Extended resource types ✅

### Phase 3: Additional Log Sources ✅ Complete
- Traditional syslog files ✅
- Kernel logs (dmesg) ✅
- Application-specific logs (nginx, apache, postgresql) ✅
- Auto-detection of installed applications ✅

### Phase 4: Remote Access (Partially Complete)
- Systemd service file for auto-start
- TLS/HTTPS support
- Authentication (API keys, basic auth)

### Phase 5: Advanced Features
- Real-time log streaming
- Log aggregation across machines
- Custom log parsers
- Statistics and summaries
- Alerting integration

## License

MIT License - See LICENSE file for details

## Contributing

Contributions welcome! Please:
1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Submit a pull request

## Support

- Issues: https://github.com/GrumpyMetalGuy/mcp-log-server/issues
- Documentation: See this README and code comments

## Acknowledgments

- Built with [FastMCP](https://github.com/anthropics/fastmcp) - Python MCP SDK
- Uses [systemd-python](https://github.com/systemd/python-systemd) for journal access