yaml-mcp-server

module
v0.0.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 4, 2026 License: MIT

README

yaml-mcp-server logo

yaml-mcp-server

🔐 MCP‑gateway с декларативными инструментами из YAML и системой аппруверов для безопасных действий модели.

Go Version Go Reference

🇬🇧 English version: README_EN.md

yaml-mcp-server — единый MCP‑сервер в кластере, который читает YAML‑DSL с описанием ресурсов и инструментов, подключает цепочки аппруверов и возвращает модели строго структурированные ответы.

🎯 Идея и мотивация

Задача сервиса — безопасно исполнять «опасные» операции модели (создание секретов, изменения репо/настроек и т.д.) только после явного approval через pluggable‑аппруверы (HTTP/Shell/лимиты).

✅ Ключевые возможности

  • MCP‑сервер (HTTP/stdio) с динамическими инструментами из YAML.
  • Последовательные аппруверы на инструмент: лимиты → shell → HTTP и т.д.
  • Жёсткий контракт ответов для модели: status, decision, reason, correlation_id.
  • Встроенные health endpoints: /healthz, /readyz.
  • Шаблонизация YAML с проверкой всех используемых env до старта.

📦 Установка

Требуется Go >= 1.25.5 (см. go.mod).

go install github.com/codex-k8s/yaml-mcp-server/cmd/yaml-mcp-server@latest

🚀 Быстрый старт

export YAML_MCP_CONFIG=/path/to/config.yaml
export YAML_MCP_LANG=ru
export YAML_MCP_LOG_LEVEL=info

yaml-mcp-server

По умолчанию HTTP‑endpoint MCP: http://localhost:8080/mcp.

🔌 Подключение к Codex (CLI/IDE)

Codex читает конфигурацию MCP из ~/.codex/config.toml, либо из проектного .codex/config.toml (для trusted projects). Есть два способа добавить сервер:

Вариант 1 — через CLI

codex mcp add yaml-mcp-server --url http://localhost:8080/mcp
codex mcp list

После добавления обязательно выставьте tool_timeout_sec в config.toml, чтобы ожидание аппруверов не обрывалось клиентом Codex (таймаут считается в секундах).

Вариант 2 — через config.toml

[mcp_servers.yaml-mcp-server]
url = "http://localhost:8080/mcp"
tool_timeout_sec = 3600

Если сервер развёрнут в кластере, укажите URL ingress/port‑forward и добавьте его тем же способом.

🧩 YAML‑DSL (кратко)

YAML описывает сервер, инструменты и ресурсы. Пример см. в examples/.

Сервер

server:
  name: yaml-mcp-server
  version: "0.1.0"
  transport: "http"   # http | stdio
  shutdown_timeout: "10s"
  startup_hooks:
    - timeout: "10s"
      command: |
        command -v gh >/dev/null
        command -v kubectl >/dev/null
    - timeout: "30s"
      command: |
        printf %s "$CODEXCTL_GH_PAT" | gh auth login --with-token
  http:
    listen: ":8080"
    path: "/mcp"
    read_timeout: "1h"
    write_timeout: "1h"
    idle_timeout: "1h"

Инструмент

tools:
  - name: GitHubSecretCreatorInK8s
    title: "Create GitHub secret and K8s secret"
    description: |
      Creates a GitHub environment secret and injects it into Kubernetes after approval.
      Input fields:
      - repo: repository in "owner/name" format.
      - secret_name: secret name (uppercase, digits, underscores).
      - environment: target environment, allowed values: ai-staging or staging.
      - namespace: Kubernetes namespace for secret injection.
      - k8s_secret_name: Kubernetes Secret name (kebab-case).
      - justification: required; write in Russian.
      The secret value is generated by the server, do NOT provide secret_value.
    requires_approval: true
    timeout: "1h"
    timeout_message: "approval timeout"
    input_schema:
      type: object
      additionalProperties: false
      required: ["repo", "secret_name", "environment", "namespace", "k8s_secret_name", "justification"]
      properties:
        repo: { type: string }
        secret_name: { type: string, pattern: "^[A-Z0-9_]+$" }
        environment: { type: string, enum: ["ai-staging", "staging"] }
        namespace: { type: string, pattern: "^[a-z0-9]([-a-z0-9]*[a-z0-9])?$" } # DNS-1123
        k8s_secret_name: { type: string, pattern: "^[a-z0-9]([-a-z0-9]*[a-z0-9])?$" } # DNS-1123
        justification: { type: string }
    approvers:
      - type: limits
        fields:
          secret_name: { regex: "^[A-Z0-9_]+$" }
          environment: { regex: "^(ai-staging|staging)$" }
          namespace: { regex: "^[a-z0-9]([-a-z0-9]*[a-z0-9])?$" }
          k8s_secret_name: { regex: "^[a-z0-9]([-a-z0-9]*[a-z0-9])?$" }
      - type: shell
        timeout: "1m"
        command: |
          if gh secret list -R {{ .Args.repo }} | awk '{print $1}' | grep -qx "{{ .Args.secret_name }}"; then
            echo "secret already exists"; exit 1; fi
    executor:
      type: shell
      timeout: "1h"
      command: |
        secret_value="$(head -c 32 /dev/urandom | base64)"
        gh api -X PUT "repos/{{ .Args.repo }}/environments/{{ .Args.environment }}" >/dev/null
        gh secret set {{ .Args.secret_name }} -R {{ .Args.repo }} --env {{ .Args.environment }} --body "$secret_value"
        kubectl -n {{ .Args.namespace }} create secret generic {{ .Args.k8s_secret_name }} \
          --from-literal={{ .Args.secret_name }}="$secret_value" \
          --dry-run=client -o yaml | kubectl apply -f -
        echo "secret {{ .Args.secret_name }} created in {{ .Args.repo }} env {{ .Args.environment }} and injected into {{ .Args.namespace }}/{{ .Args.k8s_secret_name }}"

Ресурсы

resources:
  - name: Welcome
    uri: static:welcome
    description: Welcome message
    mime_type: text/plain
    text: "Hello from yaml-mcp-server"

🔄 Пример сквозного флоу для БД (GitHubSecretCreatorInK8s → PsqlDbCreatorInK8s)

  1. Модель запрашивает создание секрета с именем, например PG_USER и PG_PASSWORD через GitHubSecretCreatorInK8s. Секреты создаются в GitHub и сразу инъектятся в Kubernetes в заданный namespace.
  2. Модель вызывает PsqlDbCreatorInK8s, передавая только имена секретов и ключей:
    • k8s_pg_user_secret_name / pg_user_secret_name
    • k8s_pg_password_secret_name / pg_password_secret_name
  3. Инструмент сам читает значения из K8s secrets и создаёт БД внутри PostgreSQL Pod.

Преимущества подхода

  • Модель не видит секреты, но может запускать согласованный автоматизированный процесс.
  • Секреты сразу доступны сервисам через Kubernetes Secret.
  • Единая цепочка аппруверов и аудит — весь поток проходит через yaml-mcp-server.

Пример запроса для PsqlDbCreatorInK8s

{
  "correlation_id": "corr-...",
  "tool": "PsqlDbCreatorInK8s",
  "arguments": {
    "namespace": "project-ai-staging",
    "db_name": "billing",
    "k8s_pg_user_secret_name": "db-credentials",
    "pg_user_secret_name": "PG_USER",
    "k8s_pg_password_secret_name": "db-credentials",
    "pg_password_secret_name": "PG_PASSWORD",
    "justification": "Нужна новая БД для сервиса billing"
  }
}

Пример ответа

{
  "status": "success",
  "decision": "approve",
  "reason": "database billing created in namespace project-ai-staging",
  "correlation_id": "corr-..."
}

🧪 Аппруверы

Поддерживаются:

  • limits — лимиты/валидации полей (regex, min/max, min/max length).
  • shell — approval по результату shell‑команды.
  • http — approval через внешний HTTP‑сервис.

Порядок строго как в YAML. На первом deny цепочка прерывается.

HTTP‑approver: формат запроса

{
  "correlation_id": "corr-...",
  "tool": "GitHubSecretCreatorInK8s",
  "arguments": {
    "secret_name": "POSTGRES_PASSWORD",
    "environment": "ai-staging",
    "namespace": "project-ai-staging",
    "k8s_secret_name": "db-credentials"
  }
}

HTTP‑approver: формат ответа

{ "decision": "approve", "reason": "ok" }

decision принимает ровно: approve | deny | error.

📡 Протокол ответов инструмента

{
  "status": "success|denied|error",
  "decision": "approve|deny|error",
  "reason": "secret POSTGRES_PASSWORD created in owner/repo env ai-staging and injected into project-ai-staging/db-credentials",
  "correlation_id": "corr-..."
}

🔧 Шаблонизация YAML

Поддерживаемые функции:

  • env, envOr, default, ternary, join, lower, upper, trimPrefix, trimSuffix, replace.

Сервер проверяет, что все используемые env переменные заданы до старта.

❤️ Health endpoints

  • GET /healthz — liveness
  • GET /readyz — readiness

⚙️ Переменные окружения

  • YAML_MCP_CONFIG — путь к YAML конфигу (по умолчанию config.yaml).
  • YAML_MCP_LOG_LEVELdebug|info|warn|error.
  • YAML_MCP_LANGen (default) или ru.
  • YAML_MCP_SHUTDOWN_TIMEOUT — таймаут graceful shutdown.

📄 Примеры

  • examples/combined_tools_shell_http.yaml (содержит два инструмента: GitHubSecretCreatorInK8s и PsqlDbCreatorInK8s)

🧷 Заметки по безопасности

yaml-mcp-server — это универсальный MCP‑gateway, который изолирует опасные действия от модели и даёт выполнять их только через явный approval. Пример с GitHub‑secret — лишь демонстрация подхода: модель не знает токенов и значений, но может инициировать создание через утверждённый поток.

Пока нет встроенного разграничения прав доступа. Поэтому сервис должен работать либо локально, либо в кластере с жёстким сетевым ограничением доступа к yaml-mcp-server.

Directories

Path Synopsis
cmd
yaml-mcp-server command
internal
app
Package app wires the HTTP server lifecycle and graceful shutdown.
Package app wires the HTTP server lifecycle and graceful shutdown.
approver/http
Package http implements an HTTP-based approver client.
Package http implements an HTTP-based approver client.
approver/limits
Package limits provides rate and field validation approvers.
Package limits provides rate and field validation approvers.
approver/shell
Package shell implements a shell-based approver.
Package shell implements a shell-based approver.
audit
Package audit records approval and tool execution events.
Package audit records approval and tool execution events.
config
Package config loads server configuration from environment variables.
Package config loads server configuration from environment variables.
constants
Package constants defines shared string constants used across the server.
Package constants defines shared string constants used across the server.
dsl
Package dsl defines the YAML configuration schema for the server.
Package dsl defines the YAML configuration schema for the server.
executil
Package executil provides helpers for templated shell execution.
Package executil provides helpers for templated shell execution.
http/health
Package health provides liveness and readiness HTTP handlers.
Package health provides liveness and readiness HTTP handlers.
log
Package log provides structured logging helpers.
Package log provides structured logging helpers.
protocol
Package protocol defines fixed response formats and decision constants.
Package protocol defines fixed response formats and decision constants.
render
Package render provides YAML template rendering helpers.
Package render provides YAML template rendering helpers.
runtime
Package runtime builds MCP resources and tools from the YAML DSL.
Package runtime builds MCP resources and tools from the YAML DSL.
runtime/approver
Package approver defines interfaces for approval checks.
Package approver defines interfaces for approval checks.
runtime/executor
Package executor implements tool execution backends.
Package executor implements tool execution backends.
security
Package security provides helpers for redacting sensitive values.
Package security provides helpers for redacting sensitive values.
startup
Package startup runs one-time startup hooks.
Package startup runs one-time startup hooks.
templates
Package templates provides localized message templates for runtime errors.
Package templates provides localized message templates for runtime errors.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL