MCP-серверы для DevOps: што гэта і два, якія можна сабраць за тыдзень
MCP-серверы для DevOps: даюць Claude жывы доступ да Kubernetes, AWS і ранбукаў. Тры тыпы сервераў, MCP-сервер для Kubernetes толькі для чытання і тыповыя памылкі.
Крыніцы: What Is an MCP Server and Why Every DevOps Team Should Have One in 2026
MCP, тое ўзе Model Context Protocol, — гэта адкрыты стандарт ад Anthropic, які дазволяе мадэлям ШЫ наструктураваным спосабам з’яўляцца у зв’язку з зовнішнімі сістэмамі: інструментамі, API, базамі дадзенаў і сервісамі. Без яго Claude працюе ў самастоятэльнай „коробцы“, і кожны факт павінен быць внесены ручна. За дапамогою MCP Claude можа безпасерэдньа зв’язвацца з гэтымі сістэмамі.
„Сервер“ у MCP — гэта проста мала програма. Яна выкладзець інструменты і даныя для Claude, керуе взаімнымі запытамі і запускаецца там, дзе знаходзяцца даныя, будзь то ноутбук, кластэр чы сервер. Цэла не ўскладнена інфраструктура, і працюючы сервер MCP можа быць проста 50-радковым скрыптам на Python.
Аналагія, якая дапамагае
Інтэграцыя з Slack дапамагаець у лёгкай параболе. Раней касцьдзей выклікаў напіс «Праця ў рэжыме продакшн запусцена» вручную. Пасля інтэграцыі цяпер CI/CD-пайплайн выклікае гэты напіс аўтаматычна, а Slack стае цэнтрам, які ведае, што адбываецца. MCP рабіць гэта для Claude. Раней чалавек сам даваў інформацыю пра інфраструктуру, а пасля — працуючы праз прымытую налажанае з’яўленне, можа сам ствараць перакананні.
Чаму команды DevOps выграюць найбольш
Большасць прыкладаў вікорыстоўвання MCP назначаныя для распрацоўшчыкаў прыкладнікаў. DevOps-інжынеры, SRE-інжынеры і інжынеры платформы маюць большыя выгоды, таму што ўсё іх аддзялленне заключаецца у кераванні сістэмамі, якія ужо маюць API: Kubernetes, AWS, Datadog або Grafana, PagerDuty, Terraform Cloud, GitHub, Confluence і Notion. Кожна з іх можа быць падключаная да Claude праз MCP. Калі гэта здабыта, больш не трэба пераходзіць з аднаго інструменту на іншы, каб скарыстацца інформацыяй. Работа прымыкае да стварэння запытаў.
Какі команды вікорыстоўваюць серверы MCP
- Пытанні пра кластэры. Калі запытаецца, якія рэлізы працуюць адзін за іншым прынаймні 30 дзён без апдэйтаў, Claude адправляе запыт на сервер Kubernetes MCP, які запытае кластэр і вяртае адпаведны адказ. Не патрэбны каманды kubectl і копіюванне-выкліканне.
- Пытанні пра вітыкі. Калі запытаецца, якія службы AWS паказалі рост выкарыстанняя ў гэты тыдзень у пораўнанні з пылейшнім, Claude адправляе запыт на сервер AWS і Cost Explorer, а адказ даёцца на простай англійскай мове.
- Кантэкст інцыдэтаў. Пытанне пра інцыдэты на серверах PagerDuty за апошнія 24 гадзіны і пра тое, чыя з іх яшчэ не заканчыліся, выкарыстоўвае інформацыю з сервера PagerDuty і стварае ўзагальнення.
- Пошук інструкцый. Запыт пра інструкцыі па рашэнню проблемы выкарыстання пула з’яносоў да базы дадзенаў выкарыстоўвае сервер Confluence для пошуку і вяртае самэй дакумент.
Тры відменнікі сервераў
Команды, якія запускаюць праекты, зазвычай ствараюць тры відменнікі сервераў.
Серверы для спаглядання толькі для чытання
Эты серверы налажваюць зв’язак між Claude і API для монітарынгу і інфраструктуры, ўнаследке чаго Claude можа атрыбутаваць тэкушчы стан рэштаў. Тыповыя прыклады — сервер стану кластэра Kubernetes, сервер інвентарызаціі AWS, сервер метрык Datadog і сервер логаў CloudWatch. Рызык вельмі нізкі, таму што Claude можа толькі чытаць. Гэта лепшы пачатак, які дапамагае стварыць довер’е пры будучым наданні прав на збірку даных.
Серверы базы знанняй
Этыя наёмы з’яўляюць Воблака з внутрашняя дакументацыяю для пошуку і адзысквання: сервер з кантэнтамі у фармаце Confluence або Notion, сервер wiki у GitHub, папка з маркдаунамі на месцачыце або база дадзеных з запісамі прынятых архітэктурных рашэнняў. Рызык практычна стоіць нуля, адколі гэта ўсё пошук унітараў. Яны важны, таму што дапамагаюць Воблаку адчуваць, што ён сапраўды знае компанію.
Серверы дзеянняў
Этыя дазваляюць Воблаку выкананы такія задачы, як стварэнне тыкетаў, запуск пайплайнаў або перзапуск служб. Прыклады включаюць стварэнне тыкетаў у Jira, кераванне інцыдэтамі у PagerDuty, стварэнне запрошэнняў да з’еднання ў GitHub і паведамленні ў Slack. Рызык колічыцца ад сяродньага да высокага, таму што Воблак цяпер зменяе ўсё. Апраўдзенні завжды павінны быць перад кожным запісам, тады перзапуск пада ніколі не адбываецца без падтверджэння.
Стварэнне сервера MCP для Kubernetes
Далей паказвана працюючая сервера Kubernetes толькі для чытання на Python. Спачатку установіце SDK:
pip install mcp kubernetes --break-system-packages
Пасуйце тады сервер пад названне k8s_mcp_server.py:
import asyncio
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp import types
from kubernetes import client, config as k8s_config
# Load kubeconfig
try:
k8s_config.load_incluster_config()
except:
k8s_config.load_kube_config()
v1 = client.CoreV1Api()
apps_v1 = client.AppsV1Api()
# Create MCP server
app = Server("k8s-devops-server")
@app.list_tools()
async def list_tools() -> list[types.Tool]:
"""Tell Claude what tools are available."""
return [
types.Tool(
name="get_pods",
description="Get all pods in a namespace with their status, restarts, and age.",
inputSchema={
"type": "object",
"properties": {
"namespace": {
"type": "string",
"description": "Kubernetes namespace (e.g. production, staging)"
}
},
"required": ["namespace"]
}
),
types.Tool(
name="get_pod_logs",
description="Get recent logs from a pod or deployment.",
inputSchema={
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Pod or deployment name"
},
"namespace": {
"type": "string",
"description": "Kubernetes namespace"
},
"lines": {
"type": "integer",
"description": "Number of log lines to return (default 50)"
}
},
"required": ["name", "namespace"]
}
),
types.Tool(
name="get_deployments",
description="List all deployments with replica counts and status.",
inputSchema={
"type": "object",
"properties": {
"namespace": {
"type": "string",
"description": "Kubernetes namespace"
}
},
"required": ["namespace"]
}
),
types.Tool(
name="get_events",
description="Get recent Kubernetes events. Useful for diagnosing issues.",
inputSchema={
"type": "object",
"properties": {
"namespace": {
"type": "string",
"description": "Kubernetes namespace"
}
},
"required": ["namespace"]
}
),
]
@app.call_tool()
async def call_tool(name: str, arguments: dict) -> list[types.TextContent]:
"""Handle tool calls from Claude."""
if name == "get_pods":
namespace = arguments["namespace"]
pods = v1.list_namespaced_pod(namespace=namespace)
lines = [f"Pods in {namespace}:\n"]
for pod in pods.items:
phase = pod.status.phase
restarts = sum(
cs.restart_count
for cs in (pod.status.container_statuses or [])
)
name_str = pod.metadata.name
lines.append(f" {name_str}: {phase} | restarts: {restarts}")
return [types.TextContent(type="text", text="\n".join(lines))]
elif name == "get_pod_logs":
pod_name = arguments["name"]
namespace = arguments["namespace"]
lines = arguments.get("lines", 50)
import subprocess
result = subprocess.run(
f"kubectl logs {pod_name} -n {namespace} --tail={lines}",
shell=True, capture_output=True, text=True
)
output = result.stdout or result.stderr or "No logs found"
return [types.TextContent(type="text", text=output)]
elif name == "get_deployments":
namespace = arguments["namespace"]
deployments = apps_v1.list_namespaced_deployment(namespace=namespace)
lines = [f"Deployments in {namespace}:\n"]
for d in deployments.items:
desired = d.spec.replicas or 0
available = d.status.available_replicas or 0
status = "✅" if desired == available else "⚠️"
lines.append(
f" {status} {d.metadata.name}: {available}/{desired} replicas"
)
return [types.TextContent(type="text", text="\n".join(lines))]
elif name == "get_events":
namespace = arguments["namespace"]
events = v1.list_namespaced_event(namespace=namespace)
# Sort by last timestamp, show recent ones
sorted_events = sorted(
events.items,
key=lambda e: e.last_timestamp or e.event_time,
reverse=True
)[:20]
lines = [f"Recent events in {namespace}:\n"]
for e in sorted_events:
lines.append(
f" [{e.type}] {e.reason}: {e.message[:100]}"
)
return [types.TextContent(type="text", text="\n".join(lines))]
return [types.TextContent(type="text", text=f"Unknown tool: {name}")]
async def main():
async with stdio_server() as (read_stream, write_stream):
await app.run(read_stream, write_stream, app.create_initialization_options())
if __name__ == "__main__":
asyncio.run(main())
Ёнкі яго з’яўляць у Claude Desktop, трэба зменіць файл налаштавання, які знаходзіцца па аднам з этых шляхоў:
Mac: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
і дадзіце запіс сервера:
{
"mcpServers": {
"kubernetes": {
"command": "python",
"args": ["/path/to/k8s_mcp_server.py"]
}
}
}
Пачатакуйце занова Claude Desktop, і ён будзе гатовы. Калі запытаць, сколькі падов працуе ў працэйнай асяроддзя, Claude фактычна пераканаецца ў гэтым.
Стварэнне сервера з інструкцыямі
Гэты элемент можа быць ўсё болей корыстным. Ён паказвае Claude інструкцыі команды, таму пад час інцыдэту Claude можа знайсці правільную інструкцыю замест таго, каб хтось ручна шукаў у Confluence.
import asyncio
import os
import glob
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp import types
app = Server("runbook-server")
RUNBOOKS_PATH = os.path.expanduser("~/runbooks") # point to your runbooks folder
def load_all_runbooks() -> dict[str, str]:
"""Load all markdown runbooks from the folder."""
runbooks = {}
for filepath in glob.glob(f"{RUNBOOKS_PATH}/**/*.md", recursive=True):
with open(filepath, 'r', errors='replace') as f:
content = f.read()
name = os.path.relpath(filepath, RUNBOOKS_PATH)
runbooks[name] = content
return runbooks
@app.list_tools()
async def list_tools() -> list[types.Tool]:
return [
types.Tool(
name="search_runbooks",
description=(
"Search your team's runbooks for a specific topic, service, or error. "
"Use this when someone asks about a procedure, a known issue, "
"or how to fix something."
),
inputSchema={
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "What to search for (e.g. 'database connection pool', 'nginx 502', 'SSL cert renewal')"
}
},
"required": ["query"]
}
),
types.Tool(
name="list_runbooks",
description="List all available runbooks by category.",
inputSchema={
"type": "object",
"properties": {}
}
),
types.Tool(
name="get_runbook",
description="Get the full content of a specific runbook by name.",
inputSchema={
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Runbook filename (from list_runbooks)"
}
},
"required": ["name"]
}
)
]
@app.call_tool()
async def call_tool(name: str, arguments: dict) -> list[types.TextContent]:
runbooks = load_all_runbooks()
if name == "list_runbooks":
names = sorted(runbooks.keys())
output = "Available runbooks:\n" + "\n".join(f" - {n}" for n in names)
return [types.TextContent(type="text", text=output)]
elif name == "search_runbooks":
query = arguments["query"].lower()
matches = []
for rb_name, content in runbooks.items():
if query in content.lower() or query in rb_name.lower():
# Return first 500 chars as preview
preview = content[:500].strip()
matches.append(f"📄 {rb_name}\n{preview}\n...")
if not matches:
return [types.TextContent(
type="text",
text=f"No runbooks found for '{query}'"
)]
return [types.TextContent(
type="text",
text=f"Found {len(matches)} runbook(s):\n\n" + "\n\n---\n\n".join(matches)
)]
elif name == "get_runbook":
rb_name = arguments["name"]
content = runbooks.get(rb_name)
if not content:
return [types.TextContent(type="text", text=f"Runbook not found: {rb_name}")]
return [types.TextContent(type="text", text=content)]
return [types.TextContent(type="text", text=f"Unknown tool: {name}")]
async def main():
async with stdio_server() as (read_stream, write_stream):
await app.run(read_stream, write_stream, app.create_initialization_options())
if __name__ == "__main__":
asyncio.run(main())
Дадзіце яго ў настройкі Claude Desktop разам з іншым серверам:
{
"mcpServers": {
"kubernetes": {
"command": "python",
"args": ["/path/to/k8s_mcp_server.py"]
},
"runbooks": {
"command": "python",
"args": ["/path/to/runbook_mcp_server.py"]
}
}
}
Пасля чаго запіт на кшталт "Які інструкцыі для высокага выкарыстання памяці ў API-кантэйнерах?" вяртае сабе власныя інструкцыі команды, а не загальны рэзультат пошуку.
Серверы, якія вялікі ўжо
Не трэба ўсё ствараць з нуля. Oficыяльны зборак сервераў-праменяў на GitHub, пад організацыяй modelcontextprotocol, абягае GitHub (рэпазітарыі, запросы прыўязкі, проблемы і зберэжэнні), Postgres, Slack, пошук у базе ведаў AWS, доступ да локальнай файловай сістэмы і пошук у Brave. Існуюць серверы, створаныя спяльнайясцю, для Datadog (мэтрыкі, панелі і манітары), PagerDuty (інцыдэнты і апавешчэнні) і Jira (заявкі і спрынты). Цікава будзе спачатку пераглянуць гэты зборак, таму што хтось можа ўжо стварыць тое, што трэба.
Памылкі, якіх трэба ухіліцца
- Занадто раннее наданне прав на запіс. Пачатакавайце толькі з рэжыму чытання. Калі будзе з’явіцца довер’е, паштоўна дадавайце інструменты для запісу по аднаму.
- Стварэнне адного велікага сервера. Маленькія, спецыялізаваныя серверы лёгкія для тыпавання, дыягностыкі і перэдачы конкрэтным адамам.
k8s-serverпавінен хаваць толькі інструменты Kubernetes,aws-server— толькі інструменты AWS, аrunbook-server— толькі дакументы. - Ігнораванне логавання. Зявляйце логі кожнага вызову інструмента, укладаючы ў яны тое, што запытаў Claude, калі і што было павернута, асобліва да таго часу, пакуль не будуць даданы інструменты для запісу.
- Ігнораванне празраджэнняя для запісу. Кожны акт, які стварае заявку, пачынае працюванне службы або з’еднае праглас, трэба падтвердзіць, пры чым Claude спачатку павінен паказаць, што ён збіраецца зрабіць.
Ранак з правільным налаштаваннем
Тыповая сесія пачынаецца з запытку пра стан вырабатчыка. Claude перакантролюе сервер Kubernetes і дае інфармацыю пра размешчэнні працоўных процэсаў і падов, пазначае пад, якій пастаюць паўтаральныя перэзапускі, а пасля прымае заходы ў зв’язку з гэтым проблемам.
You: What's the state of production right now?
Claude: [checks kubernetes MCP server]
3 deployments all healthy, 47/47 pods running.
One pod in payments namespace has 8 restarts - api-worker-6d4f9b.
Everything else looks stable.
You: Why is that pod restarting?
Claude: [checks pod logs via MCP]
Logs show OOMKilled. Memory limit is 256Mi but it's hitting
248Mi regularly. Looks like it needs a bump to at least 512Mi.
Want me to check if we have a runbook for this?
You: Yes
Claude: [searches runbook MCP server]
Found it - "memory-limit-tuning.md"
The runbook says: increase limit in Helm values,
run helm upgrade, monitor for 10 minutes.
Last updated by Rahul on March 12th.
You: What did our AWS bill look like this week?
Claude: [checks AWS MCP server]
$4,823 this week vs $4,210 last week - up 14.5%.
Spike is from EC2 in us-east-1. Looks like
3 r6g.2xlarge instances were added on Tuesday.
Весь гэты працэс займае апошнія 90 секунд, без пераключэння вікнаў, без копіювання-выклікання і без пошуку.
Пачынаем з гэтага тыжня
Стварэнне пяці сервераў адразу — глытак. Выберыце адзін. Для большасці команд DevOps найлепым першым выборам являецца сервер з інструкцыямі, таму што ён ў рэжыме толькі чытання, негаючы карысць адразу і працюючы з усіма існуючымі дакументамі. Пачатак адбываецца за тры крокі:
- Зберыце інструкцыі команды ў адну папку, напрыклад
~/runbooks/. - Взяце код сервера з інструкцыямі, як паказана вышэй, і націсніце яго на тую папку.
- Дадзіце яго ў настройкі Claude Desktop і перазапусціце.
Гэта дае асістэнта, які знае процедуры команды. Калі ён павярнёўся надзеям, дадзіце сервер Kubernetes, потым AWS, а потым усё, што будзе далей.
Большая картына
MCP яшчэ молады, а яго экасістэма быстра расце, але калькі рэчы ужо ясны. Команды, якія выкарыстоўваюць серверы MCP, маюць значна іншы досвід работы з AI, чым тыя, якія іх не выкарыстоўваюць. Чым перайсці з вікна чату да чагосьць, што функцыонуе як колега-адміністратар, ёсць адна рэч — сервер, які адкрывае доступ да правільных сістэм. А команды, якія зараз ствараюць такія рашэнні, задаюць прыклад таго, як AI будзе выкарыстоўвана у працы з інфраструктурой. Цэў не доследні праект. Команды вжо запускаюць іх у працэйнай асяроддзі, а вышэўказаны сервер Kubernetes можа запрацаваць за апошнія 20 хвілін.
Спадневана літэратура
- Асаблівы сервер MCP, які дазваляе Claude шукаць інструкцыі вашай команды — індэксаванне markdown-інструкцый і аналіза падарэжных сітуацый у ChromaDB, адкрыцце можлівасці ўсмысловага пошуку праз сервер MCP і дазвол к Claude знаходзіць процедуры рашэння інцыдэнтав за секунды.
- Практычныя прыметкі: kagent — фрэймворк AI-агента, створаны спецыяльна для Kubernetes, які вам трэба — паследовыя інструкцыі па вікорыстоўванні фрэймворка kagent: контракты, перакананні і шаблоны коду для команд, якія впрыменяюць гэты падход.