Skip to main content
Glama

olvm-mcp

tests

An MCP server for Oracle Linux Virtualization Manager (OLVM) and oVirt. It lets AI assistants such as Claude read your virtualization inventory through the engine's REST API.

Tested against OLVM 4.5.5. This is Phase 1: read-only.

Tools

Tool

What it returns

list_vms(search, max_results)

VMs with status, cluster, host, CPUs, memory, OS

get_vm(name_or_id)

One VM in detail, including disks and network interfaces

list_hosts(search, max_results)

KVM hosts with status, cluster, CPU, memory, running VMs, OS and VDSM version

search accepts the engine's search syntax, for example status=up, name=web* or cluster=Default and status=down.

Every tool is marked read-only (readOnlyHint), and results are capped at 200 items.

Related MCP server: Proxmox MCP Server

How it works

  • Logs in through the engine's SSO token endpoint (/ovirt-engine/sso/oauth/token, scope ovirt-app-api). The official oVirt SDK uses the same flow, so Keycloak and older logins both work.

  • Calls the REST API v4 in JSON over HTTPS with httpx. The official ovirt-engine-sdk-python isn't used because it has no Windows build.

  • Verifies TLS with the engine's CA certificate.

  • Refreshes the token automatically when it expires.

Requirements

  • Python 3.12+ and uv

  • Network access to the engine on port 443 (directly, or through an SSH tunnel)

  • An engine user with a read-only role. Don't use admin.

Setup

1. Create a read-only engine user

For Keycloak installs (the default on OLVM 4.5):

  1. In the Keycloak admin console (https://<engine>/ovirt-engine-auth/admin/, realm ovirt-internal), add a user named mcp-reader@ovirt. Set a password with Temporary turned off.

  2. In the Administration Portal, go to Administration → Users → Add and add the user (provider internalkeycloak-authz).

  3. Go to Administration → Configure → System Permissions → Add and assign ReadOnlyAdmin.

The API username is then mcp-reader@ovirt@internalsso.

2. Get the engine's CA certificate

curl -k -o olvm-ca.pem "https://<engine-fqdn>/ovirt-engine/services/pki-resource?resource=ca-certificate&format=X509-PEM-CA"

3. Install and test

uv sync
uv run pytest

Then run the smoke test against your engine. It prompts for the password:

# PowerShell
$env:OLVM_URL = "https://<engine-fqdn>/ovirt-engine"
$env:OLVM_USERNAME = "mcp-reader@ovirt@internalsso"
$env:OLVM_CA_FILE = "C:\path\to\olvm-ca.pem"
uv run python scripts/smoke_test.py vm-test

Configuration

Variable

Required

Description

OLVM_URL

yes

Engine base URL, e.g. https://engine.example.com/ovirt-engine (/api optional)

OLVM_USERNAME

yes

e.g. mcp-reader@ovirt@internalsso (Keycloak) or user@internal

OLVM_PASSWORD_FILE

one of

File containing only the password (recommended)

OLVM_PASSWORD

one of

The password itself

OLVM_CA_FILE

recommended

Engine CA certificate (PEM). Without it, the system trust store is used

OLVM_TIMEOUT

no

Seconds per request (default 30)

OLVM_INSECURE

no

true disables TLS verification. Lab use only

See .env.example.

Connect an MCP client

Claude Desktop

Edit %APPDATA%\Claude\claude_desktop_config.json (Windows) or ~/Library/Application Support/Claude/claude_desktop_config.json (macOS):

{
  "mcpServers": {
    "olvm": {
      "command": "uv",
      "args": ["--directory", "C:\\path\\to\\olvm-mcp-server-repo", "run", "olvm-mcp"],
      "env": {
        "OLVM_URL": "https://<engine-fqdn>/ovirt-engine",
        "OLVM_USERNAME": "mcp-reader@ovirt@internalsso",
        "OLVM_PASSWORD_FILE": "C:\\path\\to\\mcp-reader.pw",
        "OLVM_CA_FILE": "C:\\path\\to\\olvm-ca.pem"
      }
    }
  }
}

Restart Claude Desktop, then ask, for example: "Which VMs are running, and on which hosts?"

Claude Code

claude mcp add olvm -e OLVM_URL=https://<engine-fqdn>/ovirt-engine -e OLVM_USERNAME=mcp-reader@ovirt@internalsso -e OLVM_PASSWORD_FILE=/path/to/mcp-reader.pw -e OLVM_CA_FILE=/path/to/olvm-ca.pem -- uv --directory /path/to/olvm-mcp-server-repo run olvm-mcp

Engine reachable only through SSH

Tunnel port 443 and map the engine's FQDN to 127.0.0.1 in your hosts file. The engine's login only works with the FQDN given to engine-setup:

ssh -i <key> -L 443:localhost:443 opc@<engine-public-ip>

Troubleshooting

Error

Cause

Login to the engine failed

Wrong username format or password, or the password is still marked Temporary in Keycloak

HTML error page ... no permissions

The user has no role in OLVM. Assign ReadOnlyAdmin (system-wide)

CERTIFICATE_VERIFY_FAILED

Set OLVM_CA_FILE to the engine's CA certificate

Cannot reach the engine

Network, tunnel or hosts-file problem. Check https://<fqdn>/ovirt-engine/services/health in a browser

Development

src/olvm_mcp/
  config.py      settings from environment variables
  client.py      REST client: SSO login, token refresh, errors
  formatting.py  compact summaries of engine JSON
  server.py      MCP server and tools
tests/           unit tests against a mocked engine (respx)
scripts/         smoke test against a real engine

Logs go to stderr, because stdout carries the MCP protocol.

Roadmap

  • Phase 2: operator actions (start/stop, snapshots, migration, host maintenance) with dry-run, confirmation and an audit log

  • Phase 3: Streamable HTTP transport with authentication, for remote clients

  • Phase 4: agents built on top (triage, capacity reports, provisioning)

License

Apache License 2.0

Available Tools

3 tools
get_vmA
Read-onlyIdempotent

Get details of one virtual machine, including its disks and network interfaces.

Args:
    name_or_id: The VM's exact name, or its UUID.
ParametersJSON Schema
NameRequiredDescriptionDefault
name_or_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false, and openWorldHint=false, so the safety profile is covered. The description adds only what the payload contains (disks, NICs), not error behavior for a missing name/UUID or lookup semantics.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded single-line purpose followed by a short Args block; both sentences earn their place. The Args heading is minor formatting noise but the content is substantive.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

A single required parameter with a clear description, plus an output schema that handles return values. Nothing critical is missing for correct invocation, though error behavior on an unresolved name/UUID is left unstated.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% and the schema offers only a bare 'Name Or Id' title, so the description carries the burden and does so usefully by specifying 'exact name, or its UUID'. It doesn't clarify case sensitivity or ambiguity handling, but it clearly adds meaning beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Get details of one virtual machine') and enumerates the notable return content (disks, network interfaces). The word 'one' implicitly separates it from list_vms, but it never names the sibling explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied rather than stated: the agent can infer this is the single-VM lookup versus the list_vms sibling. There is no explicit when-to-use, no exclusion, and no mention of alternatives or prerequisites.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_hostsA
Read-onlyIdempotent

List KVM hosts with their status, cluster, CPU, memory and running VM count.

Args:
    search: Optional oVirt search query, for example `status=up`,
        `cluster=Default`, or `name=kvm*`. Leave empty to list all hosts.
    max_results: Maximum number of hosts to return (1-200, default 50).
ParametersJSON Schema
NameRequiredDescriptionDefault
searchNo
max_resultsNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint=false, so the safety profile is fully covered by structured data. The description adds nothing behavioral beyond that (no auth requirements, no pagination/truncation behavior when more hosts match), so it merely matches the annotation baseline.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded one-line summary followed by a scoped Args list; no filler sentences. The format is slightly verbose in listing parameters that are also present in the schema, but each line adds meaning the schema lacks.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be re-explained, and both parameters are covered. Annotations handle the safety profile. Only minor gaps remain, such as what happens when results exceed max_results or exceed the 200 ceiling.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description carries the full load and does so reasonably well: it gives the search query syntax with three examples, states that an empty value lists everything, and documents the 1-200 range and default 50 for max_results. Only missing detail is the exact search field grammar beyond the examples.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('List') and resource ('KVM hosts') and even enumerates the fields returned (status, cluster, CPU, memory, running VM count). Siblings list_vms and get_vm operate on a clearly different resource, so the agent can route without ambiguity, though the description never names them explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The Args block explains how to use `search` (with three concrete query examples and 'leave empty to list all hosts'), which is real usage guidance for the parameter. However, there is no when-to-use/when-not guidance relative to list_vms or any other tool, so context is only implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_vmsA
Read-onlyIdempotent

List virtual machines with their status, cluster, host, CPUs and memory.

Args:
    search: Optional oVirt search query, for example `status=up`,
        `name=web*`, `cluster=Default and status=down`, or `host=kvm01`.
        Leave empty to list all VMs.
    max_results: Maximum number of VMs to return (1-200, default 50).
ParametersJSON Schema
NameRequiredDescriptionDefault
searchNo
max_resultsNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, and non-destructive behavior, so the bar is lower. The description still adds real value beyond them by disclosing the result bound (1-200) and default (50), which the schema does not express as a range constraint.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The core purpose is front-loaded in a single sentence, with parameters organized under a clear 'Args:' block. The four search examples are slightly more than needed, but each demonstrates a distinct query form so they largely earn their place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-parameter read-only listing tool with an output schema covering return values, the description is nearly complete: purpose, both parameters, and result limits are all addressed. Only error handling and ordering conventions are left unstated.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description carries the full load and does so well: it defines the search parameter's syntax with multiple domain-specific examples and gives the max_results range and default. It stops short of describing invalid-query behavior or result ordering.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('List virtual machines') and enumerates the returned attributes (status, cluster, host, CPUs, memory). The plural list framing clearly separates it from the singular get_vm sibling.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives concrete when-to-use guidance through four example search queries and explicitly states 'Leave empty to list all VMs.' It does not, however, name alternatives such as get_vm for single-VM lookups or explain when listing is preferable to a targeted fetch.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 3 tool updatesv0.1.0
    • First observedget_vm
    • First observedlist_hosts
    • First observedlist_vms

TDQS

A3.7/5.0

Scored across 3 tools

Disambiguation5/5

Each tool has a clearly distinct purpose: list_vms and list_hosts enumerate different resources, and get_vm provides single-VM detail. There is no overlap or ambiguity between them.

Naming Consistency5/5

All three tools follow a consistent verb_noun pattern (list_vms, get_vm, list_hosts), with plural nouns for list operations and singular for the detail operation, which is idiomatic and predictable.

Tool Count3/5

Three tools is borderline thin for an oVirt virtualization server; it covers only basic VM and host inventory, leaving little room for the broader management surface the domain implies. A read-only inventory intent could justify this, but it feels underpowered.

Completeness2/5

The surface only supports listing VMs, getting one VM, and listing hosts. It lacks VM lifecycle actions (start/stop/reboot), host detail or operations, cluster and storage domain queries, and create/update/delete operations, which are significant gaps for an oVirt management server.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    D
    maintenance
    Enables read-only interaction with Proxmox homelab VMs and containers, allowing LLM agents to list VMs, monitor status and performance metrics, view snapshots, and check cluster health through natural language queries.
    8
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables management of oVirt / Red Hat Virtualization environments via AI assistants, supporting VM lifecycle, power operations, snapshots, and infrastructure queries.
    -