Labsco
paulomac1000 logo

mikrus-mcp

ā˜… 10

from paulomac1000

MCP (Model Context Protocol) server for managing VPS servers via the mikr.us API and remote Linux servers over SSH. Built in Python, runs anywhere — locally, in Docker, or as a Claude Desktop integration.

šŸ”„šŸ”„šŸ”„āœ“ VerifiedAccount requiredAdvanced setup

Mikrus MCP Server

MCP (Model Context Protocol) server for managing VPS servers via the mikr.us API and remote Linux servers over SSH. Built in Python, runs anywhere — locally, in Docker, or as a Claude Desktop integration.

All tools follow the MCP Server Standards for response format, testing, and documentation.

Contents

Available Tools

Discovery

ToolDescription
list_configured_serversList all configured servers, their types, and connection status. Use this first to discover available servers.
describe_mikrus_capabilitiesReturns the full tool catalog with capability manifests, supported transports, and schema version. Zero I/O, instant.

mikr.us API tools (mikrus servers only)

ToolAPI endpointDescription
get_server_info/infoServer info: ID, RAM, disk, expiration date, PRO plan status (cache=60s)
list_servers/serweryList all servers associated with the account (cache=60s)
get_server_stats/statsUsage stats: RAM, disk, uptime, load avg, processes (cache=60s)
execute_command/execExecute a shell command on the server (60s API limit)
restart_server/restartRestart the VPS server
get_logs/logsLast 10 task log entries from the panel
get_log_by_id/logs/IDDetails of a specific log entry by ID
boost_server/amfetaminaTemporary resource boost (+512MB RAM for 30 min, free)
get_db_info/dbDatabase access credentials (MySQL/PostgreSQL, cache=60s)
get_ports/portyAssigned TCP/UDP ports (cache=60s)
get_cloud/cloudCloud services and statistics assigned to the account
assign_domain/domainAssign a domain to a port (use - for auto-generated subdomain)

System management tools (mikrus + SSH servers)

ToolDescription
read_fileRead a text file from the server (up to 200 lines)
write_fileWrite text content to a file (base64-safe transfer)
manage_serviceManage systemd services: status, start, stop, restart, enable, disable
analyze_diskDisk usage overview (df -h + top-20 largest directories)
check_portCheck if a TCP port is listening and what process uses it
manage_processList top processes by memory or kill a process by PID/name
update_systemRun system updates (apt update && apt upgrade -y)
list_directoryList directory contents (ls -la)
tail_fileRead last N lines from a text file (max 500)
search_in_filesSearch for a pattern in files under a path (grep -r)
get_memory_infoShow memory usage (free -h)
get_network_infoShow network interfaces and listening TCP ports
get_process_treeShow running processes in a tree view (ps auxf)

Docker tools (mikrus + SSH servers, requires Docker access)

ToolDescription
list_docker_containersList all Docker containers with status and image
get_docker_logsFetch recent logs from a Docker container
get_docker_statsShow resource usage stats for Docker containers

Journal tools (mikrus + SSH servers, may require sudo_password)

ToolDescription
get_journal_logsFetch systemd journal logs for a specific service unit
find_system_errorsFind error-level journal entries from the last N hours
search_journal_logsSearch journal logs for a keyword or phrase

Note about journal tools: If the remote user is not in the systemd-journal or adm group, journal commands will fail. To fix this, add sudo_password to the SSH server configuration. If sudo_password is omitted, the tool will still work but returns a helpful hint for the user when privileges are insufficient.

All system tools accept an optional server parameter to target a specific configured server (e.g. server=myssh). If omitted, the default server is used.

Tool Response Format

All 33 tools return a consistent JSON structure. Every response includes a _meta envelope with a unique request_id:

{"success": true, "data": {"server_id": "emil359", "param_ram": "1024"}, "_meta": {"request_id": "a1b2c3d4-...", "duration_ms": 42, "cached": false, "retry_safe": false}}

On failure:

{"success": false, "error": "Server 'unknown' is not a mikrus server", "_meta": {"request_id": "e5f6g7h8-..."}}

The success field is always a boolean. Successful responses contain a data key with the tool-specific result. Error responses contain an error key with a human-readable message. No tool raises unhandled exceptions — errors are always returned as structured JSON.

Tools are annotated with risk-level prefixes in their descriptions:

PrefixMeaningExamples
[DANGEROUS]Executes arbitrary shell commandsexecute_command
[WRITE]Modifies server state or fileswrite_file, update_system
[DESTRUCTIVE]Kills processes, restarts servicesmanage_service (stop/restart), manage_process (kill)
[SENSITIVE]Returns credentials or tokensget_db_info, get_journal_logs
(none)Read-only, no side effectsget_server_info, list_servers, describe_mikrus_capabilities

AI agents use these prefixes to decide whether to request user confirmation before invoking a tool. Tools are additionally gated behind ENABLE_WRITE_OPERATIONS — a server-level authorization flag that must be explicitly enabled for any write, destructive, or command-execution tool to perform I/O.

Security Considerations

This MCP server grants full system access to configured servers. Treat it as a privileged remote administration tool.

SSE Transport

  • By default, SSE listens on 127.0.0.1 only.
  • Binding to 0.0.0.0 requires MCP_UNSAFE_PUBLIC_ACCESS_CONFIRMED=1.
  • Never expose SSE to the internet without authentication. Use a reverse proxy (nginx, Traefik) with TLS and basic auth if remote access is needed.

SSH Security

  • verify_host_key defaults to false for ease of use. In production, set it to true and provide a known_hosts_file to prevent MITM attacks.
  • sudo_password is fed via asyncssh.create_process + stdin, never via shell string interpolation, so it won't appear in ps aux.
  • SSH private keys mounted into Docker must have permissions 600 or 400.

Input Validation

  • All file paths are validated against traversal (..) and forbidden paths (e.g. /etc/shadow).
  • Dangerous commands (rm -rf /, mkfs, dd if=) are blocked before execution.
  • Shell metacharacters (;, |, $, `) in commands are rejected before any patterns are checked.
  • Service names, container names, ports, and domains are validated with strict regex patterns.
  • File writes outside /home, /var/www, /opt, /tmp, /srv, /var/log trigger a warning.

Write Guard

  • Write, destructive, and command-execution tools are gated behind ENABLE_WRITE_OPERATIONS=1 (default: disabled).
  • When disabled, these tools return a structured error before any I/O.
  • Read-only actions (manage_service status, manage_process list) bypass the write guard.

Credentials

  • API keys and passwords are loaded from environment variables or .env (gitignored).
  • Never commit credentials to version control.

Development

Setup

pip install -e ".[dev]"

Run tests

# Unit tests (fast, no credentials needed) — 310 tests
pytest tests/unit/ -q --cov=mikrus_mcp --cov-report=term

# Smoke tests — API connectivity and response format
pytest tests/smoke/ -q

# Integration tests — real mikr.us API
pytest tests/integration/ -q

# E2E tests — full pipeline workflows
pytest tests/e2e/ -q

All tests use respx (HTTP mocking) or unittest.mock (SSH mocking). No real network calls are made in unit or e2e tests. Smoke and integration tests require a valid MIKRUS_API_KEY and skip gracefully otherwise.

REST Bridge (optional testing utility)

Set MCP_REST_PORT to expose an HTTP bridge that turns tool calls into REST endpoints:

MCP_PORT=8300 MCP_REST_PORT=8301 mikrus-mcp
# GET  http://127.0.0.1:8301/health
# GET  http://127.0.0.1:8301/tools
# POST http://127.0.0.1:8301/tools/get_server_info  {"params": {}}

This is a development utility for smoke testing and debugging. It is separate from the MCP SSE transport and runs on its own port. All endpoints have /api/ prefixed mirrors (GET /api/health, GET /api/tools, POST /api/tools/{name}). Tool manifest endpoints are also available at GET /tools/{name}/manifest and GET /api/tools/{name}/manifest.

Lint & type check

ruff check src/ tests/
ruff format --check src/ tests/
mypy src/
bandit -r src/

In Docker

docker compose run --rm test

Architecture

src/mikrus_mcp/
ā”œā”€ā”€ __init__.py          # Package version
ā”œā”€ā”€ __main__.py          # python -m mikrus_mcp entry point
ā”œā”€ā”€ config.py            # Environment variable loader (dotenv) — single-server, multi-server, SSH-only
ā”œā”€ā”€ constants.py         # Backward-compat re-export for tools/constants.py
ā”œā”€ā”€ validators.py        # Centralized input validation (path, port, service, container, domain)
ā”œā”€ā”€ sanitizer.py         # Log sanitization (redacts API keys, IPs, passwords, MACs)
ā”œā”€ā”€ client.py            # Async HTTP client (httpx) + SSH client (asyncssh)
ā”œā”€ā”€ server.py            # MCP server with 33 tools, stdio + SSE transport, partial startup
ā”œā”€ā”€ rest_bridge.py       # Optional REST bridge for smoke/e2e testing (on MCP_REST_PORT)
└── tools/
    ā”œā”€ā”€ __init__.py
    ā”œā”€ā”€ constants.py     # SSOT defaults, tool manifests, validation limits, write guard
    ā”œā”€ā”€ response.py      # _success_response / _error_response helpers
    ā”œā”€ā”€ capabilities.py  # describe_mikrus_capabilities introspection tool (L3+)
    ā”œā”€ā”€ mikrus_api.py    # 12 mikr.us API tools + internal functions + registration
    ā”œā”€ā”€ system.py        # 14 system management tools (exec, file, service, disk, etc.)
    ā”œā”€ā”€ container_journal.py  # 6 Docker + journalctl tools + registration
    └── discovery.py     # Server listing tool + registration

tests/
ā”œā”€ā”€ conftest.py              # Root: environment loading
ā”œā”€ā”€ fixtures.py              # Mock data constants
ā”œā”€ā”€ _env_loader.py           # Shared .env loader for conftest files
│
ā”œā”€ā”€ unit/                    # Unit tests — zero I/O, fully mocked
│   ā”œā”€ā”€ conftest.py
│   ā”œā”€ā”€ test_client.py
│   ā”œā”€ā”€ test_config.py
│   ā”œā”€ā”€ test_server_tools.py
│   ā”œā”€ā”€ test_ssh_client.py
│   ā”œā”€ā”€ test_multi_server.py
│   ā”œā”€ā”€ test_rest_bridge.py
│   ā”œā”€ā”€ test_sanitizer.py
│   ā”œā”€ā”€ test_tool_registration.py
│   ā”œā”€ā”€ test_capabilities.py
│   └── test_validators.py
│
ā”œā”€ā”€ smoke/                   # Smoke tests — direct API calls (skipif no creds)
│   ā”œā”€ā”€ conftest.py
│   ā”œā”€ā”€ test_connectivity.py
│   ā”œā”€ā”€ test_critical_tools.py
│   └── test_response_format.py
│
ā”œā”€ā”€ integration/             # Integration tests — real API calls
│   ā”œā”€ā”€ conftest.py
│   ā”œā”€ā”€ mcp_wrapper.py
│   └── test_real_tools.py
│
└── e2e/                     # E2E tests — full pipeline workflows
    ā”œā”€ā”€ conftest.py
    └── test_server_api.py

Notes

  • 33 tools total: 2 discovery + 12 mikr.us API + 19 system management tools.
  • All tools return {"success": True/False, ...} JSON format for consistent error handling.
  • All write operations are protected by input validation — no shell injection possible.
  • Errors are logged to stderr, in compliance with the MCP specification.
  • The mikr.us /exec endpoint has a 65-second client timeout (API limit is 60s).
  • /stats, /info, /serwery, /db, and /porty have a 60-second API-side cache.
  • Tool descriptions are optimized for LLM agents — each explains when and why to use the tool.