Back to Browse

OpenITCOCKPIT MCP Server

Developer ToolsModerate5.2MCP RegistryLocal
Free

Server data from the Official MCP Registry

openITCOCKPIT monitoring: host and service state, history, downtimes, acknowledgements, patches

About

openITCOCKPIT monitoring: host and service state, history, downtimes, acknowledgements, patches

Security Report

5.2
Moderate5.2Moderate Risk

This is a well-structured MCP server for openITCOCKPIT monitoring with strong security fundamentals. Authentication is properly implemented with bearer tokens and constant-time comparison, credentials are managed securely through environment variables, and write operations are gated behind a feature flag. Minor code quality issues exist around broad exception handling and incomplete input validation, but these do not represent security vulnerabilities. Supply chain analysis found 8 known vulnerabilities in dependencies (0 critical, 4 high severity).

6 files analyzed · 11 issues found

Security scores are indicators to help you make informed decisions, not guarantees. Always review permissions before connecting any MCP server.

Permissions Required

This plugin requests these system permissions. Most are normal for its category.

HTTP Network Access

Connects to external APIs or services over the internet.

env_vars

Check that this permission is expected for this type of plugin.

File System Read

Reads files on your machine. Normal for tools that analyze or process local data.

What You'll Need

Set these up before or after installing:

API key of a dedicated, least-privilege openITCOCKPIT user. This server presents it to openITCOCKPIT; it is never handed to a client.Required

Environment variable: OITC_APIKEY

Base URL of the openITCOCKPIT instance, e.g. https://openitcockpit.example.org - without a path.Optional

Environment variable: OITC_BASEURL

Transport mode. The image defaults to 'http', which additionally requires MCP_AUTH_TOKEN and a published port; a client that runs this container itself wants 'stdio'.Optional

Environment variable: OITC_TRANSPORT

Register the 15 tools that change the monitoring configuration. Off by default: they are not even registered unless this is 'true'.Optional

Environment variable: OITC_ENABLE_WRITE_TOOLS

Verify the openITCOCKPIT TLS certificate. On by default; for a self-signed instance set OITC_CA_BUNDLE rather than turning this off.Optional

Environment variable: OITC_VERIFY_TLS

How to Install

Add this to your MCP configuration file:

{
  "mcpServers": {
    "io-github-openitcockpit-mcp-server": {
      "env": {
        "OITC_APIKEY": "your-oitc-apikey-here",
        "OITC_BASEURL": "your-oitc-baseurl-here",
        "OITC_TRANSPORT": "your-oitc-transport-here",
        "OITC_VERIFY_TLS": "your-oitc-verify-tls-here",
        "OITC_ENABLE_WRITE_TOOLS": "your-oitc-enable-write-tools-here"
      },
      "args": [
        "openitcockpit-mcp-server"
      ],
      "command": "uvx"
    }
  }
}

Documentation

View on GitHub

From the project's GitHub README.

openITCOCKPIT MCP Server

An MCP server that exposes an openITCOCKPIT monitoring instance to an LLM client: host and service status, log entries, downtimes, acknowledgements, check history, software inventory and pending updates - plus optional, off-by-default tools that change the monitoring configuration.

  • Requires openITCOCKPIT 5.6 or newer. See Compatibility.
  • 39 tools, 24 read-only and 15 write.
  • Write tools are disabled by default and are not even registered until you enable them.
  • Names, never IDs. Every tool takes hostnames, template names and container paths; the server resolves them itself.
  • Scope-checked writes. References are validated against the target container before anything is sent, which openITCOCKPIT's own API does not do.

Quickstart

cp .env.example .env          # fill in the two secrets, see Configuration
docker compose up --build

Then point your client at http://localhost:8000/mcp with the bearer token from your .env. Compose reads that same file for the published port, so setting OITC_PORT there moves both sides at once.


Configuration

The server needs two separate secrets and refuses to start if they are the same value:

SecretWho presents it to whom
MCP_AUTH_TOKENClients → this server. A random token you generate.
OITC_APIKEYThis server → openITCOCKPIT. The API key of a dedicated, least-privilege openITCOCKPIT user.
python -c "import secrets; print(secrets.token_urlsafe(32))"   # generate MCP_AUTH_TOKEN

Copy .env.example to .env and fill it in. Precedence, highest first: CLI flags → environment variables → .env → defaults. .env is gitignored and must never be committed.

SettingEnv varDefault
Client bearer tokenMCP_AUTH_TOKEN(required for http)
openITCOCKPIT API keyOITC_APIKEY(required)
openITCOCKPIT base URLOITC_BASEURL(required)
Verify the instance's TLS certificateOITC_VERIFY_TLStrue
CA bundle for a self-signed instanceOITC_CA_BUNDLE(unset)
Request timeout, secondsOITC_TIMEOUT_SECONDS20
Register the write toolsOITC_ENABLE_WRITE_TOOLSfalse
Cache scope-validation lookupsOITC_SCOPE_CACHE_ENABLEDtrue
Scope cache TTL, secondsOITC_SCOPE_CACHE_TTL_SECONDS30
Summarise the text half of a resultOITC_COMPACT_CONTENTfalse
Transport, http or stdioOITC_TRANSPORThttp
Bind address / port (http)OITC_HOST / OITC_PORT0.0.0.0 / 8000
Log levelOITC_LOG_LEVELINFO
Print the start-up bannerOITC_SHOW_BANNERtrue

Connecting a client

HTTP (server runs as a service)

Clients send Authorization: Bearer <MCP_AUTH_TOKEN>. The comparison is constant-time; a missing, malformed or wrong token gets HTTP 401.

{
  "url": "http://your-mcp-server:8000/mcp",
  "headers": { "Authorization": "Bearer your-mcp-auth-token" }
}

stdio (client spawns the server)

No HTTP layer, so no MCP_AUTH_TOKEN is needed. Two ways to spawn it.

From the image, which needs nothing installed but Docker. This is what the MCP Registry entry describes, and the form to hand to someone who just wants to connect a desktop client:

{
  "command": "docker",
  "args": [
    "run", "-i", "--rm",
    "-e", "OITC_TRANSPORT=stdio",
    "-e", "OITC_APIKEY",
    "-e", "OITC_BASEURL",
    "openitcockpit/mcp-server:0.3.0"
  ],
  "env": {
    "OITC_APIKEY": "your-openitcockpit-api-key",
    "OITC_BASEURL": "https://openitcockpit.example.org"
  }
}

The -e NAME flags carry no value: Docker takes it from the environment the client provides, so neither secret ends up in the process list.

From an install, once pip install . has put oitc-mcp on the path:

{
  "command": "oitc-mcp",
  "args": ["--transport", "stdio"],
  "env": {
    "OITC_APIKEY": "your-openitcockpit-api-key",
    "OITC_BASEURL": "https://openitcockpit.example.org"
  }
}

[!NOTE] Either way the server runs on the client's machine and holds the openITCOCKPIT API key there. The http transport keeps that key on one host you operate and gives clients a bearer token instead - prefer it when more than one person connects.


Installation

Docker

docker run -d -p 8000:8000 --env-file .env openitcockpit/mcp-server:0.3.0

Which tag? The tag is this server's own version. 0.3.0 never changes, so a redeploy gives you exactly what you tested - pin that. latest is the only other tag and it moves under you. The tag says nothing about your openITCOCKPIT version; one image serves 5.6 and newer. See Versioning.

Or with individual variables, for CI or a secret manager:

docker run -d -p 8000:8000 \
  -e MCP_AUTH_TOKEN="..." \
  -e OITC_APIKEY="..." \
  -e OITC_BASEURL="https://openitcockpit.example.org" \
  openitcockpit/mcp-server:0.3.0

No secret is baked into the image; configuration is read from the environment at start-up.

Or with Compose. docker-compose.example.yml is a complete deployment of the published image - restart policy, health check, and every setting inline in two blocks, required and optional. Copy it, fill in the three required values, and:

docker compose -f docker-compose.example.yml up -d

The docker-compose.yml next to it is a different thing: it builds from this repository and reads .env, which is what Quickstart uses.

From source

pip install .
cp .env.example .env
oitc-mcp

oitc-mcp --help lists the flags that override the configuration (--transport, --host, --port, --log-level).

MCP Registry

server.json in the repo root is this server's entry for the MCP Registry, published with mcp-publisher publish. The registry name is io.github.openITCOCKPIT/mcp-server, and the Dockerfile carries the same string as an io.modelcontextprotocol.server.name label - the registry reads it off the published image as its only ownership proof for an OCI package, and compares it case-sensitively.

Three values have to agree at release time: MCP_VERSION, the version in server.json, and the image tag in its package identifier. tests/test_server_json.py fails when they do not.


Tools

39 tools, 24 read-only and 15 write. Full signatures and behaviour: read tools · write tools.

Every tool carries MCP annotations, so a client can tell a read from a write before calling it, and takes names rather than database IDs - the server resolves them itself.

A few things you can ask for, and what answers them:

AskTools
"What is broken right now?"list_services_by_state, list_log_entries
"Do we already know about db-01?"get_host_info, list_host_acknowledgements, list_host_downtimes
"Why did web-03 flap last night?"list_host_state_changes, list_host_checks
"Which hosts need security patches?"list_pending_security_updates
"Is the monitoring itself keeping up?"get_monitoring_engine_stats
"Which templates could web-05 use?"get_allowed_elements_for_container
"Add web-05 with the Linux template"create_host

Write tools are registered only when OITC_ENABLE_WRITE_TOOLS=true. They change your monitoring configuration.

docs/openitcockpit-api-notes.md documents the API behaviour this server works around - which endpoints omit newly created objects, the two names a service template carries, and the response shapes.


Toolsets

An instance can be limited to a named subset of the tools, so an agent sees only what its job needs. Fewer candidates mean fewer wrong calls - and a tool that was never registered cannot be called at all, which makes this a boundary rather than a hint.

OITC_TOOLSETS=triage                      # one set
OITC_TOOLSETS=triage,patch                # several
OITC_TOOLSETS=triage,get_container_tree   # a set plus one more tool
OITC_TOOLSETS=all                         # everything - the default

Write tools stay out of all of these unless OITC_ENABLE_WRITE_TOOLS=true, so all on its own is the read-only surface. There is no keyword for that and no blank value: all plus the write gate already says everything there is to say.

SetFor
triageWhat is broken, since when, whether it is handled, whether monitoring itself is at fault
patchUpdate and security posture across the estate
catalogLook up what exists, without changing anything
onboardingTake a host and its services into monitoring
configChange existing objects without blanking fields
provisioningCreate the building blocks hosts and services are made of

What a set serves alongside its tools is named in the same file, and nothing about it is hardcoded:

[wachdienst]
tools         = ["list_services_by_state", "get_host_info"]
skills        = ["oitc-incident-triage", "./meine-anleitung.md"]
systemprompts = ["./prompts/wachdienst.md"]

An entry is either the name of something shipped with the server - see skills/ and systemprompts/ - or a path to a file of your own, relative to the toolsets file. So a set you invent can carry material you wrote. The two are listed apart because they are used differently: a skill is attached to a conversation, a system prompt belongs in the client's system field.

oitc-capabilities and the two general system prompts are served whatever the limit, so no set needs to name them. An unfiltered instance serves every skill and both general prompts, and none of the per-set supplements - it is not playing one of those roles.

oitc-mcp --list-toolsets prints each set with its tools, and names anything that belongs to no set. Selecting a set never widens what is available: the write tools stay unregistered without OITC_ENABLE_WRITE_TOOLS=true, whatever a set names.

Giving one agent several roles. One instance per set, differing in a single variable - the client spawns a process per entry anyway:

{
  "mcpServers": {
    "oitc-triage": { "command": "docker", "args": ["run","-i","--rm","-e","OITC_TOOLSETS=triage", "..."] },
    "oitc-config": { "command": "docker", "args": ["run","-i","--rm","-e","OITC_TOOLSETS=config","-e","OITC_ENABLE_WRITE_TOOLS=true", "..."] }
  }
}

Your own sets. The sets live in src/openitcockpit_mcp/toolsets.toml, not in code. Copy it next to where you start the server, or point OITC_TOOLSETS_FILE at it:

cp src/openitcockpit_mcp/toolsets.toml toolsets.toml

A file found that way replaces the sets rather than adding to them, and its description per set is what a client is told this instance is for - so your own wording reaches your own agents without living in this repository.

What an instance says about itself. The active sets and their descriptions are appended to the server instructions, and served as the resource oitc://skills/oitc-toolsets as well. The resource matters on the protocol revision from 2026-07-28: it has no initialize handshake, so it has no instructions either, and reading them back is how a client shows an operator what an instance is for. It also names which tools each set holds, which tools/list does not - that list is flat.

One instance per role. docker-compose.roles.yml runs four at once - triage, catalog, patch and a config instance that may write - each on its own port:

docker compose -f docker-compose.roles.yml up -d

Give each one its own openITCOCKPIT API key. That account's permissions are what every client of that instance acts with, so one key shared across all four gives every role the rights of the widest one.


Skills

src/openitcockpit_mcp/skills/ ships prompt material that teaches a model how to chain these tools, plus a system prompt for an openITCOCKPIT assistant. It lives inside the package because the server also serves it over MCP - see Resources and prompts.

SkillUse it for
systemprompts/en/general.mdBaseline assistant behaviour
systemprompts/de/general.mdThe same, in German
systemprompts/<lang>/<toolset>.mdOne per toolset: what that role does differently
oitc-incident-triage"What is broken?", in the order that rules things out
oitc-host-onboardingAdding a host and its services without scope rejections
oitc-patch-reviewSecurity and update overview across the estate
oitc-config-changeChanging an object without blanking fields
oitc-capabilitiesWhat the server cannot do, so a model does not invent it

The oitc-* folders follow the Agent Skills layout, so cp -r src/openitcockpit_mcp/skills/oitc-* ~/.claude/skills/ is enough for Claude Code and Claude Desktop; for other clients they are plain Markdown. See src/openitcockpit_mcp/skills/README.md.

Resources and prompts

The same files are served over MCP, so a client that cannot copy folders into a skills directory still gets them:

  • Resources at oitc://skills/<name>, one per file, text/markdown. The description a client shows is the SKILL.md frontmatter description.
  • Prompts named after the workflow, for the oitc-* skills only. The two system-prompt files are resources but not prompts: a prompt is inserted as a message, and a system prompt belongs in the client's system field.

oitc-host-onboarding and oitc-config-change describe write workflows and are registered only when OITC_ENABLE_WRITE_TOOLS=true, exactly as the write tools are - offering a sequence the server cannot run would be worse than not offering it.


Security

[!IMPORTANT] Every client that passes the bearer check acts with the permissions of the one openITCOCKPIT user the API key belongs to. There is no per-client identity. Create that key for a dedicated, least-privilege user and treat MCP_AUTH_TOKEN as a shared secret.

  • The http transport serves plain HTTP. Terminate TLS at a reverse proxy or keep the server on a trusted network.
  • MCP_AUTH_TOKEN must differ from OITC_APIKEY; the server enforces this so the openITCOCKPIT key is never handed to a client.
  • TLS verification against openITCOCKPIT is on by default. For a self-signed instance set OITC_CA_BUNDLE rather than disabling verification.
  • Authentication is a shared static token, not OAuth 2.1 - a deliberate tradeoff for a server that authenticates as a single service user. See src/openitcockpit_mcp/auth.py.

Versioning

The image tag is this server's version, from MCP_VERSION. Two tags per release, and no others:

Image tagMutable?Use for
0.3.0noPin this. Exactly this build.
latestyesThe newest release, whatever it is

Semver: patch for fixes, minor for added tools, major for anything that breaks a client. But this is still 0.x - the tool set is settling, so a minor bump may break one too. Pin the exact version and read the CHANGELOG before you move.

Compatibility

openITCOCKPIT 5.6 or newer - one image serves every supported release.

All 39 tools were exercised against live instances on the 5.6 line, and the openITCOCKPIT API is backwards compatible, so newer instances are expected to work. One caveat: list_installed_software, list_pending_updates and list_pending_security_updates need the openITCOCKPIT agent's package endpoints and fail with an API error where that feature is absent.


Development

python -m venv .venv && . .venv/bin/activate    # Windows: .venv\Scripts\activate
pip install -e ".[dev]"
./scripts/checks-docker.sh    # ruff, mypy and pytest, exactly as CI runs them

The script runs the suite inside the image the Dockerfile is based on, so a local run and a CI run use the same Python. Individually: ruff check ., mypy, pytest (206 tests).

Adding a tool: write it in the matching module under tools/read/ or tools/write/, decorate it with @mcp.tool(title=..., annotations=...) using a preset from tools/annotations.py, and the subpackage's register() picks it up - anything under tools/write/ is gated by OITC_ENABLE_WRITE_TOOLS automatically. A new module goes into that subpackage's READ_MODULES / WRITE_MODULES tuple, and a new tool into the call table in tests/test_tools_smoke.py, which runs every tool once against stubbed responses.

Build the image yourself with docker build -t oitc-mcp-server ..

Reviews

No reviews yet

Be the first to review this server!