nginx-ui/mcp/config/config_modify.go
2025-04-29 17:41:09 +08:00

96 lines
2.7 KiB
Go

package config
import (
"context"
"encoding/json"
"errors"
"path/filepath"
"github.com/0xJacky/Nginx-UI/internal/config"
"github.com/0xJacky/Nginx-UI/internal/helper"
"github.com/0xJacky/Nginx-UI/internal/nginx"
"github.com/0xJacky/Nginx-UI/model"
"github.com/0xJacky/Nginx-UI/query"
"github.com/mark3labs/mcp-go/mcp"
"gorm.io/gen/field"
)
const nginxConfigModifyToolName = "nginx_config_modify"
// ErrFileNotFound is returned when a file is not found
var ErrFileNotFound = errors.New("file not found")
var nginxConfigModifyTool = mcp.NewTool(
nginxConfigModifyToolName,
mcp.WithDescription("Modify an existing Nginx configuration file"),
mcp.WithString("relative_path", mcp.Description("The relative path to the configuration file")),
mcp.WithString("content", mcp.Description("The new content of the configuration file")),
mcp.WithBoolean("sync_overwrite", mcp.Description("Whether to overwrite existing files when syncing")),
mcp.WithArray("sync_node_ids", mcp.Description("IDs of nodes to sync the configuration to")),
)
func handleNginxConfigModify(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
args := request.Params.Arguments
relativePath := args["relative_path"].(string)
content := args["content"].(string)
syncOverwrite := args["sync_overwrite"].(bool)
// Convert sync_node_ids from []interface{} to []uint64
syncNodeIdsInterface, ok := args["sync_node_ids"].([]interface{})
syncNodeIds := make([]uint64, 0)
if ok {
for _, id := range syncNodeIdsInterface {
if idFloat, ok := id.(float64); ok {
syncNodeIds = append(syncNodeIds, uint64(idFloat))
}
}
}
absPath := nginx.GetConfPath(relativePath)
if !helper.IsUnderDirectory(absPath, nginx.GetConfPath()) {
return nil, config.ErrPathIsNotUnderTheNginxConfDir
}
if !helper.FileExists(absPath) {
return nil, ErrFileNotFound
}
q := query.Config
cfg, err := q.Assign(field.Attrs(&model.Config{
Filepath: absPath,
})).Where(q.Filepath.Eq(absPath)).FirstOrCreate()
if err != nil {
return nil, err
}
// Update database record
_, err = q.Where(q.Filepath.Eq(absPath)).
Select(q.SyncNodeIds, q.SyncOverwrite).
Updates(&model.Config{
SyncNodeIds: syncNodeIds,
SyncOverwrite: syncOverwrite,
})
if err != nil {
return nil, err
}
cfg.SyncNodeIds = syncNodeIds
cfg.SyncOverwrite = syncOverwrite
err = config.Save(absPath, content, cfg)
if err != nil {
return nil, err
}
result := map[string]interface{}{
"name": filepath.Base(absPath),
"content": content,
"file_path": absPath,
"dir": filepath.Dir(relativePath),
"sync_node_ids": cfg.SyncNodeIds,
"sync_overwrite": cfg.SyncOverwrite,
}
jsonResult, _ := json.Marshal(result)
return mcp.NewToolResultText(string(jsonResult)), nil
}