Command Palette

Search for a command to run...

UnylyUnyly
Browse all

DevOps

FreeNot checked

A production-ready MCP (Model Context Protocol) server that serves an internal DevOps knowledge base — skills, instructions, prompts, and policies for Python, A

GitHubEmbed

About

A production-ready MCP (Model Context Protocol) server that serves an internal DevOps knowledge base — skills, instructions, prompts, and policies for Python, Ansible, Terraform, Docker, Kubernetes, and CI/CD — to AI assistants over Streamable HTTP.

README

A production-ready Model Context Protocol (MCP) server that serves DevOps knowledge base — skills, instructions, prompts, and policies for Python, Ansible, Terraform, Docker, Kubernetes, CI/CD, and general engineering — to any MCP-compatible AI client (Claude Desktop, VS Code, Cursor, ...).


1. Overview

The server reads versioned Markdown files (with YAML frontmatter) from content/ and exposes them to AI assistants via 4 MCP tools over a Streamable HTTP transport, deployed as a Docker container.

Why MCP? It gives AI assistants a controlled, auditable, read-only window into your DevOps standards so generated code, pipelines, and infra always align with internal policy — without copy-pasting documentation into prompts.


2. Architecture

┌─────────────────────┐      HTTPS / X-API-Key       ┌─────────────────────────────┐
│  MCP Client         │ ───────────────────────────▶ │  Starlette ASGI app          │
│  (Claude / VS Code) │                              │  ├─ /health                  │
└─────────────────────┘                              │  └─ /mcp (FastMCP mount)     │
                                                     │     APIKeyMiddleware         │
                                                     └──────────────┬───────────────┘
                                                             │
                                                             ▼
                                              ┌─────────────────────────────┐
                                              │  mcp_server.tools (FastMCP)  │
                                              │    @tool fetch_devops_content│
                                              │    @tool list_devops_*       │
                                              │    @tool get_devops_*_by_id  │
                                              └──────────────┬───────────────┘
                                                             │
                                                             ▼
                                              ┌─────────────────────────────┐
                                              │  src/services                │
                                              │   └─ ContentService          │
                                              │       ├─ ContentLoader (fs)  │
                                              │       └─ ContentFilter       │
                                              └──────────────┬───────────────┘
                                                             │
                                                             ▼
                                                 ┌────────────────────────┐
                                                 │  content/*.md          │
                                                 │  (frontmatter + body)  │
                                                 └────────────────────────┘

3. Prerequisites

  • Python 3.11+
  • Poetry 1.7+ (or pip)
  • Docker Engine 24+ and Docker Compose v2 (for containerized deployment)
  • An API key value of your choosing (any non-empty string) for MCP_API_KEY

4. Local Setup

# 1. Clone
git clone <repo-url> hbiz-devops-mcp
cd hbiz-devops-mcp

# 2. Environment
cp .env.example .env
# Edit .env — at minimum set MCP_API_KEY to a non-empty secret

# 3. Install dependencies
poetry install
# OR
python -m venv .venv && source .venv/bin/activate     # Windows: .venv\Scripts\activate
pip install -r requirements.txt

# 4. Run
poetry run python main.py
# OR
python main.py

The server listens on http://localhost:8000 by default.

  • Health: GET http://localhost:8000/health
  • MCP: POST http://localhost:8000/mcp (with X-API-Key: <your-key>)

5. Docker

cp .env.example .env
# Edit .env — set MCP_API_KEY and adjust MCP_PORT as needed

# Build the image
docker build -t hbiz-devops-mcp:latest .

# Start the container
docker compose up -d

# Verify
curl http://localhost:8001/health
# {"status":"healthy","server":"hBiz-DevOps MCP Server","version":"1.0.0"}

# View live logs
docker logs hbiz-devops-mcp -f

The server is exposed on the port defined by MCP_PORT (default 8001); the MCP endpoint is http://localhost:8001/mcp.

Stop:

docker compose down

6. VS Code MCP Configuration

Create .vscode/mcp.json in any consumer workspace (this file is committed on purpose — it contains no secrets, only the server URL):

{
  "servers": {
    "hbiz-devops": {
      "type": "http",
      "url": "http://localhost:8000/mcp",
      "headers": {
        "X-API-Key": "${env:HBIZ_MCP_API_KEY}"
      }
    }
  }
}

Then export the key in your shell (or VS Code user env):

export HBIZ_MCP_API_KEY="<your-key>"

For a production deployment, replace http://localhost:8000/mcp with https://<your-host>/mcp.


7. Environment Variables

Server

Variable Default Description
DOCKER_IMAGE hbiz-devops-mcp:latest Docker image name used in docker-compose.yml
ENVIRONMENT local local / staging / production
MCP_API_KEY (required) API key clients must send as X-API-Key
MCP_SERVER_NAME hBiz-DevOps MCP Server Display name surfaced to MCP clients
MCP_HOST 0.0.0.0 Bind address
MCP_PORT 8000 Bind port (exposed on host)
CONTENT_DIR content Path (relative or absolute) to content root

Logging

Variable Default Description
LOG_LEVEL INFO DEBUG / INFO / WARNING / ERROR
LOG_FORMAT %(asctime)s - %(name)s - %(levelname)s - %(message)s Python logging format string
LOG_FILE_ENABLED false Set true to also write logs to a file
LOG_FILE_PATH logs/mcp_logs.log Path to the log file (created automatically)
LOG_FILE_MAX_BYTES 10485760 Max file size before rotation (default 10 MB)
LOG_FILE_BACKUP_COUNT 5 Number of rotated backup files to keep

All variables can be overridden via .env or process environment.


8. MCP Tools

Tool Args Returns
fetch_devops_content query: str, content_type?: str, tags?: list[str] Matching items rendered as markdown
list_devops_categories (none) Sorted list of categories
list_devops_content category?: str, content_type?: str Markdown table of metadata
get_devops_content_by_id content_id: str Single item rendered as markdown

All tools are read-only (readOnlyHint: true, destructiveHint: false).


9. Adding New Content

  1. Create a Markdown file under content/<category>/<type>/<id>.md where:

    • <category>python | ansible | terraform | docker | kubernetes | cicd | general
    • <type>skills | instructions | prompts | policies | rules
  2. Add the required frontmatter:

    ---
    id: kebab-case-unique-id
    title: Human-Readable Title
    type: skill        # skill | instruction | prompt | policy | rule
    category: python   # must match the folder name
    tags:
      - python         # first tag should be the category
      - clean-arch
    version: "1.0"     # quoted string
    ---
    
    # Title
    
    Body markdown here...
    
  3. Restart the server (content is loaded once at startup).

id values must be globally unique across the whole tree — duplicates will fail loading with ContentLoadError.


10. Project Structure

hbiz-devops-mcp/
├── main.py                      # Uvicorn entry point
├── pyproject.toml               # Poetry deps
├── requirements.txt             # pip-installable mirror
├── Dockerfile
├── .dockerignore
├── docker-compose.yml
├── .env.example                 # Template — copy to .env
├── config/
│   └── settings.py              # Pydantic settings
├── src/
│   ├── core/
│   │   ├── content_loader.py    # Filesystem → ContentItem[]
│   │   ├── content_filter.py    # Pure filtering logic
│   │   └── exceptions.py
│   ├── models/
│   │   └── content.py           # ContentMeta, ContentItem, ContentType
│   ├── services/
│   │   └── content_service.py   # Caches + exposes content
│   └── utils/
│       ├── auth.py              # APIKeyMiddleware
│       └── logger.py            # stdout + optional rotating file handler
├── mcp_server/
│   ├── app.py                   # Starlette + FastMCP wiring
│   └── tools.py                 # @mcp.tool definitions
├── content/                     # The DevOps knowledge base
│   ├── python/ ansible/ terraform/ docker/ kubernetes/ cicd/ general/
├── logs/                        # Created at runtime (gitignored)
│   └── mcp_logs.log             # Only present when LOG_FILE_ENABLED=true
└── tests/
    ├── conftest.py
    ├── core/
    └── services/

11. Dependency Management

  • Source of truth: pyproject.toml (Poetry).

  • requirements.txt is regenerated for environments without Poetry:

    poetry export -f requirements.txt -o requirements.txt --without-hashes
    
  • Pin major + minor (^1.0). Update via poetry update and run the full test suite before committing the new lockfile.

  • Security: poetry run pip-audit (or safety check) on every PR.


12. Logging

By default logs are written to stdout only and are visible via:

# Local run
python main.py

# Docker
docker logs hbiz-devops-mcp
docker logs hbiz-devops-mcp -f     # follow/live

Enable file logging

Set the following in .env and restart the server:

LOG_FILE_ENABLED=true
LOG_FILE_PATH=logs/mcp_logs.log
LOG_FILE_MAX_BYTES=10485760     # 10 MB per file
LOG_FILE_BACKUP_COUNT=5         # keep last 5 rotated files

The logs/ directory is created automatically. Files rotate once they reach LOG_FILE_MAX_BYTES and up to LOG_FILE_BACKUP_COUNT backups are retained (mcp_logs.log, mcp_logs.log.1, … mcp_logs.log.5). Both stdout and file logging are active simultaneously when file logging is enabled.

logs/ is gitignored — log files are never committed to source control.


13. Testing with Postman

The MCP server speaks JSON-RPC 2.0 over HTTP POST. Every request goes to http://localhost:8001/mcp with the X-API-Key header set.

Required headers (all requests)

Header Value
Content-Type application/json
Accept application/json, text/event-stream
X-API-Key your MCP_API_KEY value

Step 1 — Verify the server is up

GET http://localhost:8001/health

Expected response:

{"status": "healthy", "server": "hBiz-DevOps MCP Server", "version": "1.0.0"}

Step 2 — Initialize the MCP session

POST http://localhost:8001/mcp

Body:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {
    "protocolVersion": "2024-11-05",
    "capabilities": {},
    "clientInfo": { "name": "postman", "version": "1.0" }
  }
}

Copy the mcp-session-id value from the response headers — you must include it as mcp-session-id: <value> in all subsequent requests.


Step 3 — List available tools

POST http://localhost:8001/mcp
Add header: mcp-session-id: <value from step 2>

Body:

{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/list",
  "params": {}
}

Step 4 — Call a tool

List all categories

{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "list_devops_categories",
    "arguments": {}
  }
}

Search content

{
  "jsonrpc": "2.0",
  "id": 4,
  "method": "tools/call",
  "params": {
    "name": "fetch_devops_content",
    "arguments": {
      "query": "docker",
      "content_type": "skill"
    }
  }
}

List content by category

{
  "jsonrpc": "2.0",
  "id": 5,
  "method": "tools/call",
  "params": {
    "name": "list_devops_content",
    "arguments": {
      "category": "python"
    }
  }
}

Fetch a specific item by ID

{
  "jsonrpc": "2.0",
  "id": 6,
  "method": "tools/call",
  "params": {
    "name": "get_devops_content_by_id",
    "arguments": {
      "content_id": "python-clean-architecture"
    }
  }
}

Step 5 — Verify auth rejection

Send any request without the X-API-Key header (or with a wrong value). Expected response: HTTP 401

{"detail": "Unauthorized"}

14. Unit Tests

# Run all tests
poetry run pytest -v

# With coverage
poetry run pytest --cov=src --cov-report=term-missing

# A single file
poetry run pytest tests/core/test_content_loader.py -v

Tests use sample markdown fixtures created in tmp_path — they do not read the production content/ tree.

from github.com/IranUdesha/DevOps-MCP-Server

Installing DevOps

This server has no published package — it is built from source. Open the repository and follow its README.

▸ github.com/IranUdesha/DevOps-MCP-Server

FAQ

Is DevOps MCP free?

Yes, DevOps MCP is free — one-click install via Unyly at no cost.

Does DevOps need an API key?

No, DevOps runs without API keys or environment variables.

Is DevOps hosted or self-hosted?

Self-hosted: the server runs locally on your machine via the install command above.

How do I install DevOps in Claude Desktop, Claude Code or Cursor?

Open DevOps on unyly.org, pick your client tab (Claude Desktop, Claude Code, Cursor) and press Install — the config is generated automatically, no JSON editing.

Related MCPs

Compare DevOps with

Not sure what to pick?

Find your stack in 60 seconds

Author?

Embed badge for your README

Browse similar

All development MCPs