openITCOCKPIT MCP Server
OfficialopenITCOCKPIT 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 --buildThen 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:
Secret | Who presents it to whom |
| Clients → this server. A random token you generate. |
| This server → openITCOCKPIT. The API key of a dedicated, least-privilege openITCOCKPIT user. |
python -c "import secrets; print(secrets.token_urlsafe(32))" # generate MCP_AUTH_TOKENCopy .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.
Setting | Env var | Default |
Client bearer token |
| (required for http) |
openITCOCKPIT API key |
| (required) |
openITCOCKPIT base URL |
| (required) |
Verify the instance's TLS certificate |
|
|
CA bundle for a self-signed instance |
| (unset) |
Request timeout, seconds |
|
|
Register the write tools |
|
|
Cache scope-validation lookups |
|
|
Scope cache TTL, seconds |
|
|
Summarise the text half of a result |
|
|
Transport, |
|
|
Bind address / port (http) |
|
|
Log level |
|
|
Print the start-up banner |
|
|
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.2.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"
}
}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.2.0Which tag? The tag is this server's own version. 0.2.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.2.0No 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 -dThe 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-mcpoitc-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:
Ask | Tools |
"What is broken right now?" |
|
"Do we already know about db-01?" |
|
"Why did web-03 flap last night?" |
|
"Which hosts need security patches?" |
|
"Is the monitoring itself keeping up?" |
|
"Which templates could web-05 use?" |
|
"Add web-05 with the Linux template" |
|
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.
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.
Skill | Use it for |
Baseline assistant behaviour | |
The same, in German | |
"What is broken?", in the order that rules things out | |
Adding a host and its services without scope rejections | |
Security and update overview across the estate | |
Changing an object without blanking fields | |
What 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 twosystem-promptfiles 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
Every client that passes the bearer check acts with the permissions of theone 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_TOKENmust differ fromOITC_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_BUNDLErather 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 tag | Mutable? | Use for |
| no | Pin this. Exactly this build. |
| yes | The 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 themThe 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 ..
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/openITCOCKPIT/openITCOCKPIT-MCP-Server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server