Files
Maksim Totmin 1c7242d5c5
ci / test (push) Successful in 2m12s
ci / lint (push) Successful in 4m21s
Переименование Go-модуля в omnichannel-configserver-mcp
2026-10-07 20:14:40 +07:00

119 lines
5.0 KiB
Go

package tools
import (
"context"
"omnichannel-configserver-mcp/internal/configserver"
"github.com/modelcontextprotocol/go-sdk/mcp"
)
// release.go — страница «Развёртывание»: файлы схемы, seed/fill, релиз.
func registerReleaseTools(s *mcp.Server) {
addPatternTool(s, &mcp.Tool{
Name: "save_deployment_files",
Description: "Сохранить файлы развёртывания (schema/manifest/prebuild_vars/ip_overrides). Передавай только изменяемые поля.",
InputSchema: schema(map[string]any{
"server": serverProp(),
"schema": strProps("JSON-схема развёртывания (опционально)", false),
"manifest": strProps("JSON-манифест (опционально)", false),
"prebuild_vars": strProps("Строка prebuild_vars (опционально)", false),
"ip_overrides": strProps("JSON ip_overrides (опционально)", false),
}, nil),
}, releasePatterns, func(ctx context.Context, req *mcp.CallToolRequest) (*mcp.CallToolResult, error) {
args := requestArgs(req)
upd := configserver.DeploymentUpdate{
Schema: optionalString(args, "schema"),
Manifest: optionalString(args, "manifest"),
PrebuildVars: optionalString(args, "prebuild_vars"),
IPOverrides: optionalString(args, "ip_overrides"),
}
if upd.Schema == nil && upd.Manifest == nil && upd.PrebuildVars == nil && upd.IPOverrides == nil {
return errorResult("нужно передать хотя бы одно из полей: schema, manifest, prebuild_vars, ip_overrides"), nil
}
api, res := openAPI(ctx, args, true)
if res != nil {
return res, nil
}
defer api.Close()
return result(api.SaveDeploymentFiles(ctx, upd))
})
addPatternTool(s, &mcp.Tool{
Name: "seed_hosts",
Description: "Создать служебные записи хостов по IP из schema.json. Изменяет БД.",
InputSchema: schema(map[string]any{"server": serverProp()}, nil),
}, releasePatterns, func(ctx context.Context, req *mcp.CallToolRequest) (*mcp.CallToolResult, error) {
args := requestArgs(req)
api, res := openAPI(ctx, args, true)
if res != nil {
return res, nil
}
defer api.Close()
return result(api.SeedHosts(ctx))
})
addPatternTool(s, &mcp.Tool{
Name: "fill_vars",
Description: "Заполнить prebuild_vars из schema.json. Изменяет файл конфигурации развёртывания.",
InputSchema: schema(map[string]any{"server": serverProp()}, nil),
}, releasePatterns, func(ctx context.Context, req *mcp.CallToolRequest) (*mcp.CallToolResult, error) {
args := requestArgs(req)
api, res := openAPI(ctx, args, true)
if res != nil {
return res, nil
}
defer api.Close()
v, err := api.FillVars(ctx)
return result(v, err)
})
addPatternTool(s, &mcp.Tool{
Name: "download_release",
Description: "Загрузить релиз. load_images=false — синхронно (пакеты + sync-задачи); true — фоновая загрузка образов (прогресс через release_job). Разрушительно/тяжело: требует confirm=\"true\".",
InputSchema: schema(map[string]any{
"server": serverProp(),
"load_images": boolProps("Загружать docker-образы в фоне (по умолчанию false)", false),
"gitlab_token": strProps("GitLab-токен (опционально; иначе из конфига/env сервера)", false),
"confirm": boolProps("Подтверждение операции (обязательно true)", true),
}, []string{"confirm"}),
}, releasePatterns, func(ctx context.Context, req *mcp.CallToolRequest) (*mcp.CallToolResult, error) {
args := requestArgs(req)
if res := confirmGate(args, "download_release"); res != nil {
return res, nil
}
api, res := openAPI(ctx, args, true)
if res != nil {
return res, nil
}
defer api.Close()
ack, err := api.DownloadRelease(ctx, getString(args, "gitlab_token", ""), getBool(args, "load_images", false))
return result(ack, err)
})
addPatternTool(s, &mcp.Tool{
Name: "start_services",
Description: "Создать задачи запуска сервисов для хостов из schema.json. Изменяет состояние стенда.",
InputSchema: schema(map[string]any{"server": serverProp()}, nil),
}, releasePatterns, func(ctx context.Context, req *mcp.CallToolRequest) (*mcp.CallToolResult, error) {
args := requestArgs(req)
api, res := openAPI(ctx, args, true)
if res != nil {
return res, nil
}
defer api.Close()
return result(api.StartServices(ctx))
})
}
// optionalString возвращает указатель на строковый аргумент, если он задан
// (в том числе пустой строкой), иначе nil.
func optionalString(args map[string]any, key string) *string {
if _, ok := args[key]; !ok {
return nil
}
v := getString(args, key, "")
return &v
}